【问题标题】:How to clone ImageData?如何克隆 ImageData?
【发布时间】:2012-06-17 03:23:23
【问题描述】:

这是可行的,但我觉得这段代码很长。 我正在寻找更好的主意。

var clone = function(imageData) {
  var canvas, context;
  canvas = document.createElement('canvas');
  canvas.width = imageData.width;
  canvas.height = imageData.height;
  context = canvas.getContext('2d');
  context.putImageData(imageData, 0, 0);
  return context.getImageData(0, 0, imageData.width, imageData.height);
};

【问题讨论】:

标签: javascript object canvas clone getimagedata


【解决方案1】:

大多数时候只需将imageData 分配给一个新变量就足够了,就像:

myImgData=ctx.getImageData(0,0,c.width,c.height); //get image data somewhere
imgDataCopy = myImgData;   // clone myImgData

...现在imgDataCopy 包含myImgData 的单独副本。 ?‍♂️


演示

下面的 sn-p 在 ImageData 的数组中创建 4 个“帧”,然后循环遍历它们。

const c = document.getElementById('canvas'),
      ctx = c.getContext("2d");
var wh=70, iDatas=[], i=0,
    lines=[[10,10,wh-10,wh-10], [wh/2,5,wh/2,wh-5],  // ⤡,↕
           [wh-10,10,10,wh-10], [5,wh/2,wh-5,wh/2]]; // ⤢,↔
c.width=wh;
c.height=wh;

ctx.strokeStyle='blue'; //setup to draw
ctx.lineWidth=9;
ctx.lineWidth='round';

for(var [x1,y1,x2,y2] of lines){ 
  ctx.beginPath();
  ctx.moveTo(x1,y1); //draw something
  ctx.lineTo(x2,y2);
  ctx.stroke();
  var d=ctx.getImageData(0,0,c.width,c.height); //get imgdata
  iDatas.push( d ); //save imgdata to array
  ctx.clearRect(0, 0, c.width, c.height); //clear canvas
}

ctx.strokeStyle='green'; //❌has no effect: 
  //  ↑ shows that color data comes from the source (can't be changed)
ctx.lineWidth='round'; //❌has no effect: 
  //  ↑ shows that non-color styling does NOT come from source (CAN'T be changed)

//now you can refer to the image data as iData[i] where i= 0 to 3
drawFrame();
function drawFrame(){
  ctx.putImageData( iDatas[i],0,0); //draw imgData from array
  i=(i==3?0:i+1); //set next iteration #
  setTimeout(function(){ drawFrame() }, 100); //schedule next frame
}
canvas{ border:2px dotted salmon; }
<canvas id='canvas'></canvas>

【讨论】:

    【解决方案2】:

    ImageData 构造函数接受图像数据数组。

    const imageDataCopy = new ImageData(
      new Uint8ClampedArray(imageData.data),
      imageData.width,
      imageData.height
    )
    

    【讨论】:

    • 对于那些想知道的人,像我一样,不,ImageData 构造函数不会克隆array 参数,而是将其用作其数据,因此new Uint8ClampedArray 是必要的。 Source.
    【解决方案3】:

    TypedArray.prototype.set()可以直接复制数据。

    var imageDataCopy = new Uint8ClampedArray(originalImageData.data);
    imageDataCopy.data.set(originalImageData.data);
    

    这会将imageDataCopy 的内容设置为与originalImageData 相同。

    【讨论】:

    • 什么是原始对象,什么是克隆对象?似乎对我不起作用
    • 这是一个糟糕且不清楚的代码示例 - 此外,我怀疑它已经过时并且不适用于现代浏览器。
    • Hakan,MDN documentation 说这是有效的,它对我有用。我提交了修改以澄清这一点。
    • 那么单独这些行就足够了,还是需要两行对?如果你需要这两行,第一行自己做什么?
    • @hippietrail - new operator 用于创建构造函数的新实例,因此理论上:第一行=克隆结构,第二行=复制数据...然而这种方法实际上并没有为我工作,但other answer 做了我需要的,也许是因为另一个答案包括ImageData() function 来实际创建ImageData object
    猜你喜欢
    • 2010-10-17
    • 2012-05-27
    • 2010-12-30
    • 2015-01-26
    • 2011-03-31
    • 2011-08-20
    • 1970-01-01
    相关资源
    最近更新 更多