简体   繁体   中英

Does resizing jpeg images affect their compression?

I'm resizing jpegs by using the Graphics.DrawImage method (see code fragment below). Can anyone confirm that this will not affect the compression of the new image? I have seen this thread , but I am talking specifically about compression of jpegs.

    private byte[] getResizedImage(String url, int newWidth)
    {
        Bitmap bmpOut = null;
        System.IO.MemoryStream outStream = new System.IO.MemoryStream();

        //input image is disposable
        using (Bitmap inputImage = LoadImageFromURL(url))
        {
            ImageFormat format = inputImage.RawFormat;
            decimal ratio;  //ratio old width:new width
            int newHeight = 0;

            //*** If the image is smaller than a thumbnail just return it
            if (inputImage.Width < newWidth)
                return null;

            ratio = (decimal)newWidth / inputImage.Width;
            decimal h = inputImage.Height * ratio;
            newHeight = (int)h;

            bmpOut = new Bitmap(newWidth, newHeight);
            Graphics g = Graphics.FromImage(bmpOut);
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            // try testing with following options:
            //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            //g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

            g.FillRectangle(Brushes.White, 0, 0, newWidth, newHeight);
            g.DrawImage(inputImage, 0, 0, newWidth, newHeight);
            bmpOut.Save(outStream, getImageFormat(url));
        }

        return outStream.ToArray();

    }

JPEGs have no "compression" value saved within them. When you resize and save them, they are compressed with whatever value you tell your save function to use. As you are not passing a value, it will just use whatever default for the library is.

Resizing an image effects the compression, if by "compression" you refer to how much detail can be fitted into how many pixels.

The JPEG compression algorithm favors blurry or homogeneous images with gradients and flat patches of colors. Therefore there isn't a direct correlation between image dimensions and the resultant file size. What matters most is the amount of detail in the image (all images were saved as JPEG with 80% loss factor):

  1. The original SO logo:

    Original http://magnetiq.com/exports/sologo/original.jpg

    File size: 4,483 bytes

  2. Preserve the dimensions and apply a heavy Gaussian blur:

    Blurred http://magnetiq.com/exports/sologo/blurred.jpg

    File size: 1,578 bytes

  3. Resize the original to 1/4:

    Shrunk http://magnetiq.com/exports/sologo/shrunk.jpg

    File size: 2,063 bytes

Note that the blurred image (2), even though it's 4 times as large as the shrunk one (3) is tinier in file size than both (1) and (2). Blurring adds nice gradients that make JPEG compression happy.

The small image (3), although it only has 1/4 the pixels that the original has (1), isn't quite 1/4 the file size. This is because shrinking the image results in finer details and JPEG compression doesn't like that.

When you call "bmpOut.Save" you have to pass in some EncoderParameters to tell the method what quality level you would like to save it with.

http://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoderparameters(VS.80).aspx

In your code " HighQualityBicubic " is the compression you are using. Resizing to a smaller size does remove detail, but that has nothing to do with compression, it just has to do with fewer pixels.

JPEG compression is lossy -- not all of the original data is actually stored exactly. If you compress an image as a JPEG and decompress it, you won't get back the exact original image. Every time you compress and decompress, you lose a bit of quality.

For some simple transformations, such as rotating a JPEG, you can do it losslessly with programs such as jpegtran .

However, for resizing images, you can't do it losslessly. You're definitely going to degrade the quality somewhat when you do this, although probably not by very much. If possible, try to use original lossless images as the source for the resize operation to get the highest possible quality, and if you concatenate multiple resize operations, instead just do a single resize from the original.

Do not confuse the storage format (JPEG) with the format you operate on using the Graphics object. The storage format is compressed, the Graphics object works with decompressed data.

The LoadImageFromURL method decompresses the information stored in the JPEG, you perform your resize operation on the decompressed data, and when you save it to a JPEG file, it gets compressed again.

Since JPEG compression is not lossless, the picture quality will be reduced every time you perform this process: Decompress, mutate, recompress .

If I missunderstood your question: The compression factor you use for saving the image inot set in your code, so it will be at some default value. If you want to reduce quality loss by saving with a small compression factor, you need to explicitly set it.

Same as what you already found, but here is the VB.NET version from Circumventing GDI+ default image compression .

I personally recommend JPEG quality setting of 90L.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM