如何从BitmapImage创建WriteableBitmap?

时间:2013-02-05 23:23:38

标签: c#-4.0 windows-8 windows-runtime writeablebitmap

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

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

但是,我无法从图片目录创建WriteableBitmap,(我正在使用WinRT XAML Toolkit

//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 个答案:

答案 0 :(得分:5)

这是一个完全的设计,但似乎确实有效......

// 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);

答案 1 :(得分: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模式可写位图使用并且我通过了。

答案 2 :(得分:3)

WriteableBitmapFromBitmapImageExtension.FromBitmapImage()通过使用用于加载BitmapImage和IIRC的原始Uri工作,它只能与appx中的BitmapImage一起使用。在你的情况下,甚至没有Uri,因为从图片文件夹加载只能通过从流加载来完成,所以你从最快到最慢的选项(我认为)是:

  1. 从开始使用WriteableBitmap打开图片,这样您就不需要重新打开或复制位了。
  2. 如果您需要两份副本 - 将其打开为WriteableBitmap,然后创建一个相同大小的新WriteableBitmap并复制像素缓冲区。
  3. 如果您需要两份副本 - 跟踪用于打开第一个位图的路径,然后通过从原始位图加载它来创建新的WriteableBitmap
  4. 我认为选项2可能比选项3更快,因为您避免对压缩图像进行两次解码。