0

I have inherited a code which resizes images in width and height. What I also observe is it also decreases the file size even when the image height and width increase. Here is the resize code and calling function code which saves image

for example which might better explain.I have original image which is 709*653 pixels and file size of 670 kb

Upon resizing, it is 1000*921 which is expected but it's size is 176 kb

         Image  orgImage = Image.FromFile(originalimagepath);            
        //resizes image using below function
        transformedImage = ImageUtils.resizeImage(orgImage, Settings.MaxLargeImage);
        memstrImage = new MemoryStream();

        //saves image to memorystream which is in turn saved in destination as resized image.  
        transformedImage.Save(memstrImage,ImageFormat.Jpeg);

public static Image resizeImage(Image imgToResize, int resizeType)
{
    //resizetype is maximum resize width I want image to take.
    int height = imgToResize.Height;
    int width = imgToResize.Width;
    float ratio = 0;

    Size size = new Size();

    if (height >= width)
    {
        ratio = ((float)resizeType / (float)height);
    }
    else
    {
        ratio = ((float)resizeType / (float)width);
    }

    size.Height = Convert.ToInt32((float)ratio * (float)imgToResize.Height);
    size.Width = Convert.ToInt32((float)ratio * (float)imgToResize.Width);

    int sourceWidth = imgToResize.Width;
    int sourceHeight = imgToResize.Height;

    float nPercent = 0;
    float nPercentW = 0;
    float nPercentH = 0;

    nPercentW = ((float)size.Width / (float)sourceWidth);
    nPercentH = ((float)size.Height / (float)sourceHeight);

    if (nPercentH < nPercentW)
        nPercent = nPercentH;
    else
        nPercent = nPercentW;

    int destHeight = Convert.ToInt32(sourceHeight * nPercent);
    int destWidth = Convert.ToInt32(sourceWidth * nPercent);

    Bitmap b = new Bitmap(destWidth, destHeight);
    Graphics g = Graphics.FromImage((Image)b);
    g.CompositingQuality = CompositingQuality.HighQuality;            
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
    g.SmoothingMode = SmoothingMode.HighQuality;

    g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
    g.Dispose();

    return (Image)b;
}

I assume, and could see aspect ratios arent compromised but Is it suggested to keep this as it is, or Is it logical that ideally file size should increase , when image height and width increase

For the question, I want to increase file size when height and width increase but best practice suggestions are welcome.

Any suggestions?

Mandar Jogalekar
  • 2,809
  • 4
  • 31
  • 70
  • How do you measure the previous and new file size? – Euphoric Aug 15 '14 at 06:11
  • Are you sure your disposing of your bitmap correctly? its possible that the image file hasn't been finalized – Sayse Aug 15 '14 at 06:12
  • @Euphoric by downloading both. – Mandar Jogalekar Aug 15 '14 at 06:14
  • @Sayse can you explain more.do you see anything wrong in code? – Mandar Jogalekar Aug 15 '14 at 06:16
  • The issue will most probably be in how you save the images. The resizing is most probably irrelevant here. Show us the WHOLE code. Not just snippets. – Euphoric Aug 15 '14 at 06:16
  • `Bitmap b = new Bitmap(destWidth, destHeight);`, Bitmaps are `IDisposable` so you need to dispose – Sayse Aug 15 '14 at 06:16
  • 2
    What image format are you using? If you are using "jpg" it is re-compressed every time it is saved. This can cause reduction in size (good) and quality (bad). If you just use `Image.Save()`, the default quality is believed to be 75 [(source)](http://stackoverflow.com/questions/3957477/what-quality-level-does-image-save-use-for-jpeg-files/3959115#3959115). – dbc Aug 15 '14 at 06:17
  • Yes, i am using ImageFormat.Jpeg. Can see if I select ImageFormat.Png FileSize does not decrease. What would be sideeffect If I save Image as Image.Save(MemStream,ImageFormat.Png) and in turn save the memorystream to file with extension "Jpg"? – Mandar Jogalekar Aug 15 '14 at 06:36
  • PNG is not lossy so the file could be much larger. What was the original file format? – dbc Aug 15 '14 at 06:38
  • Original format was jpeg – Mandar Jogalekar Aug 15 '14 at 06:41

2 Answers2

0

This is clearly case of saving in either different image format than the original (bmp or png vs jpg) or using different compression strength for JPG.

You should either note the format of image when you load it and save it back in same format. Or make sure you use different compression strength when saving jpg. See more here.

Euphoric
  • 12,015
  • 1
  • 26
  • 41
0

You are saving your resized image to the Jpeg format. Jpeg is a "lossy" format, which means that, to save space, the image saved is only an approximation of the in-memory bitmap, chosen so that it looks "close" to the original to the human eye. If you just use Image.Save() to save your bitmap, the "storage quality" is believed to be 75, according to this post: What quality level does Image.Save() use for jpeg files?. (In any event the quality of Image.Save() to the Jpeg format is not documented.)

Thus, if you resize a bitmap and save it to Jpeg, the resulting file could be smaller than the original, or larger, because of compression, independent of the change in dimension. (Though large changes in dimension will eventually dominate any compression issues, since the raw size of a bitmap increases quadratically with scaling the pixel dimensions.)

If you want to experiment with how quality settings affect file size when saving a JPG, you can use this method:

    public static void SaveJpegWithSpecifiedQuality(this Image image, string filename, int quality)
    {
        // http://msdn.microsoft.com/en-us/library/ms533844%28v=vs.85%29.aspx
        // A quality level of 0 corresponds to the greatest compression, and a quality level of 100 corresponds to the least compression.
        if (quality < 0 || quality > 100)
        {
            throw new ArgumentOutOfRangeException("quality");
        }

        System.Drawing.Imaging.Encoder qualityEncoder = System.Drawing.Imaging.Encoder.Quality;
        EncoderParameters encoderParams = new EncoderParameters(1);
        EncoderParameter encoderParam = new EncoderParameter(qualityEncoder, (long)quality);
        encoderParams.Param[0] = encoderParam;

        image.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParams);
    }

    private static ImageCodecInfo GetEncoder(ImageFormat format)
    {
        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
        foreach (ImageCodecInfo codec in codecs)
        {
            if (codec.FormatID == format.Guid)
            {
                return codec;
            }
        }
        return null;
    }
Community
  • 1
  • 1
dbc
  • 80,875
  • 15
  • 141
  • 235
  • I tried this, and my file size went from 670 kb to 70 kb! – Mandar Jogalekar Aug 15 '14 at 06:41
  • @Mandar Jogalekar - Well, you should try a range of qualities from 100 (best) to 10 (awful) to get a feeling of how badly the visual appearance is degraded at each quality level. – dbc Aug 15 '14 at 06:45