【问题标题】:Convert a BitmapImage to byte array in UWP在 UWP 中将 BitmapImage 转换为字节数组
【发布时间】:2016-07-06 14:31:33
【问题描述】:

如何在 UWP 中将 BitmapImage 对象转换为字节数组?在 .Net 中很容易实现,即使在以前的 WinRT 版本中,查看整个互联网但没有成功,其中一个解决方案是使用 WriteableBitmap 就像在这个 answer 中提到的那样,但在当前版本的 UWP ,不可能从 BitmapImage 构造 WriteableBitmap,有什么解决方法吗?

【问题讨论】:

  • 你是如何得到那个 BitmapImage 的?来自 URL 还是什么?
  • @fillobotto :来自一个网址先生,一个网址。
  • 我刚刚阐述了一个答案,在一个空白的 UWP 项目中为我工作
  • 这与以前的 WinRT 版本完全相同。您链接的从 BitmapImage 创建 WritableBitmap 的答案是针对 Windows Phone Silverlight 应用程序,而不是 Windows Phone 运行时应用程序。

标签: c# winrt-xaml win-universal-app bitmapimage


【解决方案1】:

由于您是从图像 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 在谷歌搜索时我发现 MSDN 论坛上的帖子说这是不可能的。如果我再次找到它,我会发布一个链接social.msdn.microsoft.com/Forums/en-US/…
【解决方案2】:

是的,对一个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 是迄今为止最不糟糕的解决方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-19
  • 1970-01-01
  • 2016-04-07
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多