在调整大小的canvas元素上使用putImageData更新图像数据

时间:2010-07-07 20:15:31

标签: javascript html5 canvas

我有一个使用drawImage在canvas元素上绘制的静态图像(png)。

var _canvas = null;
var _context = null;
var _curImageData;

function copyImageToCanvas(aImg)
{
  _canvas = document.getElementById("canvas");
  var w = aImg.naturalWidth;
  var h = aImg.naturalHeight;
  _canvas.width = w;
  _canvas.height = h;

  _context = _canvas.getContext("2d");
  _context.clearRect(0, 0, w, h);
  _context.drawImage(aImg, 0, 0);

  _curImageData = _context.getImageData(0, 0, w, h);
}

然后我逐个像素地操作图像数据(根据像素值将不透明度设置为255或0),然后使用putImageData更新画布。

function updateImage(maxPixelValToShow)
{
  for (var x = 0; x < _curImageData.width; x++)
    for (var y = 0; y < _curImageData.height; y++)
    {
        var offset = (y * _curImageData.width + x) * 4;
        var r = _curImageData.data[offset];
        var g = _curImageData.data[offset + 1];
        var b = _curImageData.data[offset + 2];
        var a = _curImageData.data[offset + 3];
        var pixelNum = ((g * 255) + b);

        //if greater than max or black/no data
        if (pixelNum > maxPixelValToShow || (!r && !g && !b)) {
            _curImageData.data[offset + 3] = 0;
        } else {
            _curImageData.data[offset + 3] = 255;
        }

    }
  _context.putImageData(_curImageData, 0, 0);
}

这一切都很完美。我遇到的问题是当我创建一个两倍于我的图像大小的画布(或者大小的一半)时,绘制图像以适合画布大小。

function copyImageToCanvas(aImg)
{
  _canvas = document.getElementById("canvas");
  var w = aImg.naturalWidth * 2;  //double the size!
  var h = aImg.naturalHeight * 2; //double the size!

  _canvas.width = w;
  _canvas.height = h;

  _context = _canvas.getContext("2d");
  _context.clearRect(0, 0, w, h);
  _context.drawImage(aImg, 0, 0, w, h);

  _curImageData = _context.getImageData(0, 0, w, h);
}

当我调用updateImage函数时,我的图像边缘会出现很多奇怪的文物。有谁知道a)为什么会发生这种情况?b)我能做些什么呢?

以下是一些显示正在生成内容的图片:

The original image

The original image after my updateImage function call

The resized image

The resized image after my updateImage function call

[解决] 感谢Adam和sunetos,这就是问题所在。一旦我设置一个画布来存储原始文件数据并进行像素操作而另一个仅用于显示,它工作正常。以下代码段:

function updateImage(maxPixelValToShow) {
  //manipulate the _workingContext data

  _workingContext.putImageData(_curImageData, 0, 0);
  _displayContext.clearRect(0, 0, _workingCanvas.width*_scale, _workingCanvas.height*_scale);
  _displayContext.drawImage(_workingCanvas, 0, 0, _workingCanvas.width*_scale, _workingCanvas.height*_scale);
}

1 个答案:

答案 0 :(得分:1)

在drawImage()中放大图像时,浏览器使用的图像平滑看起来像是对形状边缘进行了抗锯齿处理,导致边缘周围的新中间颜色值无法由updateImage()函数处理。就像Adam评论的那样,你应该对未修改的原始像素应用你的updateImage()逻辑,然后然后对它进行缩放。