none
Resizing Image

    Question

  • Is there posibility of resizing BitmapImage using WPF?

     

    I do not want to resize an Image control. I want to resize image itself so when i convert it to bytes and stores it in database it has desired size.

     

    Thanks for suggestions

     

    Peter

    Thursday, September 06, 2007 3:09 PM

Answers

  • Actually, WPF contains some very powerful classes in the System.Windows.Media.Imaging namespace that can be leveraged for image manipulation.  Here's a quick sample I threw together to demonstrate how you can resize an image by leveraging the BitmapImage class.

     

    This sample also demonstrates how to use the different encoder classes to save the image data in the desired format.

     

    Note that I have written the methods such that they take byte arrays instead of file names.  This will allow you to easily load (and save) data from (and to) a field in your database.

     

    There are all kinds of other classes that can be leveraged for image manipulation, like CroppedBitmap (one of my favorites), ColorConvertedBitmap, TransformedBitmap, etc.

     

    Let me know if you have any trouble with this code.  I can always send you the project.

     

    Code Snippet

     

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Windows;

    using System.Windows.Controls;

    using System.Windows.Data;

    using System.Windows.Documents;

    using System.Windows.Input;

    using System.Windows.Media;

    using System.Windows.Media.Imaging;

    using System.Windows.Shapes;

    using System.IO;

     

    namespace WindowsApplication1

    {

        public partial class Window1 : System.Windows.Window

        {

     

            public Window1()

            {

                InitializeComponent();

            }

     

            private void ResizeImage(object sender, RoutedEventArgs e)

            {

                byte[] imageBytes = LoadImageData(@"c:\temp\MyImage.jpg");

     

                // decode the image such that its width is 120 and its

                // height is scaled proportionally

                ImageSource imageSource = CreateImage(imageBytes, 120, 0);

     

                // OTHER OPTIONS

     

                // the following will decode the image to its natural size

                // imageSource = CreateImage(imageBytes, 0, 0);

     

                // the following will decode the image such that its height

                // is 160 and its width is scaled proportionally

                // imageSource = CreateImage(imageBytes, 0, 160);

     

                // the following will decode the image to exactly 120 x 160

                // imageSource = CreateImage(imageBytes, 120, 160);

                imageBytes = GetEncodedImageData(imageSource, ".gif");

                SaveImageData(imageBytes, @"c:\temp\MyResizedImage.gif");

            }

     

            private static byte[] LoadImageData(string filePath)

            {

                FileStream fs = new FileStream(filePath, FileMode.Open,

                    FileAccess.Read);

                BinaryReader br = new BinaryReader(fs);

                byte[] imageBytes = br.ReadBytes((int)fs.Length);

                br.Close();

                fs.Close();

                return imageBytes;

            }

     

            private static void SaveImageData(byte[] imageData,

                string filePath)

            {

                FileStream fs = new FileStream(filePath, FileMode.Create,

                    FileAccess.Write);

                BinaryWriter bw = new BinaryWriter(fs);

                bw.Write(imageData);

                bw.Close();

                fs.Close();

            }

     

            private static ImageSource CreateImage(byte[] imageData,

                    int decodePixelWidth, int decodePixelHeight)

            {

                if (imageData == null) return null;

     

                BitmapImage result = new BitmapImage();

                result.BeginInit();

                if (decodePixelWidth > 0)

                {

                    result.DecodePixelWidth = decodePixelWidth;

                }

                if (decodePixelHeight > 0)

                {

                    result.DecodePixelHeight = decodePixelHeight;

                }

                result.StreamSource = new MemoryStream(imageData);

                result.CreateOptions = BitmapCreateOptions.None;

                result.CacheOption = BitmapCacheOption.Default;

                result.EndInit();

                return result;

            }

     

            internal byte[] GetEncodedImageData(ImageSource image,

                    string preferredFormat)

            {

                byte[] result = null;

                BitmapEncoder encoder = null;

                switch (preferredFormat.ToLower())

                {

                    case ".jpg":

                    case ".jpeg":

                        encoder = new JpegBitmapEncoder();

                        break;

     

                    case ".bmp":

                        encoder = new BmpBitmapEncoder();

                        break;

     

                    case ".png":

                        encoder = new PngBitmapEncoder();

                        break;

     

                    case ".tif":

                    case ".tiff":

                        encoder = new TiffBitmapEncoder();

                        break;

     

                    case ".gif":

                        encoder = new GifBitmapEncoder();

                        break;

     

                    case ".wmp":

                        encoder = new WmpBitmapEncoder();

                        break;

                }

     

                if (image is BitmapSource)

                {

                    MemoryStream stream = new MemoryStream();

                    encoder.Frames.Add(

                        BitmapFrame.Create(image as BitmapSource));

                    encoder.Save(stream);

                    stream.Seek(0, SeekOrigin.Begin);

                    result = new byte[stream.Length];

                    BinaryReader br = new BinaryReader(stream);

                    br.Read(result, 0, (int)stream.Length);

                    br.Close();

                    stream.Close();

                }

                return result;

            }

        }

    }

     

     

    Thursday, September 06, 2007 6:12 PM

All replies

  • There's nothing really built into WPF directly to do image manipulation outside of displaying the image on screen. You can always call CopyPixels on the BitmapImage and push that into a System.Drawing Bitmap and do the resizing using that API.

     

    The only "pure" WPF way to accomplish this is to use RenderTargetBitmap where you pass the image control into it and specify your target size for output and call Render. This is likely to be more costly than the System.Drawing approach, though this is just a gut feel as I don't have actual measurements.

     

    HTH,
    Drew

    Thursday, September 06, 2007 5:06 PM
  • Actually, WPF contains some very powerful classes in the System.Windows.Media.Imaging namespace that can be leveraged for image manipulation.  Here's a quick sample I threw together to demonstrate how you can resize an image by leveraging the BitmapImage class.

     

    This sample also demonstrates how to use the different encoder classes to save the image data in the desired format.

     

    Note that I have written the methods such that they take byte arrays instead of file names.  This will allow you to easily load (and save) data from (and to) a field in your database.

     

    There are all kinds of other classes that can be leveraged for image manipulation, like CroppedBitmap (one of my favorites), ColorConvertedBitmap, TransformedBitmap, etc.

     

    Let me know if you have any trouble with this code.  I can always send you the project.

     

    Code Snippet

     

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Windows;

    using System.Windows.Controls;

    using System.Windows.Data;

    using System.Windows.Documents;

    using System.Windows.Input;

    using System.Windows.Media;

    using System.Windows.Media.Imaging;

    using System.Windows.Shapes;

    using System.IO;

     

    namespace WindowsApplication1

    {

        public partial class Window1 : System.Windows.Window

        {

     

            public Window1()

            {

                InitializeComponent();

            }

     

            private void ResizeImage(object sender, RoutedEventArgs e)

            {

                byte[] imageBytes = LoadImageData(@"c:\temp\MyImage.jpg");

     

                // decode the image such that its width is 120 and its

                // height is scaled proportionally

                ImageSource imageSource = CreateImage(imageBytes, 120, 0);

     

                // OTHER OPTIONS

     

                // the following will decode the image to its natural size

                // imageSource = CreateImage(imageBytes, 0, 0);

     

                // the following will decode the image such that its height

                // is 160 and its width is scaled proportionally

                // imageSource = CreateImage(imageBytes, 0, 160);

     

                // the following will decode the image to exactly 120 x 160

                // imageSource = CreateImage(imageBytes, 120, 160);

                imageBytes = GetEncodedImageData(imageSource, ".gif");

                SaveImageData(imageBytes, @"c:\temp\MyResizedImage.gif");

            }

     

            private static byte[] LoadImageData(string filePath)

            {

                FileStream fs = new FileStream(filePath, FileMode.Open,

                    FileAccess.Read);

                BinaryReader br = new BinaryReader(fs);

                byte[] imageBytes = br.ReadBytes((int)fs.Length);

                br.Close();

                fs.Close();

                return imageBytes;

            }

     

            private static void SaveImageData(byte[] imageData,

                string filePath)

            {

                FileStream fs = new FileStream(filePath, FileMode.Create,

                    FileAccess.Write);

                BinaryWriter bw = new BinaryWriter(fs);

                bw.Write(imageData);

                bw.Close();

                fs.Close();

            }

     

            private static ImageSource CreateImage(byte[] imageData,

                    int decodePixelWidth, int decodePixelHeight)

            {

                if (imageData == null) return null;

     

                BitmapImage result = new BitmapImage();

                result.BeginInit();

                if (decodePixelWidth > 0)

                {

                    result.DecodePixelWidth = decodePixelWidth;

                }

                if (decodePixelHeight > 0)

                {

                    result.DecodePixelHeight = decodePixelHeight;

                }

                result.StreamSource = new MemoryStream(imageData);

                result.CreateOptions = BitmapCreateOptions.None;

                result.CacheOption = BitmapCacheOption.Default;

                result.EndInit();

                return result;

            }

     

            internal byte[] GetEncodedImageData(ImageSource image,

                    string preferredFormat)

            {

                byte[] result = null;

                BitmapEncoder encoder = null;

                switch (preferredFormat.ToLower())

                {

                    case ".jpg":

                    case ".jpeg":

                        encoder = new JpegBitmapEncoder();

                        break;

     

                    case ".bmp":

                        encoder = new BmpBitmapEncoder();

                        break;

     

                    case ".png":

                        encoder = new PngBitmapEncoder();

                        break;

     

                    case ".tif":

                    case ".tiff":

                        encoder = new TiffBitmapEncoder();

                        break;

     

                    case ".gif":

                        encoder = new GifBitmapEncoder();

                        break;

     

                    case ".wmp":

                        encoder = new WmpBitmapEncoder();

                        break;

                }

     

                if (image is BitmapSource)

                {

                    MemoryStream stream = new MemoryStream();

                    encoder.Frames.Add(

                        BitmapFrame.Create(image as BitmapSource));

                    encoder.Save(stream);

                    stream.Seek(0, SeekOrigin.Begin);

                    result = new byte[stream.Length];

                    BinaryReader br = new BinaryReader(stream);

                    br.Read(result, 0, (int)stream.Length);

                    br.Close();

                    stream.Close();

                }

                return result;

            }

        }

    }

     

     

    Thursday, September 06, 2007 6:12 PM
  • Interesting, mea culpa I suppose. I didn't realize that using the DecodePixelWidth/Height when loading the image or using a TransformedBitmap would actually trigger the encoder architecture to write those bytes out as opposed to the original source bytes. Makes sense I suppose.

     

    -Drew

    Thursday, September 06, 2007 6:18 PM
  • Awesome answer, thank you very much. I am going to experiment with this code immediately.

     

    Peter

    Friday, September 07, 2007 6:43 AM
  • One thing I've noticed about this code, well mine is slightly different but follows the same logic. When you resize WMP bitmaps it doesn't actually drop unneeded data, why is that?

     

    edit: Never mind, I found out that I was opening the same file to write to. So it ended up placing the new frame infront of the previous ones Tongue Tied leading to immense confusion and the inevitible question, why is a picture that is 1/64 the size of the original image 3 times the size of the image in megabytes Tongue Tied. Regardless a File.Delete solved that problem.

    Tuesday, March 04, 2008 3:17 PM
  • Great post Doc,
    I was hoping you (or anyone else) could explain why a BitmapEncoder is needed when converting from an ImageSource to a byte[], but not from a byte[] to an ImageSource?
    Thanks,
    Lee
    Thursday, February 19, 2009 12:49 AM
  • Great Post!  That was very helpful.  I am wondering if someone could tell me this though.

    If you load a image from a database and have it as a Byte[] is there anyway to determine what type of image it is?

    Friday, February 27, 2009 2:57 PM
  • Hi Dr. WPF,

     

    Can you please send me the project you are talking about.

     

    I have to resize some different format images and have to show them in different formats, while doing

    this I am losing quality of image. Apart from this resizing, I also have to merge two images like setting

    some logo on the first image.

     

    Please send this on my email ids

     

    gauravkumararya@gmail.com

    and

    gauravkumararya@hotmail.com

     

    --

    Thanks & Regards

    Gaurav K Arya

    Thursday, November 11, 2010 12:41 PM