0

I want to resize images for iOS so that I don't have to do it manually all the time. This should be done using WPF but it throws a ObjectDisposedException.

What it does is the user selects a csproj file and then an image which will be resized in 3 sizes. After resizing the file should be safed to disk but it throws an exception.

retrieving the bytes of the original BitmapImage

byte[] data = original.GetByteArray();

The used method:

 public static byte[] GetByteArray(this BitmapImage bmi)
    {
        byte[] data;
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(bmi));
        using (Sys.MemoryStream ms = new Sys.MemoryStream())
        {
            encoder.Save(ms);
            data = ms.ToArray();
        }
        return data;
    }

the resizing:

private BitmapImage ResizeImage(byte[] imageData, double dheight, double dwidth)
        {
            int height = (int)dheight;
            int width = (int)dwidth;
            BitmapImage resizedImage = new BitmapImage();

            using (Sys.MemoryStream ms = new Sys.MemoryStream(imageData))
            {
                resizedImage.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
                resizedImage.CacheOption = BitmapCacheOption.OnLoad;
                resizedImage.DecodePixelHeight = height;
                resizedImage.DecodePixelWidth = width;
                resizedImage.BeginInit();  // Needed only so we can call EndInit()
                resizedImage.StreamSource = ms;
                resizedImage.EndInit();// This does the actual loading and resizing
            }
            return resizedImage;
        }

then the saving of the files:

public static void Save(this BitmapImage image, string filePath)
        {
            //PngBitmapEncoder encoder = new PngBitmapEncoder();
            //encoder.Frames.Add(BitmapFrame.Create(image));

            //using (var fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Create))
            //{
            //    encoder.Save(fileStream);
            //}
            File.WriteAllBytes(filePath, image.GetByteArray());
        }

how I used it:

            var bmi512 = ResizeImage(data, 512, 512);
            var bmi256 = ResizeImage(data, 256, 256);
            var bmi128 = ResizeImage(data, 128, 128);
            bmi512.Save(Sys.Path.Combine(imageFolderPath, String.Format("{0}512{1}", imageName, imageExt)));
            bmi256.Save(Sys.Path.Combine(imageFolderPath, String.Format("{0}256{1}", imageName, imageExt)));
            bmi128.Save(Sys.Path.Combine(imageFolderPath, String.Format("{0}128{1}", imageName, imageExt)));

it works for retrieving the byte[] of the original but when it try it for bmi512 I get the exception.

Thanks in advance

MelloPs
  • 135
  • 11
  • Where exactly is the exception thrown? You should call `resizedImage.BeginInit();` before setting any of its properties, i.e. as first statement inside the using block. You might also change the argument type of GetByteArray to BitmapSource, so you could use it with other BitmapSource-derived types than BitmapImage. – Clemens Nov 27 '18 at 10:15
  • Note also that there is a [TransformedBitmap](https://learn.microsoft.com/en-us/dotnet/api/system.windows.media.imaging.transformedbitmap?view=netframework-4.7.2) class, which you may use for scaling. – Clemens Nov 27 '18 at 10:23
  • Seriously the problem got solved by simply moving the BeginInt() to top position. Please write it as an answer so that I can accept it. – MelloPs Nov 27 '18 at 10:35

1 Answers1

2

You have to call BeginInit before you set any of the BitmapImage's properties:

using (var ms = new MemoryStream(imageData))
{
    resizedImage.BeginInit();
    resizedImage.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
    resizedImage.CacheOption = BitmapCacheOption.OnLoad;
    resizedImage.DecodePixelHeight = height;
    resizedImage.DecodePixelWidth = width;
    resizedImage.StreamSource = ms;
    resizedImage.EndInit();
}
Clemens
  • 123,504
  • 12
  • 155
  • 268