How to create WriteableBitmap from BitmapImage?
Asked Answered
Z

3

7

I could create WriteableBitmap from pictures in Assets.

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

but, I can't create WriteableBitmap from Pictures Directory,(I'm using 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);

Is this correct ?

Zincograph answered 5/2, 2013 at 23:23 Comment(0)
F
6

This is a total contrivance, but it does seem to work ...

// 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);
Ftc answered 6/2, 2013 at 6:0 Comment(0)
L
4

Here's the way reading an image to a WriteableBitmap works as Filip noted:

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

Note that I am using the pixel format and alpha mode Writeable Bitmap uses and that I pass .

Lithographer answered 6/2, 2013 at 7:22 Comment(0)
I
3

WriteableBitmapFromBitmapImageExtension.FromBitmapImage() works by using the original Uri used to load BitmapImage and IIRC it only works with BitmapImages from the appx. In your case there isn't even a Uri since loading from Pictures folder can only be done by loading from stream, so your options from the fastest to slowest (I think) are:

  1. Open the image as WriteableBitmap from the get go, so that you don't need to reopen it or copy bits around.
  2. If you need to have two copies - open it as WriteableBitmap and then create a new WriteableBitmap of same size and copy the pixel buffer.
  3. If you need to have two copies - track the path used to open the first bitmap and then create a new WriteableBitmap by loading it from the same file as the original one.

I think option 2 might be faster than option 3 since you avoid decoding a compressed image twice.

Institution answered 6/2, 2013 at 2:10 Comment(2)
Thank you for answering, but how to open image as writeablebitmap from the get go,? I think this may be helpful, but I cant't cannot pass a bitmap directly into a writablebitmap .Zincograph
No that link is for Silverlight. You need to get a StorageFile for your image e.g. using a file picker, then await OpenReadAsync, then create a 1x1 WriteableBitmap and await SetSourceAsync. Check this for sample/extensions: winrtxamltoolkit.codeplex.com/SourceControl/changeset/view/…Institution

© 2022 - 2024 — McMap. All rights reserved.