我不认为这个标题很准确,但我想不出更好的了。
我正在处理医学图像,在这类图像中没有确定的像素值,您必须提取一些信息并自己计算每个像素值。第二个特点是图像分辨率可能非常大。
因此,一旦我将图像加载到内存中,我就有了一个 ArrayBuffer 和一些其他计算所需的属性。由于这些图像不是基于任何常见格式,我不能使用图像 DOMElement 在画布上绘制它们。
这是我遇到的两个相关问题:
1)我必须使用 ImageData 将图像绘制到画布中,这意味着我必须遍历我的 ArrayBuffer 计算每个像素值并将它们存储在 ImageData 中,然后我使用 canvas.putImageData() 并且浏览器可能会遍历再次 ImageData 和显示像素。我不喜欢这样,因为它需要迭代两次才能显示图像并且每次更新时都需要迭代。
2)正如我所说,图像可能非常大,所以我需要使用缩放/切片,但画布只为 drawImage 提供这些功能,而不为 putImageData 提供这些功能。如果我不想自己计算它,我必须使用缓冲区画布,将整个图像复制到其中,然后将 drawImage 与此缓冲区画布一起用作图像。这很糟糕,原因有两个:
我正在复制数据,我必须保留原始的 ArrayBuffer 和缓冲区画布。可以创建和删除缓冲区画布,但由于我需要在鼠标移动时更新图像,所以最好保留它。
如果对图像进行了更改,例如对比度/亮度,我必须为整个图像(缓冲区画布创建)重新计算它,即使我只是显示其中的一小部分。
这是一些代码:
//image contains raw data: TypedArrayView and some attributes
// size (2828,2320)
var image;
//displayed canvas
// size (500,500)
var canvas;
//buffer canvas
// size (2828,2320)
var buffCanvas;
function drawImage(sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight){
var buffContext = buffCanvas.getContext('2d');
var imageData = buffContext.getImageData(buffCanvas.width,buffCanvas.height);
//Iterate over all the image (2828,2320)
for(var i = 0; i < imageData.data.length; i++ )
//process pixel calculation
imageData[i] = image.buffer[i] + SomeCalculation;
buffContext.putImageData(imageData,0,0);
canvas.getContext('2d').drawImage(buffCanvas,sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
}
function onmousemove(){
//change some image properties
image.contrast = 150;
...
drawImage(sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
}
我对此有点陌生,所以我一定会遗漏一些东西,因为我这样做的方式不会有成效。
我的梦想是创建一个像 ArrayBuffer 一样的视图,或者覆盖(不可能)括号运算符或创建一个假图像元素。这可以这样工作:
function MedicalImage(data, ...){
...
}
MedicalImage.prototype.getPixelValueAt = function(pos){
return data[pos] + SomeCalculation;
}
var img = new MedicalImage();
context.drawImage(img,sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
并且浏览器会在需要时调用 getPixelValueAt() 来获取像素值。