如何将byte[]转换为BitmapImage?

12
我有一个代表图像原始数据的byte[],我想将其转换为BitmapImage
我尝试了几个我找到的示例,但我一直收到以下异常:
“未找到适合完成此操作的成像组件。”
我认为这是因为我的byte[]实际上并不代表图像,而只是原始位。 所以我的问题如上所述,如何将原始位的byte[]转换为BitmapImage
4个回答

11
以下代码不会从原始像素缓冲区创建BitmapSource,与问题中所要求的不同。
但是,如果您想从编码帧(如PNG或JPEG)创建BitmapImage,则可以按照以下方式执行:
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;
    }
}

1
实际上,我尝试过这个方法,但是直到我添加了这个问题中的原始帖子中的代码行之后,它才起作用:http://stackoverflow.com/questions/35831893/bitmapimage-to-byte-and-reverse: image.CreateOptions = BitmapCreateOptions.PreservePixelFormat; image.CacheOption = BitmapCacheOption.OnLoad; - 否则我只会得到一个空白图像区域。 - vapcguy

9
当您的字节数组包含位图的原始像素数据时,您可以使用静态方法BitmapSource.Create创建一个BitmapSource(这是BitmapImage的基类)。
但是,您需要指定位图的一些参数。您必须预先知道缓冲区的宽度和高度以及PixelFormat
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);

var bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8; 的目的是什么? - Karl Stephen
1
@Karl 如其名,每像素字节数,从每像素位数四舍五入为整数,以防它不是8的倍数。它旨在计算步幅,但是步幅计算有些错误。我已经编辑了答案。 - Clemens
或许还有一件事需要提到。只要步幅不小于此处计算的值,您可以自由地使用任意大的步幅。然而,该步幅也必须被传递给 Create 方法所使用的像素缓冲区。 - Clemens

-1

我遇到了同样的错误,但是因为我的数组没有被实际数据填充。我有一个字节数组,长度应该是正确的,但是值仍然都是0 - 它们还没有被写入!

我的特定问题 - 我怀疑其他人也会遇到这个问题 - 是由于OracleBlob参数引起的。我认为我不需要它,以为我可以像下面这样做:

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"];
}

我错了!为了获取那个 blob 中的真实字节,我需要将结果读入一个 OracleBlob 对象中。而不是填充数据集/数据表,我应该这样做:

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();
}

然后,我可以取出myArray并执行以下操作:

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

而我的修改后的LoadBitmapFromBytes函数来自于另一个答案:

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;
}

-3

从原始字节创建一个MemoryStream,并将其传递到Bitmap构造函数中。

像这样:

MemoryStream stream = new     MemoryStream(bytes);
Bitmap image = new Bitmap(stream);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接