Javascript 渲染bmp文件的最快方法

Javascript 渲染bmp文件的最快方法,javascript,canvas,binary,webgl,blob,Javascript,Canvas,Binary,Webgl,Blob,客户端上有一个二进制文件。它是从书中扫描出来的一页,以某种方式被压缩。我们有一个解码器(在客户端),它输出一个包含BMP数据文件的TypedArray。我们需要尽快渲染它。BMP大小约为3000000字节(解码后,其长度为返回的typedArray)。我们尝试了很多解决方案,但在速度较慢的PC上,却无法奏效。例如,我们发现的最快的方法是:从TypedArray构建blob。创建指向此blob的URL,并将其指定为图像源上的src属性。渲染20页需要大约22000毫秒。此外,我们还尝试在base6

客户端上有一个二进制文件。它是从书中扫描出来的一页,以某种方式被压缩。我们有一个解码器(在客户端),它输出一个包含BMP数据文件的TypedArray。我们需要尽快渲染它。BMP大小约为3000000字节(解码后,其长度为返回的typedArray)。我们尝试了很多解决方案,但在速度较慢的PC上,却无法奏效。例如,我们发现的最快的方法是:从TypedArray构建blob。创建指向此blob的URL,并将其指定为图像源上的src属性。渲染20页需要大约22000毫秒。此外,我们还尝试在base64中使用src标记(34000ms)中指定的data:URL呈现它。我们试图在画布上渲染它。但也存在一些问题,例如我们在画布上使用drawImage,这需要加载图像对象。可能是我们如何用硬件加速的WebGL渲染它

时间中的PS包括在所有情况下相同的解码时间

PS我可以附上我们尝试过的代码示例。

物理定律始终适用:

下载大型图像比下载小型图像需要更长的时间

作为一种变通方法,“老式”方法如何

首先显示您的书页的“有损”版本(可能是一个小的.jpg)。

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

function start(){
    context.drawImage(imgJPG,0,0);
}
同时开始异步下载您的大型.bmp

var imgPNG=new Image();
imgPNG.onload=start;
imgPNG.src="yourBookPage.bmp";
当大图像完全加载时,将.jpg图像替换为.bmp图像

function start(){
    context.clearRect(0,0,canvas.width,canvas.height);
    context.drawImage(imgPNG,0,0);
}
如果用户在加载.bmp之前添加图形,则可以让它们直接在.jpg画布上的单独画布上绘制。然后,当加载.bmp时,可以将现有图形合并到新加载的.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);
祝你的项目好运

物理定律始终适用:

下载大型图像比下载小型图像需要更长的时间

作为一种变通方法,“老式”方法如何

首先显示您的书页的“有损”版本(可能是一个小的.jpg)。

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

function start(){
    context.drawImage(imgJPG,0,0);
}
同时开始异步下载您的大型.bmp

var imgPNG=new Image();
imgPNG.onload=start;
imgPNG.src="yourBookPage.bmp";
当大图像完全加载时,将.jpg图像替换为.bmp图像

function start(){
    context.clearRect(0,0,canvas.width,canvas.height);
    context.drawImage(imgPNG,0,0);
}
如果用户在加载.bmp之前添加图形,则可以让它们直接在.jpg画布上的单独画布上绘制。然后,当加载.bmp时,可以将现有图形合并到新加载的.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);

祝你的项目好运

我不知道你说的BMP文件是什么意思,直到你指的是

我不知道该格式的所有细节,但如果你用JavaScript手工将其解码为像素,你可以直接显示解码后的数据,方法是将其上传到WebGL中的纹理,然后用该纹理渲染一个四边形

网络上到处都有关于如何在WebGL中渲染纹理四边形的示例

您可以使用

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

请注意,如果您的像素不是RGB或RGBA,比如说它们是YUV,而不是在JavaScript中将它们转换为RGB/RGBA,我不确定您所说的BMP文件是什么意思,直到您指的是

我不知道该格式的所有细节,但如果你用JavaScript手工将其解码为像素,你可以直接显示解码后的数据,方法是将其上传到WebGL中的纹理,然后用该纹理渲染一个四边形

网络上到处都有关于如何在WebGL中渲染纹理四边形的示例

您可以使用

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

请注意,如果您的像素不是RGB或RGBA,比如说它们是YUV,而不是在JavaScript中将它们转换为RGB/RGBA

如果文件太大,并且您希望完全加载它,我认为没有什么可做的。也许你可以尝试用黑白页面之类的东西来改变解决问题的方法。我不确定颜色数据,但如果它非常重要,可以检查bmp标题。MarcoCI,也许我可以用低分辨率重建它?但是我担心它会太慢。因为我们需要在客户机上做所有的事情。如果文件那么大,而你想完全加载它,我认为没有什么可以做的。也许你可以尝试用黑白页面之类的东西来改变解决问题的方法。我不确定颜色数据,但如果它非常重要,可以检查bmp标题。MarcoCI,也许我可以用低分辨率重建它?但是我担心它会太慢。因为我们需要在客户端做所有的事情,我不需要下载文件。它已经下载(在客户机上以Blob呈现,问题是呈现的速度有多快)。在您的示例中,您使用画布上的drawImage。我们发现了几个问题。(糟糕的工作调整,我们需要等待加载img对象等)我们可以在DOM中附加img吗?为什么我们要使用drawImage?速度快吗?画布中没有渲染吗?我想补充的是,我们在Blob对象中已经有了BMP。我们不需要下载它,因为我们以某种特定的格式下载,然后在客户机上以Blob的形式解码。但不管怎样,您的回答非常有用!所以投票赞成。到达客户端的图像格式是DJVU块,我们在浏览器的客户端机器上通过javascript在BMP中对其进行解码。所以在网络上没有问题。我们尝试将src指定为data:uri。还有很多其他的方法,比如你提出的。但是这种方法需要在base64中编码BMP,这需要时间。需要加载图像对象。问题是,可能存在一些更快地绘制图像的方法?例如,在画布中不加载img对象?(这当然需要一些内存)我不需要下载文件。它已经下载(在客户机上以Blob呈现,问题是呈现的速度有多快)。在您的示例中,您使用画布上的drawImage。我们发现了几个问题。(糟糕的工作调整,我们需要等待加载img对象等)我们可以在DOM中附加img吗?为什么我们要使用drawImage?速度快吗?画布中没有渲染吗?我想补充的是,我们在Blob对象中已经有了BMP。我们不需要下载它,因为w