Question

We have a binary file on client. It's scaned page from book which come to client somehow compressed. We have a decoder(on client), which output a TypedArray which contains BMP data file. We need to render it, as fast as possible. BMP size is about 3000000 bytes(after decoding, it's length of returned typedArray). We tried a lot of solutions but on slow PCs it didn't work. For example fastest way which we found: We build blob from TypedArray. Create URL to this blob and specify it as src attribute on image source. It tooks about 22000ms to render 20 pages. Also we tried to render it in base64 with data: URL specified in src tag also(34000ms). We tried to render it on canvas. But there are problems such as we use drawImage on canvas which require loaded image object. May be some how we can render it with WebGL with hardware acceleration?

PS In the time included decode time which are the same in all cases.

PS I can attach code samples which we tried.

Was it helpful?

Solution

I'm not sure what you mean by BMP file until you mean the Microsoft BMP format.

I don't know all the details of that format but if you're decoding it by hand into pixels in JavaScript you can display the decoded data directly by uploading it to a texture in WebGL and then rendering a quad with the texture.

There are example all over the net about how to render a textured quad in WebGL. Here's one

You'd upload your data to a texture with

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 
              widthOfImageInPixels, heightOfImagePixels, 0
              gl.RGBA, gl.UNSIGNED_BYTE, someUint8ArrayWithWidthByHeightPixels);

Note that if your pixels are not RGB or RGBA, like a say they are YUV or something you can create a shader to display them directly rather than convert them in JavaScript to RGB/RGBA

OTHER TIPS

The Laws of Physics always apply:

Large Images take longer to download than small images.

As a workaround, how about the "old-fashioned" approach.

Intially show a "lossy" version of your book page (a small .jpg perhaps).

var imgJPG=new Image();
imgJPG.onload=start;
imgJPG.src="yourBookPage.JPG";

function start(){
    context.drawImage(imgJPG,0,0);
}

At the same time begin an asynchronous download of your large .bmp

var imgPNG=new Image();
imgPNG.onload=start;
imgPNG.src="yourBookPage.bmp";

When the large image is fully loaded, replace the .jpg image with the .bmp image

function start(){
    context.clearRect(0,0,canvas.width,canvas.height);
    context.drawImage(imgPNG,0,0);
}

If the user is adding drawings before the .bmp is loaded, you can let them draw on a separate canvas directly on top of the .jpg canvas. Then when the .bmp is loaded you can combine the existing drawings on top of the newly loaded .bmp

context.clearRect(0,0,canvas.width,canvas.height);

// draw the .png in the background

context.drawImage(imgPNG,0,0);

// add any user drawings on top

context.drawImage(theTempDrawingCanvasWithManyUserDrawings,0,0);

Good luck with your project!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top