I have written a handler and a function to send watermark response back. But some how the image changes to read only.
I have disposed all the object.
The codes are as below:
public void ProcessRequest(HttpContext context)
{
var imagePath = QueryString.getValueOf("ID");
var watermark = QueryString.getValueOf("watermark");
context.Response.ContentType = "image/jpeg";
if (string.IsNullOrWhiteSpace(imagePath) || string.IsNullOrWhiteSpace(watermark))
{
var originalImage = Image.FromFile(context.Server.MapPath("Images/NoImage.jpg"));
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
originalImage.Dispose();
}
else
{
if (watermark == "0")
{
var absolutePath = context.Server.MapPath(imagePath);
var fileexist = System.IO.File.Exists(absolutePath);
if (fileexist)
{
var originalImage = Image.FromFile(absolutePath);
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
originalImage.Dispose();
}
else
{
var originalImage = Image.FromFile(context.Server.MapPath("Images/NoImage.jpg"));
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
originalImage.Dispose();
}
}
else
{
if (imagePath.ToUpper().Contains(".GIF"))
{
var absolutePath = context.Server.MapPath(imagePath);
var fileexist = System.IO.File.Exists(absolutePath);
if (fileexist)
{
var originalImage = Image.FromFile(absolutePath);
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
originalImage.Dispose();
}
else
{
var originalImage = Image.FromFile(context.Server.MapPath("Images/NoImage.jpg"));
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
originalImage.Dispose();
}
}
else
{
var absolutePath = context.Server.MapPath(imagePath);
var fileexist = System.IO.File.Exists(absolutePath);
if (fileexist)
{
var originalImage = Image.FromFile(absolutePath);
originalImage = new ImageMethods().AddWatermarkText(originalImage);
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
originalImage.Dispose();
}
else
{
var originalImage = Image.FromFile(context.Server.MapPath("Images/NoImage.jpg"));
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
originalImage.Dispose();
}
}
}
}
}
and the function is to writing images is as follows
public Image AddWatermarkText(Image img)
{
try
{
var textOnImage = ConfigurationManager.AppSettings["textOnImage"];
var opacity = Int32.Parse(ConfigurationManager.AppSettings["opicity"]);
var red = Int32.Parse(ConfigurationManager.AppSettings["red"]);
var green = Int32.Parse(ConfigurationManager.AppSettings["green"]);
var blue = Int32.Parse(ConfigurationManager.AppSettings["blue"]);
var fontSize = Int32.Parse(ConfigurationManager.AppSettings["fontSize"]);
var fontName = ConfigurationManager.AppSettings["fontName"];
var lobFromImage = Graphics.FromImage(img);
var lobFont = new Font(fontName, fontSize, FontStyle.Regular);
var lintTextHw = lobFromImage.MeasureString(textOnImage, lobFont);
var lintTextOnImageWidth = (int)lintTextHw.Width;
var lintTextOnImageHeight = (int)lintTextHw.Height;
var lobSolidBrush = new SolidBrush(Color.FromArgb(opacity, Color.FromArgb(red, green, blue)));
var posLeft = (img.Width - lintTextOnImageWidth) / 2;
posLeft = posLeft > 0 ? posLeft : 5;
var lobPoint = new Point(posLeft, (img.Height / 2) - (lintTextOnImageHeight / 2));
// var lobPoint = new Point(RandomNumber(0, img.Width - lintTextOnImageWidth), RandomNumber(0, img.Height - lintTextOnImageHeight));
lobFromImage.DrawString(textOnImage, lobFont, lobSolidBrush, lobPoint);
lobFromImage.Dispose();
lobSolidBrush.Dispose();
lobFont.Dispose();
}
catch (Exception ex)
{
HavException = true;
ExceptionMessage = ex.Message;
}
return img;
}
Am I missing something?
if you have an exception before your Dispose call then your images won't be disposed and files will remain locked. You should put calls to Dispose in "finally" section or use "using" like:
using (var originalImage = Image.FromFile(absolutePath))
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
Also to avoid locking you can read file to stream first and then create image from stream
using(var imageStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
return Image.FromStream(imageStream );
I solved my problem. I don't know why it worked but it is working.
public void ProcessRequest(HttpContext context)
{
var imagePath = QueryString.getValueOf("ID");
var watermark = QueryString.getValueOf("watermark");
string lstrResponseType;
// context.Response.ContentType = "image/jpeg";
if (string.IsNullOrWhiteSpace(imagePath) || string.IsNullOrWhiteSpace(watermark))
{
using (var originalImage = Image.FromFile(context.Server.MapPath("Images/NoImage.jpg")))
{
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
originalImage.Dispose();
}
lstrResponseType = "image/jpeg";
}
else
{
var absolutePath = context.Server.MapPath(imagePath);
var fileexist = System.IO.File.Exists(absolutePath);
if (!fileexist)
{
var originalImage = Image.FromFile(context.Server.MapPath("Images/NoImage.jpg"));
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
lstrResponseType = "image/jpeg";
originalImage.Dispose();
}
else
{
using (var originalImage = Image.FromFile(absolutePath))
{
if (watermark == "0")
{
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
lstrResponseType = "image/jpeg";
}
else
{
if (imagePath.ToUpper().Contains(".GIF"))
{
originalImage.Save(context.Response.OutputStream, ImageFormat.Gif);
lstrResponseType = "image/gif";
}
else
{
new ImageMethods().AddWatermarkText(originalImage);
originalImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
lstrResponseType = "image/jpeg";
}
}
}
}
}
context.Response.ContentType = lstrResponseType;
}
Related
I used this code but not getting correct format Image.
give better way to convert pdf to Image using iTextsharp.
FileStream fs = File.OpenRead(ImagePath);
byte[] data = new byte[fs.Length];
fs.Read(data, 0, (int)fs.Length);
List<System.Drawing.Image> ImgList = new List<System.Drawing.Image>();
iTextSharp.text.pdf.RandomAccessFileOrArray RAFObj = null;
iTextSharp.text.pdf.PdfReader PDFReaderObj = null;
iTextSharp.text.pdf.PdfObject PDFObj = null;
iTextSharp.text.pdf.PdfStream PDFStremObj = null;
try
{
RAFObj = new iTextSharp.text.pdf.RandomAccessFileOrArray(data);
PDFReaderObj = new iTextSharp.text.pdf.PdfReader(RAFObj, null);
for (int k = 0; k <= PDFReaderObj.XrefSize - 1; k++)
{
PDFObj = PDFReaderObj.GetPdfObject(k);
if ((PDFObj != null) && PDFObj.IsStream())
{
PDFStremObj = (iTextSharp.text.pdf.PdfStream)PDFObj;
iTextSharp.text.pdf.PdfObject subtype = PDFStremObj.Get(iTextSharp.text.pdf.PdfName.SUBTYPE);
if ((subtype != null) && subtype.ToString() == iTextSharp.text.pdf.PdfName.IMAGE.ToString())
{
byte[] bytes = iTextSharp.text.pdf.PdfReader.GetStreamBytesRaw((iTextSharp.text.pdf.PRStream)PDFStremObj);
if ((bytes != null))
{
try
{
System.IO.MemoryStream MS = new System.IO.MemoryStream(bytes);
MS.Position = 0;
System.Drawing.Image ImgPDF = System.Drawing.Image.FromStream(MS);
ImgList.Add(ImgPDF);
}
catch (Exception ex)
{
}
}
}
}
}
PDFReaderObj.Close();
}
catch (Exception ex) { throw ex; }
}
above coded getting file from ImagePath using FileStream to pdfobject and then memorystream to Image.
I'm trying to resize an image from stream. Getting the error
Value cannot be null.Parameter name: encoder
on the line
System.Drawing.Bitmap fullSizeBitmap = new
System.Drawing.Bitmap(fullsizeImage, new System.Drawing.Size(width,
image_height));
How do I add an encoder here? and I need it to be from the original image
public static FileProperty UploadImage(IFormFile file, string folderPath, string fileName, FileNote note, int image_height)
{
FileProperty property = new FileProperty();
if (file.Length > 0)
{
MemoryStream ms = new MemoryStream();
file.CopyTo(ms);
var fileBytes = ms.ToArray();
MemoryStream inputMemoryStream = new MemoryStream(fileBytes);
System.Drawing.Image fullsizeImage = System.Drawing.Image.FromStream(inputMemoryStream);
int width = (image_height / fullsizeImage.Height) * fullsizeImage.Width;
System.Drawing.Bitmap fullSizeBitmap = new System.Drawing.Bitmap(fullsizeImage, new System.Drawing.Size(width, image_height));
using (var stream = new MemoryStream())
{
fullSizeBitmap.Save(stream, fullSizeBitmap.RawFormat);
using (MemoryStream memoryStream = new MemoryStream(stream.ToArray()))
{
UploadFromStreamAsync(memoryStream);
}
}
property.FileName = fileName;
property.FileExtention = Path.GetExtension(fileName);
property.FileSize = file.Length;
property.FileType = file.ContentType;
property.FileNote = note.ToString();
}
return property;
}
Just use file.OpenReadStream() to read and resize the file, then save the resized bitmap to the MemoryStream and upload.
And instead of using bitmap.RawFormat you can get the uploaded image format using a method as below:
if (file.Length > 0)
{
using(var stream = file.OpenReadStream())
{
var image = Image.FromStream(stream);
int width = (image_height / fullsizeImage.Height) * fullsizeImage.Width;
Bitmap fullSizeBitmap = new Bitmap(fullsizeImage, new Size(width, image_height));
var imgFormat = GetImageFormat(file.FileName);
using(var ms = new MemoryStream())
{
fullSizeBitmap.Save(ms, imgFormat);
UploadFromStreamAsync(ms);
}
}
}
The method to get the image format by file extension:
public ImageFormat GetImageFormat(string fileName)
{
var dotIndex = fileName.LastIndexOf('.');
var ext = fileName.Substring(dotIndex, fileName.Length - dotIndex).ToLower();
switch (ext)
{
case ".bmp": return ImageFormat.Bmp;
case ".emf": return ImageFormat.Emf;
case ".exif": return ImageFormat.Exif;
case ".gif": return ImageFormat.Gif;
case ".icon": return ImageFormat.Icon;
case ".Jpg": return ImageFormat.Jpeg;
case ".Jpeg": return ImageFormat.Jpeg;
case ".png": return ImageFormat.Png;
case ".tiff": return ImageFormat.Tiff;
case ".Wmf": return ImageFormat.Wmf;
default: throw new InvalidDataException("Format not supported");
}
}
If you still need to get the uploaded image encoder info use the below method:
// ext: image extension
using System.Drawing.Imaging;
public static ImageCodecInfo GetEncoderInfo(string ext)
{
return ImageCodecInfo.GetImageEncoders().SingleOrDefault(x => x.FilenameExtension.ToLower().Contains(ext));
}
i need to resize file upload if file is image .
i write the extention for resize that :
public static Image ResizeImage(this Image image, int width, int height)
{
var res = new Bitmap(width, height);
using (var graphic = Graphics.FromImage(res))
{
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;
graphic.DrawImage(image, 0, 0, width, height);
}
return res;
}
and this is Upload Action :
[HttpPost("UploadNewsPic"), DisableRequestSizeLimit]
public IActionResult UploadNewsPic(IFormFile file)
{
if (file.IsImage())
{
}
try
{
if (file.Length > 0)
{
string fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
string fullPath = Path.Combine(_applicationRoot.UploadNewPath(), file.Name);
using (var stream = new FileStream(fullPath, FileMode.Create))
{
file.CopyTo(stream);
}
}
return Ok();
}
catch (Exception e)
{
return BadRequest();
}
}
now my problem is here => my extention just work on type of Image file but type of this file is IFormFile . how can i convert the IFormFile to Image type ?
You should use the Image.FromStream() method to read the stream as an Image:
public async Task<IActionResult> FileUpload(IFormFile file)
{
if (file == null || file.Length == 0)
{
return BadRequest();
}
using (var memoryStream = new MemoryStream())
{
await file.CopyToAsync(memoryStream);
using (var img = Image.FromStream(memoryStream))
{
// TODO: ResizeImage(img, 100, 100);
}
}
}
You need to open file using OpenReadStream and convert into image format. And pass the same to your extension method.
FileDetails fileDetails;
using (var reader = new StreamReader(file.OpenReadStream()))
{
var fileContent = reader.ReadToEnd();
var parsedContentDisposition = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
fileDetails = new FileDetails
{
Filename = parsedContentDisposition.FileName,
Content = fileContent,
ContentType=file.ContentType
};
}
I am running a cron job in C# that takes 200,000 images and convert into 1 bit image. During running this job, sometimes the process crashes (even though I have global try catch), sometimes for some images(not all) it throws OutOfMemoryException and sometimes for some images it it throws A generic error occurred in GDI.
int pageSize = 1000;
for (int pageNumber = 0; pageNumber < 200; pageNumber++)
{
var imageUrls = allIMageUrls.Skip(pageSize * pageNumber).Take(pageSize).ToList();
var counter = 0;
var total = imageUrls.Count;
Logger.Log($"Page Number : {pageNumber}");
var failedImageUrls = new System.Collections.Concurrent.ConcurrentBag<string>();
Parallel.ForEach(imageUrls, imageUrl =>
{
try
{
Interlocked.Increment(ref counter);
var image = _httpService.DownloadImage(imageUrl);
if (image != null && image.Length > 0)
{
var oneBitImage = ConvertToOnebitFaxGroup4(contract);
_httpService.UploadImage(image, oneBitImage);
oneBitImage = null;
image = null;
}
}
catch (Exception ex)
{
failedImageUrls.Add(imageUrl);
Logger.Log(ex);
}
});
This is one time process. I added paging so that when it crashes I can restart from that page instead of start at beginning.
public static class ImageProcessor
{
static ImageCodecInfo _codecInfo;
static EncoderParameters _encoderParameters;
static ImageProcessor()
{
foreach (var codec in ImageCodecInfo.GetImageEncoders())
{
if (codec.MimeType == "image/tiff")
{
_codecInfo = codec;
break;
}
}
_encoderParameters = new EncoderParameters(2);
_encoderParameters.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionCCITT4);
_encoderParameters.Param[1] = new EncoderParameter(Encoder.ColorDepth, (long)1);
}
public static byte[] ConvertToOnebitFaxGroup4(byte[] bytes)
{
using (var memoryStream = new MemoryStream(bytes))
{
var image = Image.FromStream(memoryStream);
var pData = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, pData, bytes.Length);
var bytesPerLine = (image.Width + 31) / 32 * 4;
var img = new Bitmap(image.Width, image.Height, bytesPerLine, PixelFormat.Format1bppIndexed, pData);
using (var ms = new MemoryStream())
{
image.Save(ms, _codecInfo, _encoderParameters);
img.Dispose();
Marshal.FreeHGlobal(pData);
return ms.ToArray();
}
}
}
Updated:
public static byte[] ConvertToOnebitFaxGroup4(byte[] bytes)
{
using (var memoryStream = new MemoryStream(bytes))
{
using (var image = Image.FromStream(memoryStream))
{
var pData = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, pData, bytes.Length);
var bytesPerLine = (image.Width + 31) / 32 * 4;
using (var img = new Bitmap(image.Width, image.Height, bytesPerLine, PixelFormat.Format1bppIndexed, pData))
{
using (var ms = new MemoryStream())
{
img.Save(ms, _codecInfo, _encoderParameters);
Marshal.FreeHGlobal(pData);
return ms.ToArray();
}
}
}
}
}
Update2
public static byte[] ConvertToOnebitFaxGroup4(byte[] bytes)
{
using (var memoryStream = new MemoryStream(bytes))
{
using (var image = Image.FromStream(memoryStream))
{
using (var ms = new MemoryStream())
{
image.Save(ms, _codecInfo, _encoderParameters);
return ms.ToArray();
}
}
}
}
Following is the code to retrieve image from database and then saving it to a folder.
public string BinarytoNewsImage(int ID)
{
byte[] btimage = null;
string image = "";
string filename = null;
int mediaid;
DataSet dsNews = new DataSet();
adp = new SqlDataAdapter("Select Top 1 * from tblNew Where intNewId=" + ID, offcon);
adp.Fill(dsNews, "tblNews1");
if (dsNews.Tables["tblNews1"].Rows.Count > 0)
{
if (dsNews.Tables["tblNews1"].Rows[0]["strImage"] != DBNull.Value)
{
btimage = (byte[])dsNews.Tables["tblNews1"].Rows[0]["strImage"];
mediaid = Convert.ToInt32(dsNews.Tables["tblNews1"].Rows[0]["intMediaId"].ToString());
filename = dsNews.Tables["tblNews1"].Rows[0]["strfilename"].ToString();
image = BinarytoImage(btimage, mediaid);
}
else
{
filename = dsNews.Tables["tblNews1"].Rows[0]["strfilename"].ToString();
image = "http://www.patrika.com/media/" + filename;
}
}
return image;
}
public string BinarytoImage(byte[] stream, int ID)
{
string ImagePath = "";
string Image = ID + ".jpg";
var URL = System.Configuration.ConfigurationManager.AppSettings["ImagePath"].ToString();
string FolderName = new Uri(URL).LocalPath;
var help = HttpContext.Current.Server.MapPath(FolderName);
if (Directory.Exists(HttpContext.Current.Server.MapPath(FolderName)))
{
string[] files = Directory.GetFiles(HttpContext.Current.Server.MapPath(FolderName), ID + ".jpg");
if (files.Length > 0)
{
ImagePath = URL + ID + ".jpg";
}
else
{
using (MemoryStream MS = new MemoryStream(stream, 0, stream.Length))
{
MS.Write(stream, 0, stream.Length);
System.Drawing.Image img = System.Drawing.Image.FromStream(MS);
img.Save(help + ID + ".jpg", System.Drawing.Imaging.ImageFormat.Gif);
img.Dispose();
img = null;
ImagePath = URL + ID + ".jpg";
}
}
}
return ImagePath;
}
Everything is working fine the images are saving to a folder but my problem is images are getting blur after retrieval.
I just don't know the reason as when I am using another code for retrieval than images are coming fine but are not saved to folder:
DataSet dsNews = new DataSet();
adp = new SqlDataAdapter("Select Top 1 * from tblNew Where intNewId=901371", con);
adp.Fill(dsNews, "tblNews1");
if (dsNews.Tables["tblNews1"].Rows[0]["strImage"] != DBNull.Value)
{
byte[] btimage = (byte[])dsNews.Tables["tblNews1"].Rows[0]["strImage"];
Response.ContentType = "image/jpeg";
Response.BinaryWrite(btimage);
}
I need those images to be saved to folder so that I don't have to call database after once image comes.
Wouldn't it help to change this line
img.Save(help + ID + ".jpg", System.Drawing.Imaging.ImageFormat.Gif);
to store it as JPEG rather? as that's the source format
EDIT:
Your are not moving the stream pointer back to the start.
Try change these lines:
using (MemoryStream MS = new MemoryStream(stream, 0, stream.Length))
{
MS.Write(stream, 0, stream.Length);
System.Drawing.Image img = System.Drawing.Image.FromStream(MS);
...
To
using (MemoryStream MS = new MemoryStream(stream, 0, stream.Length))
{
MS.Write(stream, 0, stream.Length);
MS.Seek(0, SeekOrigin.Begin);
System.Drawing.Image img = System.Drawing.Image.FromStream(MS);
...
I write the common method, all is ok.
Maybe your byte[]stream is not right,pls check.
byte[] stream = File.ReadAllBytes(#"D:\YWG\123.jpg");
using (MemoryStream MS = new MemoryStream(stream, 0, stream.Length))
{
MS.Write(stream, 0, stream.Length);
using (Image img = Image.FromStream(MS))
{
img.Save(#"D:\dd.jpg", System.Drawing.Imaging.ImageFormat.Gif);
}
}
I see the dest file "dd.jpg" is ok.