Reputation: 23
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
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