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.

Clemens
  • 123,504
  • 12
  • 155
  • 268
gerstla
  • 587
  • 1
  • 5
  • 20

4 Answers4

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;
    }
}
Clemens
  • 123,504
  • 12
  • 155
  • 268
Eirik
  • 4,135
  • 27
  • 29
  • 1
    Actually, I tried this, but it didn't work until I added the lines from the OP on this question: http://stackoverflow.com/questions/35831893/bitmapimage-to-byte-and-reverse : `image.CreateOptions = BitmapCreateOptions.PreservePixelFormat; image.CacheOption = BitmapCacheOption.OnLoad;` - Otherwise I just had a blank image area. – vapcguy Oct 12 '16 at 00:54
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);
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • What is the purpose of `var bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;` – Karl Stephen Jun 16 '21 at 04:42
  • 1
    @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. – Clemens Jun 16 '21 at 05:59
  • 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. – Clemens Jun 16 '21 at 08:16
-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;
}
vapcguy
  • 7,097
  • 1
  • 56
  • 52
-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);
crazylpfan
  • 1,038
  • 7
  • 9