2

I'm trying to Invert color of a page in my UWP pdf reader (using Windows.Data.Pdf) .

Piece of my code:

using Windows.Data.Pdf;

private PdfPageRenderOptions _ro;
private PdfPage _page;
private WriteableBitmap wb;

...

private async void InvertPage() {
    using(var stream = new InMemoryRandomAccessStream()) {
        await _page.RenderToStreamAsync(stream,_ro);
        await wb.SetSourceAsync(stream);
        // also tried wb.SetSource(stream);

        wb.Invert(); // ERROR IN HERE 

   }
}

I have not problem in Getting images as normal (No Inverting) or inverting Pixels byte by byte but it's toooo slow so I'm trying to Invert using Invert() in Windows.UI.Xaml.Media.Imaging.WriteableBitmap but it throws an exception!

{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}

ERROR


HINT:

When I use await _page.RenderToStreamAsync(stream); instead , everything works fine. (but It's necessary to include PdfPageRenderOptions in stream)

Shahriar
  • 939
  • 1
  • 14
  • 36
  • Don't you have to set the [`Position`](https://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.streams.inmemoryrandomaccessstream.position.aspx) of the stream to `0` after writing, before setting is as the source for the WritableBitmap? – Kris Vandermotten Dec 05 '15 at 15:46
  • @KrisVandermotten Nothing changed! I tried `stream.Seek(0);` (stream.Position just got getter option) – Shahriar Dec 05 '15 at 19:18

1 Answers1

0

A couple of notes here:

  1. Invert is not a member of Windows.UI.Xaml.Media.Imaging.WriteableBitmap. You are probably using WriteableBitmapEx which provides Invert() as an extension method.
  2. WriteableBitmapEx's Invert returns the newly inverted WriteableBitmap. It doesn't invert in place.
  3. WriteableBitmapEx provides a FromStream helper to create a WriteableBitmap from a stream.

With those in mind, you can rewrite InvertPage something like the following. Since Invert creates a new WriteableBitmap this version is async and returns the new bitmap so that the caller can set it to whatever property feeds the displaying Image.

private async Task<WriteableBitmap> InvertPageAsync()
{
    using (var stream = new InMemoryRandomAccessStream())
    {
        await _page.RenderToStreamAsync(stream, _ro);

        // Use WriteableBitmapEx's FromStream
        WriteableBitmap newWb = await wb.FromStream(stream);

        return newWb.Invert(); // ERROR IN HERE 
    }
}


async Task UpdatePdf()
{
    // Load the document, page, etc. and PreparePageAsync
    // ...
    // ...

    // Invert the page and show it in pageImage
    pageImage.Source = await InvertPageAsync();
}

Looping through the pixels individually will be exceptionally slow if you use WriteableBitmapEx's SetPixel without a GetBitmapContext block. WriteableBitmapEx needs to extract the WriteableBitmap's PixelBuffer to set a pixel. If you use GetBitmapContext it will do so once for all of the calls before the BitmapContext is disposed. If you don't call GetBitmapContext then it will need to get the PixelBuffer for each SetPixel call.

Rob Caplan - MSFT
  • 21,714
  • 3
  • 32
  • 54