我需要从画布中提取像素块并处理它们。目前,我在嵌套循环中多次调用getImageData
。
_getBinaryStringFromCanvas(canvas) {
let ctx = canvas.getContext('2d')
let { xMaxBlock, yMaxBlock, blockSize } = this.metrics;
let results = '';
for (let y = 0; y < yMaxBlock; y++) {
for (let x = 0; x < xMaxBlock; x++) {
let data = ctx.getImageData(x * blockSize, y * blockSize, blockSize, blockSize);
let digit = this._somehowProcessTheData(data);
binaryString += digit;
}
}
return binaryString;
}
这非常慢,因为xMaxBlock和yMaxBlock可能相当大。理想情况下,我想做这样的事情 -
_getChunkFromCache(cache, x, y, width, height){
// need help implementing this function
}
_getBinaryStringFromCanvas(canvas) {
let ctx = canvas.getContext('2d')
let { xMaxBlock, yMaxBlock, blockSize } = this.metrics;
let results = '';
let cache = ctx.getImageData(0, 0, xMaxBlock * blockSize, yMaxBlock * blockSize);
for (let y = 0; y < yMaxBlock; y++) {
for (let x = 0; x < xMaxBlock; x++) {
let data = this._getChunkFromCache(cache, x * blockSize, y * blockSize, blockSize, blockSize);
let digit = this._somehowProcessTheData(data);
binaryString += digit;
}
}
return binaryString;
}
但我似乎无法理解在返回的平面数组中寻址由x,y,width,height指定的区域所需的逻辑
getImageData
。
非常感谢任何实施_getChunkFromCache
的帮助。
答案 0 :(得分:2)
获取原始数据数组的子部分需要作为类型数组的副本(ImageData.data
中的数组是类型数组Uint8ClampedArray
)只是一维而不能索引2D部分另一个数组。创建副本只会增加更多工作量并增加内存使用量,从而进一步降低应用程序的速度。
您最好的选择是让somehowProcessTheData
函数直接使用图像数据,然后将数组索引到您提供的边界。
function somehowProcessTheData(imageData, x, y, w, h){
var i,j;
var result = "";
var r,g,b,a;
const data = imageData.data;
for(j = 0; j < h; j++){
var idx = (x + (y + j) * imageData.width) * 4; // get left most byte index for row at y + j
for(i = 0; i < w; i++){
r = data[idx ++];
g = data[idx ++];
b = data[idx ++];
a = data[idx ++];
// do the processing
}
}
return result;
}
或者
function somehowProcessTheData(imageData, x, y, w, h){
var i,j;
var result = "";
const data = imageData.data;
for(j = 0; j < h; j++){
var idx = (x + (y + j) * imageData.width) * 4;
for(i = 0; i < w; i++){
// get the red green blue values
var blah = data[idx] + data[idx + 1] + data[idx + 2];
// do the processing
// ...
// increment the index to the next pixel.
idx += 4;
}
}
return result;
}
然后在调用循环中
let data = this.processTheData(cache, x * blockSize, y * blockSize, blockSize, blockSize);
答案 1 :(得分:0)
您可以缓存正在处理的整个区域。 它仍然很慢,但希望您不需要经常这样做。 下面是为每个像素而不是4个字节获取整数的示例。
const pixels = new Int32Array(ctx.getImageData(0, 0, w, h).data.buffer)
pixels[x + y * w]