This is my code to resize an image. It works fine but when I try to delete the previously created, I have an error "file is used by another process". This is the code:
try
{
int newHeight = width * fromStream.Height / fromStream.Width;
Image newImage = new Bitmap(width, newHeight);
using (Graphics graphicsHandle = Graphics.FromImage(newImage))
{
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicsHandle.DrawImage(fromStream, 0, 0, width, newHeight);
}
string processedFileName = String.Concat(Configuration.CoverLocalPath, #"\Processed\res_", Path.GetFileName(imageFile));
newImage.Save(processedFileName, ImageFormat.Jpeg);
newImage.Dispose();
return processedFileName;
}
catch (Exception ex)
{
Configuration.Log.Debug("Utility.cs", "ResizeMainCover", ex.Message);
return string.Empty;
}
I tried to dispose the Image object but without success. Any hints?
Without more code, its hard to tell, but more than likely the culprit is your fromStream not being closed and disposed properly. I'm assuming "previously created" means your source stream. Try wrapping it in a using statement, note I also wrapped the newImage so it would be disposed properly in case of an Exception.
using(var fromStream = GetSourceImageStream())
{
try
{
int newHeight = width * fromStream.Height / fromStream.Width;
using(Image newImage = new Bitmap(width, newHeight))
{
using (Graphics graphicsHandle = Graphics.FromImage(newImage))
{
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicsHandle.DrawImage(fromStream, 0, 0, width, newHeight);
}
string processedFileName = String.Concat(Configuration.CoverLocalPath, #"\Processed\res_", Path.GetFileName(imageFile));
newImage.Save(processedFileName, ImageFormat.Jpeg);
}
return processedFileName;
}
catch (Exception ex)
{
Configuration.Log.Debug("Utility.cs", "ResizeMainCover", ex.Message);
return string.Empty;
}
finally
{
fromStream.Close();
}
}
Related
I am using WCF for communication between client and server program on the same machine. Earlier I used Bitmaps to transfer video frames to the client. It was successful with WCF, but I only have 6 megabytes / sec LAN. Transferring 1.2Mb every second would block the LAN. I decided to JPEG encode the captured Bitmaps from the camera. It is possible to save a JPEG on the disk from a bitmap, or to a Memorystream. I created a
[MessageContract]
public class RemoteResponse
{
[MessageBodyMember(Order = 1)]
public System.IO.MemoryStream jpegImage;
}
I return this back from the (I)LiveImageService.
As I get it out in the client: RemoteResponse ret = client.GetLiveImage();
MemoryStream returnedImage = returnedResponse.jpegImage;
returnedImage.Position = 0L;
returnedImage.Seek(0, SeekOrigin.Begin);
args.image = returnedImage;
I do this in the event handler:
args.image.Position = 0L;
args.image.Seek(0, SeekOrigin.Begin);
//bitmap = new Bitmap(args.image);
bitmap = (Bitmap)Image.FromStream(args.image);
It gives me a "parameter is not valid" exception.
I have read that this is a buggy solution of Microsoft. Actually the
retreived stream is believed to be 21 bytes long because there is a trailing
zero \0 at the end of the leading "System.Drawing.Bitmap"\0. That is why the
processing of the image is stopped.
I have read a solution that avoids this:
byte[] arr = PdfReader.FlateDecode(PdfReader.GetStreamBytesRaw((PRStream)obj), true);
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, pixelFormat);
System.Drawing.Imaging.BitmapData bmd = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat);
Marshal.Copy(arr, 0, bmd.Scan0, arr.Length);
bmp.UnlockBits(bmd);
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png); // here it is the trick
arr = ms.GetBuffer(); // now I replace my incorrect image format bytes for the correct ones
System.Drawing.Image image = System.Drawing.Image.FromStream(ms);
image.Save(path, System.Drawing.Imaging.ImageFormat.Png);
}
How does the last arr = ... have any effect? It is not used anymore later?
So I don't understand.
update:
On a Microsoft website: https://social.msdn.microsoft.com/Forums/vstudio/en-US/f9e39595-04ca-42ae-a353-eb1a08602631/resolved-creating-image-file-parameter-is-not-valid?forum=netfxbcl
I rewrote the example so:
public static Bitmap DecodeJPEGFromMemoryStream(MemoryStream stream, int width, int height, PixelFormat pixelFormat)
{
string content = System.Text.Encoding.UTF8.GetString(stream.ToArray());
byte[] arr = Encoding.UTF8.GetBytes(content);
//byte[] arr = PdfReader.FlateDecode(PdfReader.GetStreamBytesRaw((PRStream)obj), true);
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, pixelFormat);
System.Drawing.Imaging.BitmapData bmd = bmp.LockBits(new
System.Drawing.Rectangle(0, 0, width, height),
System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat);
Marshal.Copy(arr, 0, bmd.Scan0, arr.Length);
bmp.UnlockBits(bmd);
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); // here it is the trick
arr = ms.GetBuffer(); // now I replace my incorrect image format bytes for the correct ones
System.Drawing.Image image = System.Drawing.Image.FromStream(ms);
Bitmap ret = new Bitmap(image);
return ret;
}
}
I can see the image in the Picturebox, but it has only 2 lines, flickering.
If I obscure the camera I see that it darkens. So the data comes through now. But I cannot reconstruct my JPEG live data.
I was able to decode the JPEG data, only with saving it to disk.
So I've got the image without error. I tried to save the image only
temporarily and delete after.
public static Bitmap DecodeJPEGFromMemoryStream(MemoryStream stream, int width, int height, PixelFormat pixelFormat)
{
try
{
if(File.Exists("c:\\imagecache.jpg") == true)
File.Delete("c:\\imagecache.jpg");
//using (FileStream file = new FileStream("c:\\imagecache.jpg", FileMode.CreateNew, System.IO.FileAccess.ReadWrite))
using (FileStream file = File.Open("c:\\imagecache.jpg", FileMode.CreateNew, FileAccess.Write, FileShare.ReadWrite))
{
stream.WriteTo(file);
//JpegBitmapDecoder decoder = new JpegBitmapDecoder(file, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
file.Close();
file.Dispose();
}
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
//BitmapSource bitmapSource = decoder.Frames[0];
Bitmap jpeg;
{
{
FileInfo info = new FileInfo("c:\\imagecache.jpg");
if (info.Length == 0)
{
File.Delete("c:\\imagecache.jpg");
return null;
}
}
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
jpeg = (Bitmap)Image.FromFile("c:\\imagecache.jpg"); //the process cannot access the file...
}
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
if (File.Exists("c:\\imagecache.jpg") == true)
File.Delete("c:\\imagecache.jpg");
return jpeg;
}
catch(Exception ex)
{
return null;
}
}
I get the exception: The process cannot access the file "imagecache.jpg",
because it is being used by another process. Exception comes at the FromFile.
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
Bitmap retImage = (Bitmap)jpeg.Clone();
jpeg.Dispose();
if (File.Exists("c:\\imagecache.jpg") == true)
{
System.IO.FileInfo fi = new System.IO.FileInfo("c:\\imagecache.jpg");
fi.Delete();
}
return retImage;
}
catch (Exception ex)
{
return null;
}
finally
{
stream.Dispose();
}
It is fixed so. Image.FromFile: the File remains locked until the Image is disposed.
So I cloned my Image and disposed the old one.
Before I've seen my Image, now nothing is visible.
I want to store the image in a folder. For that, i give path of folder as "D:\Project\Site\ImageFiles". By using this path, I stored the image in the folder successfully.
Now I want to store the image by giving path as "..\Project\Site\ImageFiles".
Here is the code:
public static bool SaveOriginalImage(string imageName, Image image)
{
try
{
var imageLocation = "D:\Project\Site\ImageFiles\";
if (!Directory.Exists(imageLocation))
{
Directory.CreateDirectory(imageLocation);
}
imageLocation = imageLocation + imageName;
var bitMapImage = new Bitmap(image.Width, image.Height);
bitMapImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphicImageContent = Graphics.FromImage(bitMapImage))
{
graphicImageContent.CompositingQuality = CompositingQuality.HighQuality;
graphicImageContent.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicImageContent.SmoothingMode = SmoothingMode.HighQuality;
graphicImageContent.DrawImage(image, 0, 0, image.Width, image.Height);
}
bitMapImage.Save(imageLocation);
bitMapImage.Dispose();
return true;
}
catch (Exception ex)
{
return false;
}
}
When giving path as "..\Project\Site\ImageFiles\", i get exception "Access is denied for the path ..\Project\Site\ImageFiles\ " when creating directory.
How can I achieve it?
var fullPath = Path.GetFullPath("..\Project\Site\ImageFiles")
https://msdn.microsoft.com/de-de/library/system.io.path(v=vs.110).aspx
I have some code which takes an uploaded image, resizes it to 5 different sizes, then uploads those to another storage repository. I'm trying to execute the 5 image resizing operations in parallel using TPL.
Upfront I'll mention that the resizing function is a static method, but that it doesn't use any static resources (so multiple parallel calls shouldn't be stepping on each other, from what I can tell). Also very relevant is that this is in the context of ASP.NET which has some different threading concerns.
When I run the following code, I invariably get an "invalid parameter" error from one of the calls, though which call varies:
tasks = new Task<Uri>[]
{
Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.FiveHundredFixedWidth, photoStream, mediaType, minWidth)),
Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.Square220, photoStream, mediaType, minWidth)),
Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.Square140, photoStream, mediaType, minWidth)),
Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.Square80, photoStream, mediaType, minWidth)),
Task.Run<Uri>(() => Upload(intId, ProfilePhotoSize.Square50, photoStream, mediaType, minWidth))
};
await Task.WhenAll(tasks)
If I look at the images created, some will be ok, some will clearly be corrupted - and this applies not just to the "errored" image.
However, executing those five operations synchronously results in five good images:
Upload(intId, ProfilePhotoSize.FiveHundredFixedWidth, photoStream, mediaType, minWidth);
Upload(intId, ProfilePhotoSize.Square220, photoStream, mediaType, minWidth);
Upload(intId, ProfilePhotoSize.Square140, photoStream, mediaType, minWidth);
Upload(intId, ProfilePhotoSize.Square80, photoStream, mediaType, minWidth);
Upload(intId, ProfilePhotoSize.Square50, photoStream, mediaType, minWidth);
Is there a known issue with these sorts of operations, or have I maybe done something else dodgy that may be causing this?
Here is the image resizing function:
private static Stream Resize(Stream image, ResizeParameters parameters, ImageUtility.ResizeType type)
{
Image image1 = (Image) new Bitmap(image);
Image image2 = (Image) null;
Image image3 = (Image) null;
Graphics graphics = (Graphics) null;
MemoryStream memoryStream = new MemoryStream();
try
{
parameters = ImageUtility.CalculateSize(image1, parameters, type);
if (!parameters.DoNothing)
{
image2 = (Image) new Bitmap(parameters.Width, parameters.Height);
switch (type)
{
case ImageUtility.ResizeType.FixedWidth:
graphics = Graphics.FromImage(image2);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.FillRectangle(Brushes.White, 0, 0, image1.Width, image1.Height);
graphics.DrawImage(image1, 0, 0, parameters.Width, parameters.Height);
graphics.Dispose();
break;
case ImageUtility.ResizeType.PaddingSquare:
image3 = (Image) new Bitmap(parameters.SelectedWidth, parameters.SelectedHeight);
graphics = Graphics.FromImage(image3);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.FillRectangle(Brushes.White, 0, 0, parameters.SelectedWidth, parameters.SelectedHeight);
graphics.DrawImage(image1, parameters.X, parameters.Y, image1.Width, image1.Height);
graphics = Graphics.FromImage(image2);
graphics.DrawImage(image3, 0, 0, parameters.Width, parameters.Height);
graphics.Dispose();
break;
case ImageUtility.ResizeType.CropSquare:
image3 = (Image) new Bitmap(parameters.SelectedWidth, parameters.SelectedHeight);
graphics = Graphics.FromImage(image3);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.FillRectangle(Brushes.White, 0, 0, parameters.SelectedWidth, parameters.SelectedHeight);
graphics.DrawImage(image1, new Rectangle(0, 0, parameters.SelectedWidth, parameters.SelectedHeight), parameters.X, parameters.Y, image3.Width, image3.Height, GraphicsUnit.Pixel);
graphics = Graphics.FromImage(image2);
graphics.DrawImage(image3, 0, 0, parameters.Width, parameters.Height);
graphics.Dispose();
break;
}
EncoderParameter encoderParameter = new EncoderParameter(Encoder.Quality, 90L);
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = encoderParameter;
image2.Save((Stream) memoryStream, ImageUtility.GetEncoder(parameters.Format), encoderParams);
}
else
{
image.Seek(0L, SeekOrigin.Begin);
image.CopyTo((Stream) memoryStream);
}
memoryStream.Seek(0L, SeekOrigin.Begin);
return (Stream) memoryStream;
}
finally
{
image1.Dispose();
if (image2 != null)
image2.Dispose();
if (image3 != null)
image3.Dispose();
if (graphics != null)
graphics.Dispose();
}
}
I am using the below code to create bitmap. Image is getting created but not with the specified size. Is there any issue with code?
public class ProcessImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
var bmpOut = new Bitmap(100, 100);
var request = (HttpWebRequest)WebRequest.Create("http://media.zenfs.com/en_us/Sports/ap/201305061639599673916-p2.jpeg");
request.AllowWriteStreamBuffering = true;
var response = (HttpWebResponse) request.GetResponse();
var myStream = response.GetResponseStream();
var b = new Bitmap(myStream);
var g = Graphics.FromImage(bmpOut);
g.InterpolationMode = InterpolationMode.High;
g.DrawImage(b,0,0,50, 50);
context.Response.ContentType = "image/png";
var stream = new MemoryStream();
b.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
b.Dispose();
stream.WriteTo(HttpContext.Current.Response.OutputStream);
//context.Response.Write("Hello World");
}
private Bitmap ResizeImage(Image image, int width, int height)
{
Bitmap result = new Bitmap(width, height);
result.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(result))
{
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.DrawImage(image, 0, 0, result.Width, result.Height);
}
return result;
}
Well, I try to write on an image in C#, my code is:
public string WriteOnImage(Bitmap Image, string NameImage, string TextFileName)
{
string Message = "OK";
try
{
Bitmap bitMapImage = new Bitmap(Image);
using (Graphics graphImage = Graphics.FromImage(Image))
{
graphImage.SmoothingMode = SmoothingMode.AntiAlias;
string line;
// Read the file and display it line by line.
StreamReader file = new StreamReader(Resources.C_PATH_DESTINO_IMG + TextFileName);
while ((line = file.ReadLine()) != null)
{
graphImage.DrawString(line, new Font("Courier New", 15, FontStyle.Bold), SystemBrushes.WindowText, new Point(0, 0));
HttpContext.Current.Response.ContentType = "image/jpeg";
bitMapImage.Save(Resources.C_PATH_DESTINO_IMG + NameImage, ImageFormat.Jpeg);
graphImage.Dispose();
bitMapImage.Dispose();
}
file.Close();
}
return Message;
}
catch (Exception ex)
{
EventLogWrite("Error: " + ex.Message);
return Message = ex.Message;
}
}
this method doesn't work because doesn't write on the image, please help me.
PD: I'm sorry for my english but I'm Latino jeje, thanks.
It looks like you are drawing on the wrong bitmap
Bitmap bitMapImage = new Bitmap(Image);
using (Graphics graphImage = Graphics.FromImage(Image))
should be
Bitmap bitMapImage = new Bitmap(Image);
using (Graphics graphImage = Graphics.FromImage(bitMapImage))