ReadTimeout exception with MemoryStream - c#

The following method throws this exception
System.IO.Stream)(ms)).ReadTimeout threw an exception of type
System.InvalidOperationException'
This is the method:
private static byte[] ImageToByteArraybyMemoryStream(Bitmap bmp)
{
using (MemoryStream ms = new MemoryStream()) {
bmp.Save(ms, bmp.RawFormat);
return ms.ToArray();
}
}
however, this error doesn't occur all the time. I'll try to explain in short what happens:
I load a bitmap from a file, display it and store it in Dictionary<int,Bitmap>
When application is closed, i write bitmap to apps config-file as byte[] (and there's no exception)
On start of app i load bitmap from config-file and display it
When user changes application-data (like resizing or moving the bitmap) i rewrite the config-file the same way as i did when bitmap was loaded from file and this exception occurs.

i just googled "generic gdi+ error" others also got a problem with the bmp.Save Method. the workaround for them is to create a new Bitmap from the one you wanna save and then save this copy.
...
Bitmap copy = new Bitmap(bmp);
copy.Save(ms, copy.RawfFormat);
...
Maybe this also works for you, i can not tell you the reason for this error, its reffered to as a bug on other sites.
Other Post discussing this Problem

I faced this issue and it took a while to understand that, the object that uploaded the image did not release its located memory and lock it! and the garbage collection didn't dispose of that object, therefore the API could not stream the image.
somehow it works for the first time then it will raise the error.
Solution:
I used HttpPostFileBase to upload the image, and after it has done I set it to null
and that's it!

Related

Need help, Im trying to compress images [duplicate]

Having a code that works for ages when loading and storing images, I discovered that I have one single image that breaks this code:
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);
The exception is:
System.Runtime.InteropServices.ExternalException occurred
A generic error occurred in GDI+.
at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at ...
As far as I can see, there is nothing special about the image. It is approx 250 pixels in size and can be opened in e.g. Windows Image Viewer or Paint.NET:
(Since the image above, after being uploaded to Stack Overflow does not produce the error anymore, I've put the original image here)
What I discovered is that upon calling the Save method, the destination image file is being created with zero bytes.
I am really clueless on what causes the error.
My questions:
Can you think of any special thing that would hinder .NET from saving the image?
Is there any way (beside panicing) to narrow down these kind of errors?
While I still did not find out the reason what exactly caused the error when saving the image, I found a workaround to apply:
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
var i2 = new Bitmap(i);
i2.Save(i2Path, ImageFormat.Jpeg);
I.e. by copying the image internally into a Bitmap instance and saving this image instead of the original image, the error disappeared.
I'm assuming that by copying it, the erroneous parts the caused the original Save call to fail are being removed an/or normalized, thus enabling the save operation to succeed.
Interestingly, the so stored image has a smaller file on disk (16 kB) than its original source (26 kB).
First of all make sure, that the desired folder has Read/Write permissions. Changing the permissions solved this problem for me.
Solution is here, you must dispose image object to release the memory on the server.
Try use using statement. Make sure destination directory on server exists too.
The reason may be that the image is loaded lazily and the loading process is not yet finished when you try to save it.
Following what's said in this blog post (assuming you're German by the picture you linked in your question) provides a possible solution. Also this SO question's accepted answer indicates this is due to the fact the image file you're trying to save to is locked.
EDIT
For Ulysses Alves, from the linked blog entry: If you load an image using Image.FromFile() it remains locked until it is disposed of. This prevents calls to Save().
pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
pictureBox1.Image.Save("C:\\test\\test2.jpg");
The above code throws an error.
To make it work, you need to copy the image. The following code works:
pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
Image copy = pictureBox1.Image;
copy.Save("C:\\test\\test2.jpg")
I found this question because I also faced the similar error and the file was actually created with zero length (if you don't see any file, first check the permissions to write into folder as other answers suggest). Although my code was slightly different (I use stream to read the image from memory, not from file), I think my answer may be helpful to anyone facing similar problem.
It may looks counter-intuitive, but you can't really dispose memory stream until you finish with image.
NOT WORKING:
Image patternImage;
using (var ms = new MemoryStream(patternBytes)) {
patternImage = new Bitmap(ms);
}
patternImage.Save(patternFile, ImageFormat.Jpeg);
Just don't dispose the stream until you done with image.
WORKS:
using (var ms = new MemoryStream(patternBytes)) {
patternImage = new Bitmap(ms);
patternImage.Save(patternFile, ImageFormat.Jpeg);
}
What is misleading:
Error message doesn't really tell you anything
You can see the image properties, like width and height, but can't
save it
my solution was to make, write temp content (File.WriteAllText) just before saving the file
Here is the code:
var i = Image.FromFile(i1Path);
File.WriteAllText(i2Path, "empty"); // <---- magic goes here
i.Save(i2Path, ImageFormat.Jpeg);
Please try and let me know
In my case I have accidentally deleted the directory where image was getting stored.
Key Information:
// Using System.Drawing.Imaging:
new Bitmap(image).Save(memoryStream, ImageFormat.Jpeg);
You MUST Cast the Image to a Bitmap to Save it.
Using:
// Using System.Drawing.Imaging:
image.Save(memoryStream, ImageFormat.Jpeg);
WILL throw the Error:
Generic GDI+ error when saving an image
Just use the visual studio as administrator or run the application created by the code as administrator it should work smoothly.
It is user access rights issue.
I faced the same and resolved it by running visual studio as administrator.
In my case, I set validateImageData to false:
Image.FromStream(stream, validateImageData: false);
solution:
Image.FromStream(stream, validateImageData: true);
Open in the program
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);
i.Dispose();

A generic error occurred in GDI+ during Bitmap.Save

First off, I've read through the existing StackOverflow answers on this specific issue. The consensus from those answers seems to be about permissions or existing files, etc... I've eliminated all of those issues.
Basically, the flow here is as follows:
The app takes a 24-bit PNG file and reading it into a Bitmap object, bmpOriginal.
The app saves bmpOriginal to a memory stream using the JPG encoder (obtained from looping through ImageCodecInfo.GetImageEncoders() until I found the one with the "image/jpeg" MimeType.
The app creates a new Bitmap, bmpOptimized, from the memory stream in step 2 and displays it in a PictureBox. So far, so good - everything works exactly as intended and I can even see JPG compression artifacts in the new Bitmap, so I know the encoder is working.
Later on in the code flow, the user clicks a button and it should save bmpOptimized to a new file, using the Bitmap.Save() method.
When I run this, it throws an error about "A generic error occurred in GDI+".
I double-checked to make sure the folder was writeable and that the file didn't already exist. In fact, the app actually does create a file in the right location, but it's empty (0 bytes).
The only other thing that seemed odd was that the bmpOriginal and bmpOptimized both have the same RawFormat value:
{[ImageFormat: b96b3caf-0728-11d3-9d7b-0000f81ef32e]}
...even though bmpOriginal comes from the PNG and bmpOptimized is from the encoded JPEG.
EDIT:
The code looks like this:
public Bitmap bmpOriginal;
public Bitmap bmpOptimized;
...
// Step 1
bmpOriginal = new Bitmap("foo.png");
// Step 2
using(MemoryStream ms = new MemoryStream())
{
ImageCodecInfo _jpgEncoder = _getEncoder("image/jpeg");
EncoderParameters _encoderParams = new EncoderParameters(1);
_encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 70L);
bmpOriginal.Save(ms, _jpgEncoder, _encoderParams);
// Step 3
bmpOptimized = new Bitmap(ms);
}
And then later on when the user clicks the button for step 4:
bmpOptimized.Save("bar.jpg");
...that's where the error happens.
Note that this edit is simply adding in the simplified version of the flow, since people are apparently downvoting this question for lack of source code. The one person who commented actually provided the correct answer - I needed to preserve the MemoryStream until after I saved the optimized bitmap.
Try this below
Please check whether memory stream didn't disposed until bmpOptimized image getting save in the desired location. If problem persist, then Check if path exists.

GDI+ exception when saving image in PNG format

An ASP.NET application on my server starts throwing GDI+ exception after running for several days. After I restart the server, all works fine for a couple of days and then suddenly this exception occurs again. After the first time it occurs, it occurs every time I try to save a PNG image, until I restart again.
When I try to save the image in JPEG, it works fine.
When I run this code from my project, it fails:
var path = #"C:\Project\images\logo.png";
var image = Image.FromFile(path);
using (var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Png); // Fails here on GDI+ exception.
//image.Save(ms, ImageFormat.Jpeg); // JPEG works somehow
}
Again: When I restart remote desktop and run this code, it works for a couple of days and at some moment suddenly starts to fail over and over.
I tried:
To make a console application with the same code and run it in the RDP where the project is. It worked fine!
Lots of different variations of codes that were suggested in more then 10 articles I read on this topic.
GCI.Collect() – no help.
Checked all the folders that has write permissions (maybe there is something with the IIS?).
More.
I think that it should be some configuration that suddenly changes due to something and I can’t understand what can it be.
After I restart the server all works fine for a couple of days and then suddenly this exception occurs and after the first time it occurs it will occur everytime I try to save the PNG image, until I will restart again.
Sounds like a memory leak to me. What .NET version is this compiled to? What server OS this running on?
You can start by enclosing your image in a using block:
var path = #"C:\Project\images\logo.png";
using (Image image = Image.FromFile(path))
{
using (var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Png);
}
}
This link I believe is relevant to your case.
It throw GDI+ error because one of your object not disposed, so better dispose used object.
If you are getting that error , then I can say that your application doesn't have a write permission on some directory.
GDI+ limits the height of an image to 65534
Always favor using the using statement. Which never forgets to dispose an object, even if the code throws an exception.
var path = #"C:\Project\images\logo.png";
using (Image image = Image.FromFile(path))
{
using (var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Png); //fails here on GDI+ exception.
//image.Save(ms, ImageFormat.Jpeg); //Jpeg Works somehow
}
}
The FromFile method locks the file, so use the Image.FromStream() method for reading the image:
byte[] bytes = System.IO.File.ReadAllBytes(filename);
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
using (var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Png); //fails here on GDI+ exception.
//image.Save(ms, ImageFormat.Jpeg); //Jpeg Works somehow
}
Basically, if you have disposable objects... Dispose them !
Image is disposable and as bitmap does, it uses windows resources.
If you do not dispose, the windows resources are not freed till you shut down your application. So you need to dispose any image instantiated.

How to find reason for Generic GDI+ error when saving an image?

Having a code that works for ages when loading and storing images, I discovered that I have one single image that breaks this code:
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);
The exception is:
System.Runtime.InteropServices.ExternalException occurred
A generic error occurred in GDI+.
at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at ...
As far as I can see, there is nothing special about the image. It is approx 250 pixels in size and can be opened in e.g. Windows Image Viewer or Paint.NET:
(Since the image above, after being uploaded to Stack Overflow does not produce the error anymore, I've put the original image here)
What I discovered is that upon calling the Save method, the destination image file is being created with zero bytes.
I am really clueless on what causes the error.
My questions:
Can you think of any special thing that would hinder .NET from saving the image?
Is there any way (beside panicing) to narrow down these kind of errors?
While I still did not find out the reason what exactly caused the error when saving the image, I found a workaround to apply:
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
var i2 = new Bitmap(i);
i2.Save(i2Path, ImageFormat.Jpeg);
I.e. by copying the image internally into a Bitmap instance and saving this image instead of the original image, the error disappeared.
I'm assuming that by copying it, the erroneous parts the caused the original Save call to fail are being removed an/or normalized, thus enabling the save operation to succeed.
Interestingly, the so stored image has a smaller file on disk (16 kB) than its original source (26 kB).
First of all make sure, that the desired folder has Read/Write permissions. Changing the permissions solved this problem for me.
Solution is here, you must dispose image object to release the memory on the server.
Try use using statement. Make sure destination directory on server exists too.
The reason may be that the image is loaded lazily and the loading process is not yet finished when you try to save it.
Following what's said in this blog post (assuming you're German by the picture you linked in your question) provides a possible solution. Also this SO question's accepted answer indicates this is due to the fact the image file you're trying to save to is locked.
EDIT
For Ulysses Alves, from the linked blog entry: If you load an image using Image.FromFile() it remains locked until it is disposed of. This prevents calls to Save().
pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
pictureBox1.Image.Save("C:\\test\\test2.jpg");
The above code throws an error.
To make it work, you need to copy the image. The following code works:
pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
Image copy = pictureBox1.Image;
copy.Save("C:\\test\\test2.jpg")
I found this question because I also faced the similar error and the file was actually created with zero length (if you don't see any file, first check the permissions to write into folder as other answers suggest). Although my code was slightly different (I use stream to read the image from memory, not from file), I think my answer may be helpful to anyone facing similar problem.
It may looks counter-intuitive, but you can't really dispose memory stream until you finish with image.
NOT WORKING:
Image patternImage;
using (var ms = new MemoryStream(patternBytes)) {
patternImage = new Bitmap(ms);
}
patternImage.Save(patternFile, ImageFormat.Jpeg);
Just don't dispose the stream until you done with image.
WORKS:
using (var ms = new MemoryStream(patternBytes)) {
patternImage = new Bitmap(ms);
patternImage.Save(patternFile, ImageFormat.Jpeg);
}
What is misleading:
Error message doesn't really tell you anything
You can see the image properties, like width and height, but can't
save it
my solution was to make, write temp content (File.WriteAllText) just before saving the file
Here is the code:
var i = Image.FromFile(i1Path);
File.WriteAllText(i2Path, "empty"); // <---- magic goes here
i.Save(i2Path, ImageFormat.Jpeg);
Please try and let me know
In my case I have accidentally deleted the directory where image was getting stored.
Key Information:
// Using System.Drawing.Imaging:
new Bitmap(image).Save(memoryStream, ImageFormat.Jpeg);
You MUST Cast the Image to a Bitmap to Save it.
Using:
// Using System.Drawing.Imaging:
image.Save(memoryStream, ImageFormat.Jpeg);
WILL throw the Error:
Generic GDI+ error when saving an image
Just use the visual studio as administrator or run the application created by the code as administrator it should work smoothly.
It is user access rights issue.
I faced the same and resolved it by running visual studio as administrator.
In my case, I set validateImageData to false:
Image.FromStream(stream, validateImageData: false);
solution:
Image.FromStream(stream, validateImageData: true);
Open in the program
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);
i.Dispose();

Image.Save crashing: {"Value cannot be null.\r\nParameter name: encoder"}

I am trying to save an image into a MemoryStream but it is failing under certain conditions.
Here is the code:
The following code succeeds:
Image img = Bitmap.FromStream(fileStream);
MemoryStream ms = new MemoryStream();
img.Save(ms, img.RawFormat); // This succeeds.
The following code fails:
Image img = Bitmap.FromStream(fileStream);
Image thumb = img.GetThumbnailImage(thumbWidth, thumbHeight, null, System.IntPtr.Zero);
MemoryStream ms = new MemoryStream();
thumb.Save(ms, thumb.RawFormat); // This fails.
Notice that the second snippet is using an image created using Image.GetThumbnailImage.
What is the difference? Does anyone have any idea why is it failing?
I believe the problem has to do with this part of the GetThumbnailImage documentation:
If the Image contains an embedded thumbnail image, this method retrieves the embedded thumbnail and scales it to the requested size. If the Image does not contain an embedded thumbnail image, this method creates a thumbnail image by scaling the main image.
This probably accounts for the intermittent behaviour (AKA "certain conditions"). The explanation is in the following Microsoft Connect ticket:
The underlying API is not able to locate an encoder for the MemoryBmp image type. We will need to investigate this will the GDI+ team. In the meantime, you should be able to simply change your ImageFormat to ImageFormat.Bmp rather than ImageFormat.MemoryBmp and it should work. It will still be saved to the MemoryStream using the BMP format.
In all likelihood, if there is no embedded thumbnail, the new thumbnail generated by the GetThumbnailImage API is in fact going to have a RawFormat of MemoryBmp which has no associated encoder - thus the specific error message you're seeing.
Just don't use thumb.RawFormat; since you know it's a bitmap anyway, use ImageFormat.Bmp instead.
P.S. Please note that although I deleted my earlier answer because it turned out to not to be relevant to this particular issue, it is still important to use the GetThumbnailImage API properly as the documentation specifies; you must pass a valid delegate for the callback parameter instead of null, otherwise it can fail, and you still need to be wrapping disposables in using clauses.

Categories

Resources