I'd like to open a .jpg file in WPF, scale it down to around 50%, then save it back to the file system. What's a good/efficient way to go about doing that?
Take a look at the answer with the most upvotes to this question. It offers a helper class for manipulating images. Take a look at the ResizeImage
function and SaveJpeg
function.
EDIT:
I have found something more WPF-specific here.
If you want to save on the memory usage you should look into specifying DecodePixelWidth/DecodePixelHeight on BitmapImage or the JpegDecoder.
The scaling can be accomplished using TransformedBitmap.
I have used 2 functions here. ResizeImage accepts Original Image as Byte Array and target size in pixel. This function Returns resized Image as Byte Array. You can write it in file.
Follow these steps
1) Read Image as Byte array using BinaryReader
2) Call ResizeImage function by Passing this array and target size of imag.
3) Store Returned value in Byte array
4) Write it to file using BinaryWriter
byte[] ResizeImage(byte[] imageFile, int targetSize)
{
System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile));
System.Drawing.Size newSize = CalculateDimensions(oldImage.Size, targetSize);
using (System.Drawing.Bitmap newImage = new System.Drawing.Bitmap(oldImage, (int)newSize.Width, (int)newSize.Height))
{
using (System.Drawing.Graphics canvas = System.Drawing.Graphics.FromImage(newImage))
{
canvas.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
canvas.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
canvas.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
canvas.DrawImage(oldImage, new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), newSize));
MemoryStream m = new MemoryStream();
newImage.Save(m, System.Drawing.Imaging.ImageFormat.Jpeg);
return m.GetBuffer();
}
}
}
System.Drawing.Size CalculateDimensions(System.Drawing.Size oldSize, int targetSize)
{
System.Drawing.Size newSize = new System.Drawing.Size();
if (oldSize.Height > oldSize.Width)
{
newSize.Width = (int)(oldSize.Width * ((float)targetSize / (float)oldSize.Height));
newSize.Height = targetSize;
}
else
{
newSize.Width = targetSize;
newSize.Height = (int)(oldSize.Height * ((float)targetSize / (float)oldSize.Width));
}
return newSize;
}