使用 drawImage 缩放透明图像时出现故障

Posted

技术标签:

【中文标题】使用 drawImage 缩放透明图像时出现故障【英文标题】:Glitch when scaling transparent image using drawImage 【发布时间】:2022-01-01 19:09:31 【问题描述】:

我正在尝试使用 CanvasRenderingContext2D.drawImage 缩放具有透明像素的图像,但每当我绘制图像时,我最终得到的是原始大小的图像和画布上绘制的缩放版本。这是一些重现故障的代码:

<canvas id="cvs" width=200 height=100></canvas>
const canvas = document.getElementById('cvs');
const ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
const imageData = ctx.createImageData(100, 50);
const data = imageData.data;
for (var i = 0; i < data.length; i += 4) 
  if (i % 400 > 360) 
    data[i]     = 255;
    data[i + 1] = 0;
    data[i + 2] = 0;
    data[i + 3] = 255;
  
  else 
    data[i]     = 0;
    data[i + 1] = 0;
    data[i + 2] = 0;
    data[i + 3] = 0; // Change this to 255 to get rid of the glitch
  

ctx.putImageData(imageData, 0, 0);
ctx.drawImage(canvas, 0, 0, 100, 50, 0, 0, 200, 100);

https://jsfiddle.net/o4sv6qhb/2/

我不明白为什么会这样。如果我不使用任何透明像素,那么问题就会消失。

我想一种解决方法是直接填充最终尺寸图像的像素而不使用 drawImage 的缩放,但我宁愿不必这样做。

【问题讨论】:

【参考方案1】:

您在画布上绘制了两次,一次使用 putImageData 以 1:1 像素的比例绘制,然后再次使用放大版的 drawImage

第二次绘制与第一次重叠,因此如果您没有透明像素,您将无法看到原始图像,因为它正在被绘制。

但是,如果您确实有透明像素,则较大的图像不会覆盖后面的图像,并且您会看到旧图像。

如果您只想要 drawImage 命令中的图像,您可以尝试创建一个单独的画布来绘制您的 imageData,然后将该画布绘制到第一个画布上,但要按比例放大。

const canvas = document.getElementById('cvs');

// create a second hidden canvas/context pair
const offscreenCanvas = document.createElement('canvas');
const hiddenContext - offscreenCanvas.getContext('2d');

const ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
const imageData = ctx.createImageData(100, 50);
const data = imageData.data;

for (var i = 0; i < data.length; i += 4) 
  if (i % 400 > 360) 
    data[i]     = 255;
    data[i + 1] = 0;
    data[i + 2] = 0;
    data[i + 3] = 255;
  
  else 
    data[i]     = 0;
    data[i + 1] = 0;
    data[i + 2] = 0;
    data[i + 3] = 0; // Change this to 255 to get rid of the glitch
  


// draw to the hidden canvas
hiddenContext.putImageData(imageData, 0, 0);

// draw the hidden canvas content to the visible one and scale
ctx.drawImage(offscreenCanvas, 0, 0, 100, 50, 0, 0, 200, 100);

【讨论】:

谢谢。在最后一行中,第一个参数应该是 offscreenCanvas。

以上是关于使用 drawImage 缩放透明图像时出现故障的主要内容,如果未能解决你的问题,请参考以下文章

当我将透明度添加到 gif 并将其转换为 webm 时出现故障

刷新页面时出现图像故障

渲染大图像时出现javafx NullPointerException

java中 g.drawImage()方法如何使用

如何使用 g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2) 缩放图像?

缩放后在滚动视图中设置新图像时出现问题