使用 ctx.putImageData 更改图像大小

Dan*_*iel 3 html html5-canvas putimagedata typescript angular

我正在研究角度项目,我必须将图像放在画布上。图像没有本地存储,我只有图像数据,所以我使用它。

this.context.putImageData(imgData, firstPointX, firstPointY);
Run Code Online (Sandbox Code Playgroud)

现在我的问题是我收到的图片是640 * 480。我想知道是否有办法改变图像大小,以便我可以显示大于640 * 480?

Kai*_*ido 7

putImageData()将始终使用自己的目标宽度width目标高度,我们可以在drawImage()中使用它。 height

它对上下文矩阵变换不敏感,因此缩放它对此方法没有影响。

它具有的一件事是dirtyWidthdirtyHeight参数,这对我们没有多大帮助,因为虽然它们可以减少将要绘制的表面积,但它们不会修改包含的像素,并且无法无论如何都要让这个表面生长...... (你可以看到这个问答来更深入地了解它)


为了实现你想要的,你必须实际渲染你的ImageData然后drawImage渲染图像。

最全面的方法可能是使用第二个画布:

var ctx = canvas.getContext('2d'),
  cW = canvas.width,
  cH = canvas.height,
  imgW = 20,
  imgH = 20;

// generate a 20*20 ImageData full of noise
var data = new Uint8Array(imgW * imgH * 4);
crypto.getRandomValues(data);
var img = new ImageData(new Uint8ClampedArray(data.buffer), imgW, imgH);


// generate a second canvas
var renderer = document.createElement('canvas');
renderer.width = img.width;
renderer.height = img.height;
// render our ImageData on this canvas
renderer.getContext('2d').putImageData(img, 0, 0);
// Now we can scale our image, by drawing our second canvas
ctx.drawImage(renderer, 0,0, cW, cH);
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" height="100" width="100"></canvas>
Run Code Online (Sandbox Code Playgroud)

在现代浏览器中,由于ImageBitmap对象,整个事情可以以更干净的方式处理:

var ctx = canvas.getContext('2d'),
  cW = canvas.width,
  cH = canvas.height,
  imgW = 20,
  imgH = 20;

// generate a 20*20 ImageData full of noise
var data = new Uint8Array(imgW * imgH * 4);
crypto.getRandomValues(data);
var img = new ImageData(new Uint8ClampedArray(data.buffer), imgW, imgH);

createImageBitmap(img).then(renderer => 
  ctx.drawImage(renderer, 0,0, cW, cH)
)
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" height="100" width="100"></canvas>
Run Code Online (Sandbox Code Playgroud)

第三种方法,仅适用于放大 ImageData,并且将避免第二个画布并在所有实现中可用,是使用与 ImageBitmap 渲染器相同的画布,并使用合成将此画布绘制到自身上:

var ctx = canvas.getContext('2d'),
  cW = canvas.width,
  cH = canvas.height,
  imgW = 20,
  imgH = 20;

// generate a 20*20 ImageData full of noise
var data = new Uint8Array(imgW * imgH * 4);
crypto.getRandomValues(data);
var img = new ImageData(new Uint8ClampedArray(data.buffer), imgW, imgH);

// we use the main canvas as renderer
ctx.putImageData(img, 0, 0);
// Now we have an unscaled version of our ImageData
// let's make the compositing mode to 'copy' so that our next drawing op erases whatever was there previously
// just like putImageData would have done
ctx.globalCompositeOperation = 'copy';
// now we can draw ourself over ourself.
ctx.drawImage(canvas,
  0,0, img.width, img.height, // grab the ImageData part
  0,0, canvas.width, canvas.height // scale it
);
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" height="100" width="100"></canvas>
Run Code Online (Sandbox Code Playgroud)