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:
...even though bmpOriginal comes from the PNG and bmpOptimized is from the encoded JPEG.
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 = 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:
...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.