Asked by:
Adjusting image quality when resizing

Question
-
User768014394 posted
I'm trying to refactor some image resizing code to make it more efficient. I have the resizing working fine, however the resulting image's bytes are a bit larger than the original code's results.
I have the following code
private Bitmap ResizeImage(Bitmap originalImage, int width, int height) { Bitmap finalImage = new Bitmap(width, height); using (Graphics graphics = Graphics.FromImage(finalImage)) { Rectangle rectangle = new Rectangle(0, 0, width, height); graphics.CompositingQuality = CompositingQuality.Default; graphics.SmoothingMode = SmoothingMode.None; graphics.InterpolationMode = InterpolationMode.Bilinear; graphics.DrawImage(originalImage, rectangle); } const int quality = 40; ImageCodecInfo codec = RetrieveCodec("image/jpeg"); using (EncoderParameters codeParams = new EncoderParameters()) { using (EncoderParameter p = new EncoderParameter(Encoder.Quality, quality)) { using (MemoryStream bmpStream = new MemoryStream()) { codeParams.Param[0] = p; // Exception occurs here finalImage.Save(bmpStream, codec, codeParams); } } } return finalImage; } private ImageCodecInfo RetrieveCodec(string mimeType) { ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); foreach (ImageCodecInfo codec in codecs) { if (codec.MimeType == mimeType) return codec; } return null; }
When I call finalImage.Save(bmpStream, codec, codeParams), I get an Argument exception. What am I doing wrong? I checked the arguments and it seems everything has the right values.
Monday, September 19, 2011 5:12 PM
All replies
-
User768014394 posted
Figured it out. Apparently I wasn't copying the bitmap with "originalImage = resizedBmp;"
private Bitmap ResizeImage(Bitmap originalImage, int width, int height) { using (Bitmap resizedBmp = new Bitmap(width, height)) { using (Graphics g = Graphics.FromImage(resizedBmp)) { g.CompositingQuality = CompositingQuality.Default; g.SmoothingMode = SmoothingMode.None; g.InterpolationMode = InterpolationMode.Bilinear; Rectangle bounds = new Rectangle(0, 0, width, height); g.DrawImage(originalImage, bounds); } originalImage = resizedBmp; const int quality = 40; ImageCodecInfo codec = RetrieveCodec("image/jpeg"); using (MemoryStream bmpStream = new MemoryStream()) { using (EncoderParameters codecParams = new EncoderParameters()) { using (EncoderParameter p = new EncoderParameter(Encoder.Quality, quality)) { codecParams.Param[0] = p; resizedBmp.Save(bmpStream, codec, codecParams); } } return new Bitmap(bmpStream); } } }
Wednesday, September 21, 2011 3:59 PM -
User768014394 posted
That wasn't it. I'm still getting the same exception. The code changes I made were not being executed...
Wednesday, September 21, 2011 4:08 PM -
User768014394 posted
Here's what that problem was. I am not sure why it is happening though.
I was declaring const int quality = 40. When I created my EncoderParameter "p", the codecParams[0].Type was set to EncoderParameterValueType.ValyeTypeByte and that was apparently causing the argument exception. One of two changes fixes it:
- Instead of declaring quality as an integer constant, declare it as an integer variable
- Or declare quality as a long constant
If I do either, the codecParams[0].Type is set to EncoderParameterValue.Type.ValueTypeLong.
Why would declaring it as an integer constant try to make it a byte and declaring it as an integer variable not?
Wednesday, September 21, 2011 4:48 PM