如何从BitmapImage创建WriteableBitmap?

7

我可以从Assets中的图片创建WriteableBitmap。

Uri imageUri1 = new Uri("ms-appx:///Assets/sample1.jpg");
WriteableBitmap writeableBmp = await new WriteableBitmap(1, 1).FromContent(imageUri1);

但是,我无法从图片目录创建WriteableBitmap(我正在使用WinRT XAML工具包)。

//open image
StorageFolder picturesFolder = KnownFolders.PicturesLibrary;
StorageFile file = await picturesFolder.GetFileAsync("sample2.jpg");
var stream = await file.OpenReadAsync();

//create bitmap
BitmapImage bitmap2 = new BitmapImage();
bitmap2.SetSource();
bitmap2.SetSource(stream);

//create WriteableBitmap, but cannot
WriteableBitmap writeableBmp3 = 
    await WriteableBitmapFromBitmapImageExtension.FromBitmapImage(bitmap2);

这是正确的吗?

3个回答

6

这是一个完全虚构的东西,但它似乎确实起作用...

// load a jpeg, be sure to have the Pictures Library capability in your manifest
var folder = KnownFolders.PicturesLibrary;
var file = await folder.GetFileAsync("test.jpg");
var data = await FileIO.ReadBufferAsync(file);

// create a stream from the file
var ms = new InMemoryRandomAccessStream();
var dw = new Windows.Storage.Streams.DataWriter(ms);
dw.WriteBuffer(data);
await dw.StoreAsync();
ms.Seek(0);

// find out how big the image is, don't need this if you already know
var bm = new BitmapImage();
await bm.SetSourceAsync(ms);

// create a writable bitmap of the right size
var wb = new WriteableBitmap(bm.PixelWidth, bm.PixelHeight);
ms.Seek(0);

// load the writable bitpamp from the stream
await wb.SetSourceAsync(ms);

4
以下是关于读取图像到WriteableBitmap的方法,正如Filip所指出的:
StorageFile imageFile = ...

WriteableBitmap writeableBitmap = null;
using (IRandomAccessStream imageStream = await imageFile.OpenReadAsync())
{
   BitmapDecoder bitmapDecoder = await BitmapDecoder.CreateAsync(
      imageStream);

   BitmapTransform dummyTransform = new BitmapTransform();
   PixelDataProvider pixelDataProvider =
      await bitmapDecoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8, 
      BitmapAlphaMode.Premultiplied, dummyTransform, 
      ExifOrientationMode.RespectExifOrientation,
      ColorManagementMode.ColorManageToSRgb);
   byte[] pixelData = pixelDataProvider.DetachPixelData();

   writeableBitmap = new WriteableBitmap(
      (int)bitmapDecoder.OrientedPixelWidth,
      (int)bitmapDecoder.OrientedPixelHeight);
   using (Stream pixelStream = writeableBitmap.PixelBuffer.AsStream())
   {
      await pixelStream.WriteAsync(pixelData, 0, pixelData.Length);
   }
}

请注意,我正在使用可写位图使用的像素格式和alpha模式,并且我传递。

3
WriteableBitmapFromBitmapImageExtension.FromBitmapImage()函数通过使用用于加载BitmapImage的原始Uri进行工作,并且我IRC它仅适用于来自appx的BitmapImage。 在您的情况下,甚至没有Uri,因为只能通过从流中加载来自Pictures文件夹的内容,因此您的选项从最快到最慢(我认为)是:

  1. 从一开始就将图像作为WriteableBitmap打开,这样您就不需要重新打开它或复制位。
  2. 如果您需要两个副本-将其作为WriteableBitmap打开,然后创建一个相同大小的新WriteableBitmap并复制像素缓冲区。
  3. 如果您需要两个副本-跟踪用于打开第一个位图的路径,然后通过从与原始文件相同的文件中加载它来创建一个新的WriteableBitmap

我认为选项2可能比选项3更快,因为您避免了两次解码压缩图像的过程。


谢谢您的回答,但是如何从一开始就将图像打开为可写位图呢?我认为这个可能会有所帮助,但我无法直接将位图传递到可写位图中。 - hiroo
不,那个链接是关于Silverlight的。你需要获取一个StorageFile来存储你的图像,例如使用文件选择器,然后等待OpenReadAsync,接着创建一个1x1的WriteableBitmap并等待SetSourceAsync。请查看此链接以获取示例/扩展:http://winrtxamltoolkit.codeplex.com/SourceControl/changeset/view/4d568d4e4c6a#WinRTXamlToolkit/Imaging/WriteableBitmapLoadExtensions.cs - Filip Skakun

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