8

I've scoured the web for this and not found a solution yet. I have a DispatchTimer in my Universal phone app. On each tick, I want to capture a portion of the screen and save it to JPEG. My code seems very straightforward, and there are no crashes -- it simply never returns from the FlushAsync(). It seems like it must be a deadlock scenario, but I haven't been able to find where the conflict is yet:

using (var ms = new MemoryStream())
{
    var renderTargetBitmap = new RenderTargetBitmap();
    await renderTargetBitmap.RenderAsync(ctrl);
    var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();

    using (var ras = ms.AsRandomAccessStream())
    {
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, ras, propertySet);

        encoder.SetPixelData(
            BitmapPixelFormat.Bgra8,
            BitmapAlphaMode.Premultiplied,
            (uint) renderTargetBitmap.PixelWidth,
            (uint) renderTargetBitmap.PixelHeight,
            logicalDpi, logicalDpi,
            pixelBuffer.ToArray());

        await encoder.FlushAsync();
    }

    return ms.ToArray();
}

Any help would be great! I've been at this for hours, trying different ways to get it working with no luck.

Arian Kulp
  • 831
  • 8
  • 31

1 Answers1

14

I figured it out! Turns out you can't just use MemoryStream.AsRandomAccessStream() as your encoder destination. Turns out you should just use the InMemoryRandomAccessStream, then afterwards get the bytes:

byte[] bytes = new byte[ras.Size];
await ras.AsStream().ReadAsync(bytes, 0, bytes.Length);
return bytes;

Not sure why MemoryStream caused the problem it did, but this is a pretty easy fix! I hope this helps someone else.

Arian Kulp
  • 831
  • 8
  • 31
  • I have the same problem. Can you share the code snippet as in your questions. I cannot understand where to use the byte array. There is no overload for BitmapEncoder.CreateAsync() receiving byte array instead of random access stream. – IMK Apr 19 '18 at 08:37
  • 2
    Sorry, way too long ago. Looking at the initial code snippet, it looks like switch you have three changes: 1. Change AsRandomAccessStream to .AsInMemoryRandomAccessStream 2. At the end of the "using" block insert this code block with the byte array 3. Just remove the final return (after the using block) since it's not being used anymore. This is way too long ago for me to 100% confident, so just give it a try. – Arian Kulp Apr 19 '18 at 16:10
  • You saved my life! Thanks! – demonplus Dec 14 '18 at 06:56
  • Glad it helped @demonplus! – Arian Kulp Dec 14 '18 at 11:58