Convert BitmapImage to byte[] array in Windows Phone 8.1 Runtime - c#

There are a few samples to do this but they are for Windows Phone 8.0 or 8.1 Silverlight.
But how can you do this for Windows Phone 8.1 Runtime?

You cannot extract the pixels from a Windows.UI.Xaml.Media.Imaging.BitmapImage.
The most general solution is to use a WriteableBitmap instead of a BitmapImage. These classes are both BitmapSources and can be used almost interchangeably. The WriteableBitmap provides access to its pixel data via its PixelBuffer property:
byte[] pixelArray = myWriteableBitmap.PixelBuffer.ToArray(); // convert to Array
Stream pixelStream = wb.PixelBuffer.AsStream(); // convert to stream
Otherwise you will need to acquire the pixels from wherever the BitmapImage got them from. Depending on how the BitmapImage was initialized you may be able to find its origin from its UriSource property. The WinRT Xaml Toolkit has an extension method FromBitmapImage to create a WriteableBitmap from an BitmapImage based on its UriSource.
An ugly option would be to render the BitmapImage into an Image, create a RenderTargetBitmap based on the Image and then get its Pixels with RenderTargetBitmap.CopyPixelsAsync()

Tried this?
private byte[] ConvertToBytes(BitmapImage bitmapImage)
{
byte[] data = null;
using (MemoryStream stream = new MemoryStream())
{
WriteableBitmap wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
data = stream.GetBuffer();
}
return data;
}

Related

Convert a System.Drawing.Bitmap to Windows.Graphics.Imaging.SoftwareBitmap

I have a WPF project and captured an image from a usb camera to a System.Drawing.Bitmap (I also can capture System.Windows.Media.Imaging.BitmapSource) and need to convert it to a Windows.Graphics.Imaging.SoftwareBitmap to make a "VideoFrame" to compare to an Onnx model.
The camera driver is a .net assembly and will not bind to a uwp project. I've tried creating a .net standard assembly to bridge the gap with no success. I simply need a bitmap converted to a SoftwareBitmap. Please help!
I'm using this code for the basis of the compassion of the Bitmap image from the camera - https://github.com/Azure-Samples/cognitive-services-onnx12-customvision-sample
There is no direct conversion. You'll need to extract the image data from the System.Drawing.Bitmap and then create the new SoftwareBitmap from that data.
For example, you could use Save(Stream, ImageFormat) method to save this image to the specified stream in the specified format.
Then, you could try to call BitmapDecoder.CreateAsync method to create the decoder from the stream.
After that you could call GetSoftwareBitmapAsync to get a SoftwareBitmap object.
The following is a simple code sample:
Bitmap bitmap = getyourbitmap();
using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
{
bitmap.Save(stream.AsStream(),ImageFormat.Jpeg);//choose the specific image format by your own bitmap source
Windows.Graphics.Imaging.BitmapDecoder decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(stream);
SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync();
}
I found that you can use Windows.Security.Cryptography to create a IBuffer from the image array bytes. Then you can copy the IBuffer to the SoftwareBitmap.
using Windows.Security.Cryptography;
IBuffer buffer = CryptographicBuffer.CreateFromByteArray(ImageByteArray);
SoftwareBitmap softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Gray8, 800, 600);
softwareBitmap.CopyFromBuffer(buffer);
VideoFrame inputImage = VideoFrame.CreateWithSoftwareBitmap(softwareBitmap);
This worked for me:
Bitmap bitmap = ...;
var memoryStream = new MemoryStream();
using (var graphics = Graphics.FromImage(bitmap))
{
bitmap.Save(memoryStream, ImageFormat.Bmp);
}
var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(stream);
var bitmap = await decoder.GetSoftwareBitmapAsync();

How to convert UWP SoftwareBitmap to WPF Bitmap?

I'm trying to get a SoftwareBitmap to be usable by stuff in WPF as a Bitmap.
Approaches like this question shows look promising, but they seem to be using objects from different namespaces that don't quite work in my case. For context, I'm using MediaCapture from UWP land for webcam streaming in my app which is WPF.
public static WriteableBitmap WriteableBitmapFromSoftwareBitmap(SoftwareBitmap soft)
{
WriteableBitmap writeable = new
WriteableBitmap(soft.PixelWidth, soft.PixelHeight);
soft.CopyToBuffer(writeable.PixelBuffer);
return writeable;
}
public static Bitmap BitmapFromWriteableBitmap(WriteableBitmap writeBmp)
{
Bitmap bmp;
using (MemoryStream outStream = new MemoryStream())
{
System.Windows.Media.Imaging.BitmapEncoder enc = new
BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(writeBmp)); // Error here
enc.Save(outStream);
bmp = new Bitmap(outStream);
}
return bmp;
}
Unfortunately, in BitmapFromWriteableBitmap, the call to BitmapFrame.Create is complaining that it can't create a URI from that kind of WriteableBitmap.
Note that the WriteableBitmap is a Windows.UI.Xaml.Media.Imaging.WriteableBitmap,
the SoftwareBitmap is a Windows.Graphics.Imaging.SoftwareBitmap,
and the desired Bitmap is a System.Drawing.Bitmap.
There is no direct conversion. You'll need to extract the image data from the SoftwareBitmap and then create the new Bitmap from that data.
This is essentially what the linked question does: it encodes the data from the WriteableBitmap into a .BMP stream and then loads the System.Drawing.Bitmap from that stream.
You can do the same from the SoftwareBitmap by using Windows.Graphics.Imaging.BitmapEncoder.SetSoftwareBitmap to convert its contents to an image stream and then create a new System.Drawing.Bitmap from that stream.
See Save a SoftwareBitmap to a file with BitmapEncoder for sample code. You can render to an InMemoryRandomAccessStream instead of a StorageFile's stream to avoid saving to disk, and can use AsStream to convert it to a .Net System.IO.Stream to read into the System.Drawing.Bitmap something like the following (untested) snippet:
using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
encoder.SetSoftwareBitmap(softwareBitmap);
await encoder.FlushAsync();
bmp = new System.Drawing.Bitmap(stream.AsStream());
}

Conversion of a Bitmap to Pixel Array for Microsoft OCR C#

I'm working with Microsoft's OCR library and am having problems converting the BitmapImage to a pixel array.
I'm making this application for Windows Phone 8, and WriteableBitmap.PixelBuffer.ToArray() isn't an option so I have a static function that'll change a normal BitmapImage into a byte array to feed into the OCR engine.
Well, every time I feed it in the application crashes. What's wrong here?
Here is my static class with the bitmap converter
public static class ByteArrayChange
{
public static byte[] ConvertToBytes(this BitmapImage bitmapImage)
{
byte[] data = null;
using (MemoryStream stream = new MemoryStream())
{
WriteableBitmap wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
data = stream.GetBuffer();
}
return data;
}
}
Here is the piece of code in the OCR method that's causing the application to crash.
byte[] pa = ByteArrayChange.ConvertToBytes(bitmap);
//Here Is he problem
var ocrResult = await ocrEngine.RecognizeAsync((uint)bitmap.PixelHeight, (uint)bitmap.PixelWidth, pa);
What am I doing wrong here?
Thanks!
You're saving your image as JPEG, but I'm fairly certain that OCR library accept RGB/BGRA as an input.
So why don't you use Pixels property? It represents image as BGRA array, so the only thing you need is to convert it to byte[] array.

How to Convert a WriteableBitmap image to Byte array in WinRt App

I want to convert a WriteableBitmap image to a Byte[] array using C# code in Windows store metro style apps.
WriteableBitmap exposes PixelBuffer property of type IBuffer - a Windows Runtime interface which can be converted to a byte array with .NET Streams
byte[] ConvertBitmapToByteArray(WriteableBitmap bitmap)
{
using (Stream stream = bitmap.PixelBuffer.AsStream())
using (MemoryStream memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}

WPF/WinForms/GDI interop: converting a WriteableBitmap to a System.Drawing.Image?

How can I convert a WPF WriteableBitmap object to a System.Drawing.Image?
My WPF client app sends bitmap data to a web service, and the web service needs to construct a System.Drawing.Image on that end.
I know I can get the data of a WriteableBitmap, send the info over to the web service:
// WPF side:
WriteableBitmap bitmap = ...;
int width = bitmap.PixelWidth;
int height = bitmap.PixelHeight;
int[] pixels = bitmap.Pixels;
myWebService.CreateBitmap(width, height, pixels);
But on the web service end, I don't know how to create a System.Drawing.Image from this data.
// Web service side:
public void CreateBitmap(int[] wpfBitmapPixels, int width, int height)
{
System.Drawing.Bitmap bitmap = ? // How can I create this?
}
this blog post shows how to encode your WriteableBitmap as a jpeg image. Perhaps that helps?
If you really want to transfer the raw image data (pixels) you could:
create a System.Drawing.Bitmap with the correct size
iterate over your raw data, convert the raw data to a System.Drawing.Color (e.g. via Color.FromArgb() and set each pixel color in the newly created image via SetPixel()
I'd definitely prefer the first solution (the one described in the blog post).
If your bitmap data is uncompressed, you could probably use this System.Drawing.Bitmap constructor: Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr).
If the bitmap is encoded as jpg or png, create a MemoryStream from the bitmap data, and use it with the Bitmap(Stream) constructor.
EDIT:
Since you're sending the bitmap to a web service, I suggest you encode it to begin with. There are several encoders in the System.Windows.Media.Imaging namespace. For example:
WriteableBitmap bitmap = ...;
var stream = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add( BitmapFrame.Create( bitmap ) );
encoder.Save( stream );
byte[] buffer = stream.GetBuffer();
// Send the buffer to the web service
On the receiving end, simply:
var bitmap = new System.Drawing.Bitmap( new MemoryStream( buffer ) );
Hope that helps.
The question is for WPF, and Pixels does not appear to be a property of WriteableBitmap. Some of the answers here point to SilverLight articles, so I suspect this might be a difference between WPF and SilverLight.

Categories

Resources