C# 4.0 如何从位图创建可写位图?

C# 4.0 如何从位图创建可写位图?,c#-4.0,windows-8,windows-runtime,writeablebitmap,C# 4.0,Windows 8,Windows Runtime,Writeablebitmap,我可以从资源中的图片创建WriteableBitmap Uri imageUri1 = new Uri("ms-appx:///Assets/sample1.jpg"); WriteableBitmap writeableBmp = await new WriteableBitmap(1, 1).FromContent(imageUri1); 但是,我无法从图片目录创建WriteableBitmap(我正在使用) 这是否正确?WriteableBitMapFromBitMapImage Ext

我可以从资源中的图片创建WriteableBitmap

Uri imageUri1 = new Uri("ms-appx:///Assets/sample1.jpg");
WriteableBitmap writeableBmp = await new WriteableBitmap(1, 1).FromContent(imageUri1);
但是,我无法从图片目录创建WriteableBitmap(我正在使用)


这是否正确?

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

  • 从一开始就以
    WriteableBitmap
    的形式打开图像,这样就不需要重新打开它或复制周围的位
  • 如果需要两份副本,请将其作为
    WriteableBitmap
    打开,然后创建一个大小相同的新
    WriteableBitmap
    ,并复制像素缓冲区
  • 如果需要两个副本,请跟踪用于打开第一个位图的路径,然后从与原始位图相同的文件加载新的
    WriteableBitmap

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

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

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

    以下是将图像读取到可写位图的方法,正如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模式可写位图使用的,我通过了

    感谢您的回答,但是如何从一开始就以writeablebitmap的形式打开图像呢,?我认为这可能会有帮助,但我不能将位图直接传递到可写位图中。不,该链接适用于Silverlight。您需要为映像获取一个存储文件,例如,使用文件选择器,然后等待OpenReadAsync,然后创建1x1可写位图并等待SetSourceAsync。检查此示例/扩展:
    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);
       }
    }