【问题标题】:Updating image data using putImageData on a resized canvas element在调整大小的画布元素上使用 putImageData 更新图像数据
【发布时间】:2011-03-13 00:34:48
【问题描述】:

我有一个静态图像(png),我正在使用drawImage 在画布元素上绘制。

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,这就是问题所在。一旦我设置一个画布来存储原始文件数据并进行像素操作,而另一个仅用于显示,它就可以正常工作。代码如下:sn-p:

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);
}

【问题讨论】:

  • 如果您创建一个相同大小的新画布,将图像绘制到上面,然后按标量调整画布大小会发生什么?

标签: javascript html canvas


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2019-04-29
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 2016-12-04
    • 2012-01-31
    • 2018-02-09
    • 1970-01-01
    • 2012-08-27
    相关资源
    最近更新 更多