locked
Sharing a WriteableBitmap RRS feed

  • Question

  • I have WriteableBitmap which the user modifies, and now I would like to implement the functionality of sharing that WriteableBitmap, preferably as a PNG. How should I proceed to do so? 'Sharing content source app sample' only handles the sharing of images loaded using StorageFile.

    So far I am stuck at converting either WriteableBitmap, Stream or byte[] to the RandomAccessStreamReference required by DataPackage.RequestData.

    Wednesday, June 27, 2012 9:04 PM

Answers

  • You can encode the contents of a WriteableBitmap with the BitmapEncoder object:
                FileSavePicker picker = new FileSavePicker();
                picker.FileTypeChoices.Add("PNG File", new List<string>() { ".png" });
                StorageFile file = await picker.PickSaveFileAsync();
    
                IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite);
                BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
                Stream pixelStream = bmp.PixelBuffer.AsStream();
                byte[] pixels = new byte[pixelStream.Length];
                await pixelStream.ReadAsync(pixels, 0, pixels.Length);
    
                encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint) bmp.PixelWidth, (uint) bmp.PixelHeight,96.0,96.0, pixels);
                await encoder.FlushAsync();
      
    --Rob
    • Marked as answer by Advecticity Tuesday, July 3, 2012 12:34 AM
    Wednesday, June 27, 2012 9:12 PM
    Moderator
  • After taking a break and working on other parts of the program, I came back and found the problem. As you explain in another one of your answers, code containing async calls need to use a deferral for sharing. My code was modified as such, if anyone else has the same problem :

    DataRequestDeferral deferral = args.Request.GetDeferral();
    
    // Sharing procedure...
    
    deferral.Complete();

    And everything worked fine afterwards.

    • Marked as answer by Advecticity Tuesday, July 3, 2012 12:34 AM
    Tuesday, July 3, 2012 12:34 AM

All replies

  • You can encode the contents of a WriteableBitmap with the BitmapEncoder object:
                FileSavePicker picker = new FileSavePicker();
                picker.FileTypeChoices.Add("PNG File", new List<string>() { ".png" });
                StorageFile file = await picker.PickSaveFileAsync();
    
                IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite);
                BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
                Stream pixelStream = bmp.PixelBuffer.AsStream();
                byte[] pixels = new byte[pixelStream.Length];
                await pixelStream.ReadAsync(pixels, 0, pixels.Length);
    
                encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint) bmp.PixelWidth, (uint) bmp.PixelHeight,96.0,96.0, pixels);
                await encoder.FlushAsync();
      
    --Rob
    • Marked as answer by Advecticity Tuesday, July 3, 2012 12:34 AM
    Wednesday, June 27, 2012 9:12 PM
    Moderator
  • Hey Rob, thank you for answering.

    Is there any way to do this without going through the filepicker? The writeablebitmap in question is displayed fullscreen so it seems like unneccessary clicks for the user.

    Thanks

    Wednesday, June 27, 2012 10:08 PM
  • The FilePicker was just an easy way to get a stream for demonstration (especially since I already had that code snippet handy). The important part is the BitmapEncoder. You can initialize the BitmapEncoder with any IRandomAccessStream. You can use an InMemoryRandomAccessStream, a StorageFile in your temp directory, etc.

    --Rob

    Wednesday, June 27, 2012 10:13 PM
    Moderator
  • I have tried the following

    DataPackage requestData = args.Request.Data; requestData.Properties.Title = "Title"; IRandomAccessStream stream = new InMemoryRandomAccessStream(); BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream); Stream pixelStream = wBitmap.PixelBuffer.AsStream(); byte[] pixels = new byte[pixelStream.Length]; await pixelStream.ReadAsync(pixels, 0, pixels.Length); encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)wBitmap.PixelWidth, (uint)wBitmap.PixelHeight, 96.0, 96.0, pixels); requestData.SetBitmap(RandomAccessStreamReference.CreateFromStream(stream));

    await encoder.FlushAsync();

    However, when I attempt to share, the charms bar displays the message "There was a problem with the data from [your app]".

    If I remove 

    requestData.Properties.Title = "Title";

    Then the message becomes "Nothing to share right now".

    Am I doing something wrong?

    Note : I don't think the WriteableBitmap is the problem here, as I can save it to disk without any problems.
    • Edited by Advecticity Wednesday, June 27, 2012 11:17 PM
    Wednesday, June 27, 2012 11:15 PM
  • After taking a break and working on other parts of the program, I came back and found the problem. As you explain in another one of your answers, code containing async calls need to use a deferral for sharing. My code was modified as such, if anyone else has the same problem :

    DataRequestDeferral deferral = args.Request.GetDeferral();
    
    // Sharing procedure...
    
    deferral.Complete();

    And everything worked fine afterwards.

    • Marked as answer by Advecticity Tuesday, July 3, 2012 12:34 AM
    Tuesday, July 3, 2012 12:34 AM
  •  Hi  I have same problem can yor give me full code.....
    • Proposed as answer by Raindra Verma Thursday, December 13, 2012 4:55 AM
    • Unproposed as answer by Raindra Verma Thursday, December 13, 2012 4:56 AM
    Thursday, December 13, 2012 4:54 AM