【问题标题】:How can I fill the canvas pixel by pixel?如何逐像素填充画布?
【发布时间】:2022-04-30 15:33:55
【问题描述】:

我正在尝试设置画布上所有像素的颜色。我很确定我知道它是如何工作的:canvas.getContext("2d").getImageData.data 中的前 4 个值是指第一个像素的 r、g、b 和 a,第二个 4 是指第二个像素,依此类推。我想知道这段代码有什么问题:

function draw()
{
    var cnvs = document.getElementById("CanvasFlynn"); //Assume it's 2x2 pixels
    var cont  = cnvs.getContext("2d");
    var imdt  = cont.getImageData(0,0,2,2);
    var r     = [ 255 , 0 , 0 , 255 ];
    var g     = [ 0 , 255 , 0 , 255 ];
    var b     = [ 0 , 0 , 255 , 255 ];
    var a     = [ 1 , 1 , 1 , 1 ];
    var index = 0;
    for ( var i = 0 ; i < imdt.data.length ; i++ )
    {
        index              = 4*i;
        imdt.data[index]   = r[i];
        imdt.data[index+1] = g[i];
        imdt.data[index+2] = b[i];
        imdt.data[index+3] = a[i];
    }
}

如果有人能告诉我为什么这不会改变画布的像素颜色,那就太棒了(我实际上并没有使用 2x2 的卡瓦,这只是作为示例)。

【问题讨论】:

    标签: javascript html canvas pixels


    【解决方案1】:

    有很多问题

    1. cont.getImageData 是函数而不是属性

    2. imdt 不是画布的图像数据,它是画布图像数据的副本。

      您需要调用cont.putImageData 将数据复制回画布中

    3. imdt.data.length 是字节数而不是像素数。每个像素有 4 个字节。

    4. 图像数据中的 alpha 在 0 到 255 的范围内

    function draw()
    {
        var cnvs = document.getElementById("CanvasFlynn"); //Assume it's 2x2 pixels
        var cont  = cnvs.getContext("2d");
        var imdt  = cont.getImageData(0, 0, 2, 2);
        var r     = [ 255 , 0 , 0 , 255 ];
        var g     = [ 0 , 255 , 0 , 255 ];
        var b     = [ 0 , 0 , 255 , 255 ];
        var a     = [ 255 , 255 ,255 ,255 ];
        var index = 0;
        for ( var i = 0 ; i < imdt.data.length / 4 ; i++ )
        {
            index              = 4*i;
            imdt.data[index]   = r[i];
            imdt.data[index+1] = g[i];
            imdt.data[index+2] = b[i];
            imdt.data[index+3] = a[i];
        }
      
        cont.putImageData(imdt, 0, 0);
    }
    draw();
    <p>Note the 2x2 canvas will be stretched to 100x100 and may be bilinear filtered</p>
    <canvas id="CanvasFlynn" width="2" height="2"
     style="width: 100px; height: 100px; border: 1px solid black; image-rendering: pixelated;"></canvas>

    请注意,将数据视为 32 位值可能会更快,因此每个像素只有一个值

    function draw()
    {
        var cnvs = document.getElementById("CanvasFlynn"); //Assume it's 2x2 pixels
        var cont  = cnvs.getContext("2d");
        var imdt  = cont.getImageData(0, 0, 2, 2);
        
        // make a Uint32 view of the image data
        var pixels = new Uint32Array(imdt.data.buffer);  
        var r     = 0xFF0000FF;
        var g     = 0xFF00FF00;
        var b     = 0xFFFF0000;
        var y     = 0xFF00FFFF;
        
        pixels[0] = r;
        pixels[1] = g;
        pixels[2] = b;
        pixels[3] = y;
      
        cont.putImageData(imdt, 0, 0);
    }
    draw();
    <p>Note the 2x2 canvas will be stretched to 100x100 and may be bilinear filtered</p>
    <canvas id="CanvasFlynn" width="2" height="2"
     style="width: 100px; height: 100px; border: 1px solid black; image-rendering: pixelated;"></canvas>

    【讨论】:

    • 我确实将cont.getImageData 作为带参数的函数调用,只是忘记将其包含在 SO 问题框中,修复了它。您的其他建议虽然解决了问题。谢谢
    • 你修复了 OP 的代码,但如果你不打算使用已经绘制的数据,那么使用 ctx.createImageData() 会更便宜
    猜你喜欢
    • 1970-01-01
    • 2017-10-18
    • 2013-03-25
    • 2016-01-09
    • 2016-02-18
    • 2019-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多