在UWP中将BitmapImage转换为字节数组

8
如何在UWP中将BitmapImage对象转换为字节数组?在.Net中很容易实现,甚至在之前的WinRT版本中也是如此。我在互联网上搜索了很久,但没有成功。其中一个解决方案是使用WriteableBitmap,就像在答案中提到的那样,但在当前版本的UWP中,无法将BitmapImage构造成WriteableBitmap。有什么解决方法吗?

你是怎么获得那个BitmapImage的?从URL获取还是其他方式? - fillobotto
1
@fillobotto:从一个网址,一个网页网址。 - AymenDaoudi
我刚刚详细阐述了一个答案,这个答案在一个空的UWP项目中对我有效。 - fillobotto
可能是将BitmapImage转换为Windows Phone 8.1 Runtime中的byte[]数组的重复问题。 - Rob Caplan - MSFT
这与之前的WinRT版本完全相同。您链接的答案创建一个WritableBitmap从BitmapImage,但是适用于Windows Phone Silverlight应用程序,而不是Windows Phone Runtime应用程序。 - Rob Caplan - MSFT
你的问题不太清楚。你是想编码位图(例如 PNG),还是只是访问原始像素数据?无论如何,在你的情况下(图像源是 web url),一个可能的方法是手动进行 web 请求以获取编码的位图缓冲区(从 web 响应中),然后从响应缓冲区创建 BitmapImage 并保留缓冲区以供以后使用。 - Clemens
2个回答

12

既然你从图像url开始,我唯一能想到的方法就是获取图像的流。为此,RandomAccessStreamReference.CreateFromUri() 方法非常有用。

Windows.Storage.Streams.IRandomAccessStream random = await Windows.Storage.Streams.RandomAccessStreamReference.CreateFromUri(new Uri("http://...")).OpenReadAsync();

那么我们必须解码流以便能够读取所有像素以备后用。

Windows.Graphics.Imaging.BitmapDecoder decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(random);
Windows.Graphics.Imaging.PixelDataProvider pixelData = await decoder.GetPixelDataAsync();

最后,您可以这样访问像素缓冲区。

byte[] bytes = pixelData.DetachPixelData();

有没有办法在不通过 URL 的情况下直接转换 BitmapImage 对象本身?场景很难解释... - AymenDaoudi
2
@AymenDaoudi 在谷歌上搜索时,我发现了一篇来自 MSDN 论坛的帖子,称这是不可能的。如果我再次找到它,我会发布一个链接 https://social.msdn.microsoft.com/Forums/en-US/8974f4a4-f116-499b-ad00-e0c8a00a6494/convert-bitmapimage-to-byte?forum=winappswithcsharp - fillobotto

4

是的,将其转换为byte[]并不太复杂,我认为你可以做到。但我希望它更简单,但事实并非如此。

http://codepaste.net/ijx28i

这段代码实际上更进一步,将byte[]转换为Base64字符串(用于序列化),但你可以忽略这个额外的步骤,对吗?

// using System.Runtime.InteropServices.WindowsRuntime;

private async Task<string> ToBase64(Image control)
{
    var bitmap = new RenderTargetBitmap();
    await bitmap.RenderAsync(control);
    return await ToBase64(bitmap);
}

private async Task<string> ToBase64(WriteableBitmap bitmap)
{
    var bytes = bitmap.PixelBuffer.ToArray();
    return await ToBase64(bytes, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight);
}

private async Task<string> ToBase64(StorageFile bitmap)
{
    var stream = await bitmap.OpenAsync(Windows.Storage.FileAccessMode.Read);
    var decoder = await BitmapDecoder.CreateAsync(stream);
    var pixels = await decoder.GetPixelDataAsync();
    var bytes = pixels.DetachPixelData();
    return await ToBase64(bytes, (uint)decoder.PixelWidth, (uint)decoder.PixelHeight, decoder.DpiX, decoder.DpiY);
}

private async Task<string> ToBase64(RenderTargetBitmap bitmap)
{
    var bytes = (await bitmap.GetPixelsAsync()).ToArray();
    return await ToBase64(bytes, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight);
}

private async Task<string> ToBase64(byte[] image, uint height, uint width, double dpiX = 96, double dpiY = 96)
{
    // encode image
    var encoded = new InMemoryRandomAccessStream();
    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, encoded);
    encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, height, width, dpiX, dpiY, image);
    await encoder.FlushAsync();
    encoded.Seek(0);

    // read bytes
    var bytes = new byte[encoded.Size];
    await encoded.AsStream().ReadAsync(bytes, 0, bytes.Length);

    // create base64
    return Convert.ToBase64String(bytes);
}

private async Task<ImageSource> FromBase64(string base64)
{
    // read stream
    var bytes = Convert.FromBase64String(base64);
    var image = bytes.AsBuffer().AsStream().AsRandomAccessStream();

    // decode image
    var decoder = await BitmapDecoder.CreateAsync(image);
    image.Seek(0);

    // create bitmap
    var output = new WriteableBitmap((int)decoder.PixelHeight, (int)decoder.PixelWidth);
    await output.SetSourceAsync(image);
    return output;
}

这是重要的部分:
var bytes = (await bitmap.GetPixelsAsync()).ToArray();

我想你可能会喜欢看到它的上下文。

祝你好运。


我已经搜索和尝试了几个小时,这是我找到的唯一有用的东西。当StorageFile或uri不可用时,需要将Image.Source转换为CanvasBitmap以进行Win2D动画。真是疯狂,居然没有其他方法可以做到这一点。RenderTargetBitmap是迄今为止最不可行的解决方法。 - Sean O'Neil

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