可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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();
}
回答1:
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
回答2:
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.
回答3:
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):
The original SO logo:
Original http://magnetiq.com/exports/sologo/original.jpg
File size: 4,483 bytes
Preserve the dimensions and apply a heavy Gaussian blur:
Blurred http://magnetiq.com/exports/sologo/blurred.jpg
File size: 1,578 bytes
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.
回答4:
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.
回答5:
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.
回答6:
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.
回答7:
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.