【问题标题】:How to create WriteableBitmap from BitmapImage?如何从 BitmapImage 创建 WriteableBitmap?
【发布时间】:2013-02-05 23:23:37
【问题描述】:

我可以从 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);

这样对吗?

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      Filip 指出,将图像读取到 WriteableBitmap 的工作方式如下:

      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 和 IIRC 的原始 Uri 工作,它仅适用于 appx 中的 BitmapImages。在您的情况下,甚至没有 Uri,因为从图片文件夹加载只能通过从流加载来完成,因此您的选项从最快到最慢(我认为)是:

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

        我认为选项 2 可能比选项 3 更快,因为您避免对压缩图像进行两次解码。

        【讨论】:

        • 感谢您的回答,但是如何从一开始就将图像打开为可写位图,?我认为this 可能会有所帮助,但我不能不能将位图直接传递给可写位图。
        • 不,该链接适用于 Silverlight。您需要为您的图像获取一个 StorageFile,例如使用文件选择器,然后等待 OpenReadAsync,然后创建一个 1x1 WriteableBitmap 并等待 SetSourceAsync。检查此示例/扩展:winrtxamltoolkit.codeplex.com/SourceControl/changeset/view/…
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多