C#: Preserving Bits per Plane when resizing images
I'm developing a service in which users can upload images and save them in a library. I want to preserve the original file (so people can upload high resolution images), but also make a copy of the image to use as a thumbnail.
The problem I have is that the thumbnail "weights" much more than the original file, proportionally. When I check the basic properties of each file (in XnView), I can see that the original files are for instance saved with 32 bits per Plane, whereas the source file will have, for instance, only 24 bits per plane.
What would be the correct way to make a copy of the original file while still using compression? This is an excerpt of the code:
private void ResizeImage(string originalFile, string NewFile, int NewWidth, int MaxHeight, bool OnlyResizeIfWider, string directory)
{
System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(originalFile);
// Prevent using images internal thumbnail
FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
if (OnlyResizeIfWider)
{
if (FullsizeImage.Width <= NewWidth)
{
NewWidth = FullsizeImage.Width;
}
}
int NewHeight = FullsizeImage.Height * NewWidth / FullsizeImage.Width;
if (NewHeight > MaxHeight)
{
// Resize with height instead
NewWidth = FullsizeImage.Width * MaxHeight / FullsizeImage.Height;
NewHeight = MaxHeight;
}
System.Drawing.Image NewImage = FullsizeImage.GetThumbnailImage(NewWidth, NewHeight, null, IntPtr.Zero);
// Clear handle to original file so that we can overwrite it if necessary
Full开发者_运维技巧sizeImage.Dispose();
// Save resized picture
NewImage.Save(directory + Path.DirectorySeparatorChar + NewFile);
}
I would suggest you save the image as a PNG or JPEG stream. That will be much more efficient. Considering that the thumbnail is not the original data, it is probably OK to apply strong compression on it (QF < 60). I once managed to get useful JPEG images in less than 1000 bytes. At that point, they're so small you can consider putting them in a database rather than on disk.
EDIT: (after reading the question fully :) )
And to answer the question, the result of GetThumbnailForImage()
, is again an Image
so you can call the Save method on it, one of the overloads allows you to specify which compression to use.
Rather than calling GetThumbnailImage
, you can create a new image of the size you want and the PixelFormat
that you want, and then scale the original image into that.
System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(originalFile);
// Create a bitmap that's NewWidth x NewHeight
Bitmap bmp = new Bitmap(NewWidth, NewHeight, PixelFormat.Format24bppRgb);
// Get a Graphics object for that image and draw the original image into it
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawImage(FullsizeImage, 0, 0, NewWidth, NewHeight);
}
// you now have a 24bpp thumbnail image
精彩评论