locked
Adjusting image quality when resizing RRS feed

  • 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:

    1. Instead of declaring quality as an integer constant, declare it as an integer variable
    2. 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