加速画布的 getImageData

Say*_*yet 5 html javascript canvas

我需要从画布中提取像素块并处理它们。目前我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;
}
Run Code Online (Sandbox Code Playgroud)

这非常慢,因为 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;
}
Run Code Online (Sandbox Code Playgroud)

但我似乎无法理解在由getImageData.

任何帮助实施_getChunkFromCache都受到高度赞赏。

Bli*_*n67 6

不要复制,直接索引数组。

获取原始数据数组的一部分需要是一个副本,因为类型数组(数组中的数组ImageData.data是类型化数组Uint8ClampedArray)只是一维的,不能索引另一个数组的二维部分。创建副本只会增加更多工作并增加内存使用量,从而进一步减慢您的应用程序的速度。

您最好的选择是让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;
 }
         
Run Code Online (Sandbox Code Playgroud)

或者

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;
 }
Run Code Online (Sandbox Code Playgroud)

然后在调用循环中

 let data = this.processTheData(cache, x * blockSize, y * blockSize, blockSize, blockSize);
  

 
Run Code Online (Sandbox Code Playgroud)

  • @EntangledMess 如果您想归功于任何人,请归功于 Stackoverflow。我所做的并不费力,但他们通过他们的服务为许多人提供了帮助,这是许多人持续不断的努力。 (3认同)