【问题标题】:In what order does webgl readPixels collapse the image into arraywebgl readPixels 以什么顺序将图像折叠成数组
【发布时间】:2018-05-02 15:08:00
【问题描述】:

我正在使用诸如

之类的命令读取图像
gl.readPixels(0, 0, gl.width, gl.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

现在像素在一维数组中的长度为width*height*4。我不确定图像值沿哪个轴折叠?直觉上,我希望它读取每一行,首先向下移动红色列,然后是 G、B、A(我称之为沿宽度折叠,然后是高度折叠,而不是 RGBA)。

例如,如果我想访问图像底部右数第二个像素中的 RED 值,我会使用:

<br>
pixels[width*height-2] (collapse along width, then height, then RGBA)<br>
pixels[width*height-1-height] (collapse along height, then width, then RGBA)<br>
pixels[width*height*4-8] (collapse along RGBA, then width, then height)<br>

或其他顺序。

【问题讨论】:

    标签: javascript html image-processing webgl


    【解决方案1】:

    顺序是标准的GL顺序,即第一个像素对应于纹理、渲染缓冲区、画布中的0,0位置。

    对于画布本身,0,0 是左下角。对于纹理,没有底部的概念,有第一个像素 (0,0),像素 (1,0),像素 (0,1),最后一个像素 (1,1)。

    对于画布(因为它是唯一具有固定方向的东西), 第一行(底部)最右边的像素是data[(width - 1) * pixelSize] 第三行最右边的像素是data[(width * 3 - 1) * pixelSize] 最后一行(顶部)最右边的像素是data[(width * height - 1) * pixelSize]

    一个简单的测试

    const gl = document.querySelector("canvas").getContext("webgl");
    
    gl.enable(gl.SCISSOR_TEST);
    drawRectUsingScissor(0, 0, 1, 1, [ 1, 0, 0, 1]);
    drawRectUsingScissor(1, 0, 1, 1, [ 0, 1, 0, 1]);
    drawRectUsingScissor(0, 1, 1, 1, [ 0, 0, 1, 1]);
    drawRectUsingScissor(1, 1, 1, 1, [ 1, .5, 0, 1]);
    
    const width = 2;
    const height = 2;
    const pixelSize = 4;
    const data = new Uint8Array(width * height * pixelSize);
    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
    
    log("raw: ", data);
    
    for (let y = 0; y < height; ++y) {
     for (let x = 0; x < width; ++x) {
       const offset = (y * width + x) * pixelSize;
       log(x, ',', y, ':', data.slice(offset, offset + pixelSize)); 
     }
    }
    
    function drawRectUsingScissor(x, y, width, height, color) {
      gl.clearColor(...color);
      gl.scissor(x, y, width, height);
      gl.clear(gl.COLOR_BUFFER_BIT);
    }
    
    function log(...args) {
      const elem = document.createElement("pre");
      elem.textContent = [...args].join(' ');
      document.body.appendChild(elem);
    }
    canvas {
      width: 100px;
      height: 100px;
      image-rendering: pixelated;
    }
    pre { margin: 0 }
    &lt;canvas width="2" height="2"&gt;&lt;/canvas&gt;

    请注意,上述内容并非严格正确,因为您必须考虑 gl.PACK_ALIGNMENT 设置,默认为 4,但可以设置为 1、2、4 或 8。对于 RGBA/UNSIGNED_BYTE 读取,您没有担心PACK_ALIGNMENT

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-19
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 2021-01-12
      • 1970-01-01
      相关资源
      最近更新 更多