Does anyone have an idea of how to resize an image isotropically? Meaning I give it a set width/height, and the image is scaled to fit at it's same proportions within that box, even if there is whitespace around it?
3 Answers
found it:
public Image ResizeIsotropic(Image src, Size sz)
{
double d1 = sz.Width / (double)sz.Height;
double d2 = src.Width / (double)src.Height;
if (d1 > d2)
{
src = ResizeByHeight(src, sz.Height);
}
else
{
src = ResizeByWidth(src, sz.Width);
}
Image rtn = null;
using (Image thumbnail = new Bitmap(sz.Width, sz.Height, PixelFormat.Format32bppArgb))
{
using (Graphics graphic = System.Drawing.Graphics.FromImage(thumbnail))
{
graphic.FillRectangle(Brushes.White, 0, 0, sz.Width, sz.Height);
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;
graphic.DrawImage(src, (sz.Width - src.Width)/2, (sz.Height - src.Height)/2, src.Width, src.Height);
EncoderParameters encoderParameters;
encoderParameters = new EncoderParameters(1);
ImageCodecInfo jpginfo = GetImageCodecInfo(ImageFormat.Jpeg);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, Quality);
MemoryStream ms = new MemoryStream();
thumbnail.Save(ms, jpginfo, encoderParameters);
rtn = Image.FromStream(ms);
}
}
theImage = rtn;
return rtn;
}
private ImageCodecInfo GetImageCodecInfo(ImageFormat format)
{
ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo jpginfo = null;
foreach (ImageCodecInfo i in info)
{
if (i.FormatID == format.Guid)
{
jpginfo = i;
break;
}
}
return jpginfo;
}
the ResizeByWidth and ResizeByHeight functions are other parts of a library i have, they do exactly what you'd think they do.
here are the results:
alt text http://imagebin.antiyes.com/images/0626614001263432575_87.jpg
-
-
yeah, i wrote that too, i'll post it. the first image is the original, the second is the original resized to 300x300 Commented Jan 14, 2010 at 1:30
-
Htrnm... so I just want to make Resize methods for the two in there?– CielCommented Jan 14, 2010 at 1:36
-
You said they do exactly what they sound like - I'm not sure what you mean by that...– CielCommented Jan 14, 2010 at 1:37
-
The ResizeByHeight resizes an image scaling it with the height set to what's passed in, the ResizeByWidth does the same but for the width. basically it resizes it to fit in the area first, then draws it to that area offsetted by half the extra distance. Commented Jan 14, 2010 at 1:42
Yes. First calculate the size so that the width fits in the box. Then check if the calculated height is larger than the box, in that case you calculate the size so that the height fits in the box instead.
While I believe John Boker's answer to be sufficient, this may be a more concise method of doing this:
static Bitmap ResizeIsotropic(Image img, Size newSize, Color backgroundColor)
{
int Width, Height;
if (img.Width >= img.Height)
{
Width = newSize.Width;
Height = (int)(img.Height / (img.Width / Width));
}
else
{
Height = newSize.Height;
Width = (int)(img.Width / (img.Height / Height));
}
Bitmap bmp = new Bitmap(newSize.Width, newSize.Height);
using (Graphics gfx = Graphics.FromImage(bmp))
{
gfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
gfx.Clear(backgroundColor);
gfx.DrawImage(img, (bmp.Width / 2) - (Width / 2), (bmp.Height / 2) - (Height / 2), Width, Height);
}
return bmp;
}
Then, to call it simply do:
Bitmap bmp = ResizeIsotropic(Image.FromFile(@"c:\yourImage.jpg"), new Size(512, 512), Color.Black);
bmp.Save(@"c:\test.bmp");