Matthew Fishman
Matthew Fishman

Reputation: 23

Convert ImageBrush to byte[]

The Goal:

I want to convert an ImageBrush to a byte[].

Why?:

Because I want to print out the image, but I can't create any UI elements besides something like a MessageBox. SO I found an online tool that takes in a byte array and produces an image.

How do I do this in C# (WPF)?

What I've tried so far:

I have already converted the ImageBrush to a BitmapSource as so:

BitmapSource src = (BitmapSource)imageBrush.ImageSource;

and have converted the BitmapSource to a Bitmap Image as so:

private BitmapImage BitmapSourceToBitmapImage(BitmapSource bmpSrc)
    {
        JpegBitmapEncoder encoder = new JpegBitmapEncoder();
        MemoryStream memoryStream = new MemoryStream();
        BitmapImage bImg = new BitmapImage();

        encoder.Frames.Add(BitmapFrame.Create(bmpSrc));
        encoder.Save(memoryStream);

        memoryStream.Position = 0;
        bImg.BeginInit();
        bImg.StreamSource = memoryStream;
        bImg.EndInit();

        memoryStream.Close();

        return bImg;
    }

But for the life of me I cannot get this BitmapImage to a byte array! I have tried this:

private byte[] BitmapImagetoByteArray(BitmapImage bitmapImage) {
        byte[] data;
        JpegBitmapEncoder encoder = new JpegBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
        using(MemoryStream ms = new MemoryStream())
        {
            encoder.Save(ms);
            data = ms.ToArray();
        }
        return data;
    }

The Problem/Error:

But when the encoder tries to save the memory stream, it says a frame has been disposed... see error message below:

    Void SaveFrame(System.Windows.Media.SafeMILHandle, System.Windows.Media.SafeMILHandle, System.Windows.Media.Imaging.BitmapFrame)
Cannot access a disposed object.
System.ObjectDisposedException: Cannot access a disposed object.
   at System.Windows.Media.Imaging.BitmapEncoder.SaveFrame(SafeMILHandle frameEncodeHandle, SafeMILHandle encoderOptions, BitmapFrame frame)
   at System.Windows.Media.Imaging.BitmapEncoder.Save(Stream stream)

Any help? How can I display the ImageBrush without creating UI elements!

Upvotes: 0

Views: 932

Answers (1)

Matthew Fishman
Matthew Fishman

Reputation: 23

The error was not to set BitmapCacheOption.OnLoad, which is necessary when the source stream is to be closed right after EndInit:

bImg.BeginInit();
bImg.CacheOption = BitmapCacheOption.OnLoad;
bImg.StreamSource = memoryStream;
bImg.EndInit();
memoryStream.Close();

However, creating the intermediate BitmapImage wasn't necessary at all. The code should simply look like this:

private byte[] BitmapSourceToByteArray(BitmapSource bmpSrc)
{
    var encoder = new JpegBitmapEncoder();
    encoder.QualityLevel = 100;
    encoder.Frames.Add(BitmapFrame.Create(bmpSrc));

    using (var stream = new MemoryStream())
    {
        encoder.Save(stream);
        return stream.ToArray();
    }
}

Upvotes: 1

Related Questions