Resize with minimal loss of quality
I need to resize an image, but the image quality cannot be affected by this, the images will be from like 10x10 to 1000x1000, it will have some maj开发者_高级运维or congestions and some empty times it has to scale both up and down "potentially losing some image quality." is OK but it has to be at minimum, everything with raster graphics indeed NO libraries or other external binaries please
Here is a link showing you how to resize an image:
http://snippets.dzone.com/posts/show/4336
Whenever you resize images you're going to have some loss of quality - there's no way around that, but you can help minimize it by using the highest quality options in for the graphics context.
Here's what I use using plain GDI+ functions:
public static Bitmap ResizeImage(Bitmap bmp, int width, int height,
InterpolationMode mode = InterpolationMode.HighQualityBicubic)
{
Bitmap bmpOut = null;
try
{
decimal ratio;
int newWidth = 0;
int newHeight = 0;
// If the image is smaller than a thumbnail just return original size
if (bmp.Width < width && bmp.Height < height)
{
newWidth = bmp.Width;
newHeight = bmp.Height;
}
else
{
if (bmp.Width == bmp.Height)
{
if (height > width)
{
newHeight = height;
newWidth = height;
}
else
{
newHeight = width;
newWidth = width;
}
}
else if (bmp.Width >= bmp.Height)
{
ratio = (decimal) width/bmp.Width;
newWidth = width;
decimal lnTemp = bmp.Height*ratio;
newHeight = (int) lnTemp;
}
else
{
ratio = (decimal) height/bmp.Height;
newHeight = height;
decimal lnTemp = bmp.Width*ratio;
newWidth = (int) lnTemp;
}
}
//bmpOut = new Bitmap(bmp, new Size( newWidth, newHeight));
bmpOut = new Bitmap(newWidth, newHeight);
bmpOut.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
Graphics g = Graphics.FromImage(bmpOut);
g.InterpolationMode = mode;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.FillRectangle(Brushes.White, 0, 0, newWidth, newHeight);
g.DrawImage(bmp, 0, 0, newWidth, newHeight);
}
catch
{
return null;
}
return bmpOut;
}
This resizes an image to the largest of either the width or the height - you can vary that algorithm to fit your resizing needs.
If you want to work with files you can add another helper that wraps the code above:
public static bool ResizeImage(string filename, string outputFilename,
int width, int height,
InterpolationMode mode = InterpolationMode.HighQualityBicubic)
{
using (var bmpOut = ResizeImage(filename, width, height, mode) )
{
var imageFormat = GetImageFormatFromFilename(filename);
if (imageFormat == ImageFormat.Emf)
imageFormat = bmpOut.RawFormat;
bmpOut.Save(outputFilename, imageFormat);
}
return true;
}
GDI+ in general is not the best solution for high quality image manipulation - it's decent but if you need the highest quality, better performance and thread safety in Web apps you need to look at other options.
Bertrand LeRoy had a great article on Image Resizing some time ago that offers some alternatives using core .NET frameworks. http://weblogs.asp.net/bleroy/state-of-net-image-resizing-how-does-imageresizer-do
What you need is for your images to be scalable. I'd recommend using an XML format to store your images, since XML is very scalable. For example:
<Image Width="640" Height="480">
<Pixel X="0" Y="0">
<Red>20</Red>
<Green>80</Green>
<Blue>0</Blue>
<Alpha>255</Alpha>
</Pixel>
<Pixel X="1" Y="0">
...
If you're worried about memory, I bet this will compress really well :-).
精彩评论