locked
Rendering BitmapEncoder results to a canvas? RRS feed

  • Question

  • I'm trying to find the most efficient way to render the contents of a framebuffer to a canvas and am exploring several routes.  Using createImageData, copying the framebuffer to that image data, then using putImageData has proved to be too slow.  So my next investigation will be seeing if encoding the framebuffer to an image (in-memory of course) and then putting that image directly on the canvas will be any faster.  Here is some sample code I have:

    var stream = new streams.InMemoryRandomAccessStream(); bitmapEncoder.createAsync(bitmapEncoder.pngEncoderId, stream).then( function createSuccess(encoder) { encoder.setPixelData(Windows.Graphics.Imaging.BitmapPixelFormat.bgra8, Windows.Graphics.Imaging.BitmapAlphaMode.ignore, width, height, 1, 1, buffer); encoder.flushAsync().then( function flushSuccess() {

    var dataReader;

    stream.seek(0); dataReader = new streams.DataReader(stream); dataReader.loadAsync(stream.size).then(function () { var img = new Image(); var buffer = dataReader.readBuffer(dataReader.unconsumedBufferLength); img.src = "data:image/png;base64," + Windows.Security.Cryptography.CryptographicBuffer.encodeToBase64String(buffer); canvas2dContext.drawImage(img, left, top); }); }, function flushError(reason) { // Failure. }); }, function createFailure(reason) { // Failure. });

    Everything works pretty well until I get to the point where I am dealing with DataReader; at that point DataReader comes back with no information.  Is there a better way to go from InMemoryRandomAccessStream to the base64-encoded results to be plugged into an Image?



    • Edited by Adam Gross Wednesday, August 15, 2012 3:40 PM
    Wednesday, August 15, 2012 2:51 PM

Answers

  • Hi,

    putImageData is the standard way to manipulate canvas pixels. In most cases it would be fast. You can search for some samples on the web, and run them in IE 10 to test the performance. If you're trying to manipulate a large area of pixel data using a very complex algorithm, the performance issues may be hit. As a workaround, please divide the area into smaller areas. For example, divide a 1000*1000 area into 100 100*100, and manipulate them one by one. You may want to display a progress bar indicating some operation is going on.

    As Jeff point out, you can also use DirectX and WIC, but that forces you to use C++ instead of JavaScript.

    Best Regards,

    Ming Xu.


    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework

    • Marked as answer by Adam Gross Wednesday, September 12, 2012 3:11 PM
    Thursday, August 30, 2012 11:16 AM
    Moderator

All replies

  • As an update, it turns out I was missing a call "stream.seek(0)" before creating the DataReader.  I added it to the code example above for completeness.  However, I have found that this method does not perform well, with the image encoding taking a long amount of time.  So it seems that putImageData is still the best-performing option, even thought it still doesn't perform very well.

    Is there any way that I can optimize this code to make it perform better?  Or is this as good as it's going to get?


    • Edited by Adam Gross Wednesday, August 15, 2012 3:41 PM
    Wednesday, August 15, 2012 3:40 PM
  • If you are running into performance issues, perhaps C++ and DirectX is what you want to use?  It sounds like you are running into limitations of the rendering engine.

    Jeff Sanders (MSFT)

    Friday, August 17, 2012 1:31 PM
    Moderator
  • Hi,

    putImageData is the standard way to manipulate canvas pixels. In most cases it would be fast. You can search for some samples on the web, and run them in IE 10 to test the performance. If you're trying to manipulate a large area of pixel data using a very complex algorithm, the performance issues may be hit. As a workaround, please divide the area into smaller areas. For example, divide a 1000*1000 area into 100 100*100, and manipulate them one by one. You may want to display a progress bar indicating some operation is going on.

    As Jeff point out, you can also use DirectX and WIC, but that forces you to use C++ instead of JavaScript.

    Best Regards,

    Ming Xu.


    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework

    • Marked as answer by Adam Gross Wednesday, September 12, 2012 3:11 PM
    Thursday, August 30, 2012 11:16 AM
    Moderator
  • Thanks, it does turn out that putImageData is fast enough.  Looks like the IE team did a good job of improving performance.
    Wednesday, September 12, 2012 3:11 PM