Cristiano Ghersi
Cristiano Ghersi

Reputation: 2122

How to use CanvasBitmap.CreateFromBytes with a byte[] coming from a jpg image

I have a JPG image available as a byte[] in memory.

I need to create a CanvasBitmap to draw this image that ultimately creates a CompositionDrawingSurface that I can assign to my SpriteVisual. And I need a super-fast method to do this!!

I accomplished the task successfully using CanvasBitmap.LoadAsync(ICanvasResourceCreator, IRandomAccessStream), but this approach takes too much (more than 10 milliseconds), while using CanvasBitmap.CreateFromBytes(ICanvasResourceCreator, byte[], int, int, DirectXPixelFormat) it just takes 1 millisecond, which is ok with my performance requirements.

Unfortunately, using CanvasBitmap.CreateFromBytes the result is not the correct image, but rather a cloud of dots, which makes me thinking there is a problem in the encoding / decoding of the image.

Here's the code I tried:

byte[] imgBytes = await ReadBinaryFile(path); // read the binary content of a JPG image, for the example purpose (in the real environment, the byte[] comes from in memory caches...)

using (CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromBytes(s_canvasDevice, imgBytes, 600, 800, DirectXPixelFormat.B8G8R8A8UIntNormalized))
{
    // Draw the image to the surface
    using (CanvasDrawingSession session = CanvasComposition.CreateDrawingSession(surface))
    {
        session.Clear(Color.FromArgb(0, 0, 0, 0));
        session.DrawImage(canvasBitmap, new Rect(0, 0, 600, 800), new Rect(0, 0, 600, 800));
    }
}

What am I missing? How can I treat the byte[] imgBytes so that it can be useful as input of CanvasBitmap.CreateFromBytes?

Thank you!

Upvotes: 1

Views: 827

Answers (1)

nbura
nbura

Reputation: 388

You need to convert from JPEG (compressed) format to raw byte array first. You can't directly read a JPEG image off disk with ReadBinaryFile() and display it.

I'm guessing that much of the performance issue is coming from the time it takes for LoadAsync() to decompress the JPEG. You could probably improve performance by saving in a different, uncompressed image format.


Also, if you really do need to read JPEGs, or if it's still slow even with other image formats: There might be some way to make use of LoadAsync() to load multiple files in parallel. But I don't know how to do this, and it might not be that helpful if you're being bottlenecked by the file I/O anyways. Just a thought.

Upvotes: 1

Related Questions