How can I convert byte[] to BitmapImage?
Asked Answered
S

4

12

I have a byte[] that represents the raw data of an image. I would like to convert it to a BitmapImage.

I tried several examples I found but I kept getting the following exception

"No imaging component suitable to complete this operation was found."

I think it is because my byte[] does not actually represent an Image but only the raw bits. so my question is as mentioned above is how to convert a byte[] of raw bits to a BitmapImage.

Sumption answered 7/3, 2013 at 12:7 Comment(0)
P
9

When your byte array contains a bitmap's raw pixel data, you may create a BitmapSource (which is the base class of BitmapImage) by the static method BitmapSource.Create.

However, you need to specify a few parameters of the bitmap. You must know in advance the width and height and also the PixelFormat of the buffer.

byte[] buffer = ...;

var width = 100; // for example
var height = 100; // for example
var dpiX = 96d;
var dpiY = 96d;
var pixelFormat = PixelFormats.Pbgra32; // for example
var stride = (width * pixelFormat.BitsPerPixel + 7) / 8;

var bitmap = BitmapSource.Create(width, height, dpiX, dpiY,
                                 pixelFormat, null, buffer, stride);
Penultimate answered 7/3, 2013 at 13:31 Comment(3)
What is the purpose of var bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;Favorable
@Karl As the name said, bytes per pixel, rounded up to an integer number from bits per pixel in case that is not an integer multiple of 8. It was meant for the stride calculation, which was however slightly incorrect. I've edited the answer.Penultimate
There is perhaps one more thing to mention. You are free to use a stride as large as you want, provided that it is not less than the value calculated here. That stride must however also be used by the pixel buffer that you pass to the Create method.Penultimate
C
11

The code below does not create a BitmapSource from a raw pixel buffer, as asked in the question.

But in case you want to create a BitmapImage from an encoded frame like a PNG or a JPEG, you would do it like this:

public static BitmapImage LoadFromBytes(byte[] bytes)
{
    using (var stream = new MemoryStream(bytes))
    {
        var image = new BitmapImage();
        image.BeginInit();
        image.CacheOption = BitmapCacheOption.OnLoad;
        image.StreamSource = stream;
        image.EndInit();

        return image;
    }
}
Carnivorous answered 7/3, 2013 at 12:53 Comment(1)
Actually, I tried this, but it didn't work until I added the lines from the OP on this question: #35832393 : image.CreateOptions = BitmapCreateOptions.PreservePixelFormat; image.CacheOption = BitmapCacheOption.OnLoad; - Otherwise I just had a blank image area.Sowers
P
9

When your byte array contains a bitmap's raw pixel data, you may create a BitmapSource (which is the base class of BitmapImage) by the static method BitmapSource.Create.

However, you need to specify a few parameters of the bitmap. You must know in advance the width and height and also the PixelFormat of the buffer.

byte[] buffer = ...;

var width = 100; // for example
var height = 100; // for example
var dpiX = 96d;
var dpiY = 96d;
var pixelFormat = PixelFormats.Pbgra32; // for example
var stride = (width * pixelFormat.BitsPerPixel + 7) / 8;

var bitmap = BitmapSource.Create(width, height, dpiX, dpiY,
                                 pixelFormat, null, buffer, stride);
Penultimate answered 7/3, 2013 at 13:31 Comment(3)
What is the purpose of var bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;Favorable
@Karl As the name said, bytes per pixel, rounded up to an integer number from bits per pixel in case that is not an integer multiple of 8. It was meant for the stride calculation, which was however slightly incorrect. I've edited the answer.Penultimate
There is perhaps one more thing to mention. You are free to use a stride as large as you want, provided that it is not less than the value calculated here. That stride must however also be used by the pixel buffer that you pass to the Create method.Penultimate
S
-1

I ran across this same error, but it was because my array was not getting filled with the actual data. I had an array of bytes that was equal to the length it was supposed to be, but the values were all still 0 - they had not been written to!

My particular issue - and I suspect for others that arrive at this question, as well - was because of the OracleBlob parameter. I didn't think I needed it, and thought I could just do something like:

DataSet ds = new DataSet();
OracleCommand cmd = new OracleCommand(strQuery, conn);
OracleDataAdapter oraAdpt = new OracleDataAdapter(cmd);
oraAdpt.Fill(ds)

if (ds.Tables[0].Rows.Count > 0)
{
    byte[] myArray = (bytes)ds.Tables[0]["MY_BLOB_COLUMN"];
}

How wrong I was! To actually get the real bytes in that blob, I needed to actually read that result into an OracleBlob object. Instead of filling a dataset/datatable, I did this:

OracleBlob oBlob = null;
byte[] myArray = null;
OracleCommand cmd = new OracleCommand(strQuery, conn);
OracleDataReader result = cmd.ExecuteReader();
result.Read();

if (result.HasRows)
{
    oBlob = result.GetOracleBlob(0);
    myArray = new byte[oBlob.Length];
    oBlob.Read(array, 0, Convert.ToInt32(myArray.Length));
    oBlob.Erase();
    oBlob.Close();
    oBlob.Dispose();
}

Then, I could take myArray and do this:

if (myArray != null)
{
   if (myArray.Length > 0)
   {
       MyImage.Source = LoadBitmapFromBytes(myArray);
   }
}

And my revised LoadBitmapFromBytes function from the other answer:

public static BitmapImage LoadBitmapFromBytes(byte[] bytes)
{
    var image = new BitmapImage();
    using (var stream = new MemoryStream(bytes))
    {
        stream.Seek(0, SeekOrigin.Begin);
        image.BeginInit();
        image.StreamSource = stream;
        image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
        image.CacheOption = BitmapCacheOption.OnLoad;
        image.UriSource = null;
        image.EndInit();
    }

    return image;
}
Sowers answered 12/10, 2016 at 1:25 Comment(0)
L
-3

Create a MemoryStream from the raw bytes and pass that into your Bitmap constructor.

Like this:

MemoryStream stream = new     MemoryStream(bytes);
Bitmap image = new Bitmap(stream);
Lydell answered 7/3, 2013 at 12:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.