【问题标题】:Looking to access 16-bit image data in Javascript/WebGL希望在 Javascript/WebGL 中访问 16 位图像数据
【发布时间】:2011-09-18 19:35:02
【问题描述】:

我正在尝试从服务器下载 16 位图像数据并将其推送到没有浏览器插件的 WebGL 纹理中。 texImage2d 可用于:ImageData、HTMLImageElement、HTMLCanvasElement 或 HTMLVideoElement。我正在寻找一些可以将 16 位 TIFF 或类似(hdf5 等)图像数据解码为这些对象类型之一的 javascript(库或代码示例)。

我没有问题这样做是通过使用加载 PNG 的每通道 8 位 RGB 但这不适用于每通道 16 位数据,因为没有任何“标准”浏览器支持的图像格式是 16 位的。

【问题讨论】:

    标签: javascript image-processing webgl


    【解决方案1】:

    我认为目前主流浏览器本身不支持任何 16 位/通道图像格式。

    实现相同效果的一种方法是创建两个 PNG 图像,一个具有图像中每个颜色通道的前 8 位,另一个具有底部 8 位。 然后将图像绑定为两个纹理并组合着色器中的值,例如

    highp float val = texture2d(samplerTop8bits, tex_coord) * (256.0 / 257.0);
    val += texture2d(samplerBottom8bits, tex_coord) * (1.0 / 257.0);
    

    (注意:您需要高精度才能在 16 位范围内正确表示数据)

    仅当您的目标浏览器支持浮点纹理时,才可能使用另一种方法。您可以在浏览器中将两个 PNG 图像组合成一个浮点纹理,然后正常访问它。这可能不会更快,并且可能会使用两倍的纹理内存。

    【讨论】:

    • 我做了类似的事情,但使用了 RGB PNG 并在 R 和 G 通道中编码了 2 个字节,然后在着色器中解码。
    • 好建议@Trevor。自从我回答了这个问题以来,我就完全按照这种方式完成了。它可能比读取两次纹理更有效。
    • 有人可以举个具体的例子吗?非常感谢!
    【解决方案2】:

    如果合并两张PNG图像,一张是高8位,另一张是低8位,我认为应该是:

    highp vec4 texCol = texture2D(tex_low, vec2(vTexCoord.s, vTexCoord.t)) * (1.0 / 257.0);
    texCol += texture2D(tex_up, vec2(vTexCoord.s, vTexCoord.t)) * (256.0 / 257.0);
    

    在每通道 8 位中,RGB 颜色的范围为 0 到 255 = 2^8 - 1。
    在每通道 16 位中,RGB 颜色的范围为 0 到 65535 = 2^16 - 1 = 255*257。

    说明

    WebGL 使用从 0 到 1 的颜色值,并通过将 8 位颜色值除以 255 来实现。因此,除后的值属于 范围。
    在每个通道 16 位的情况下,我们希望将其除以 65535 以获得范围 中的正确数字。

    我们想要的是将 16 位颜色值缩小到 范围。
    lowup 为 0..255 范围内的颜色值。 up 是前 8 位,low 是低 8 位。
    要获得 16 位值,我们可以计算:low + up*256。现在我们的数字在 0..65535 范围内。要从范围 中获取值,我们将其除以 65535。请注意,WebGL 使用范围 中的颜色值,它是 Lw=low/255Uw=up/255。因此,我们不必将其乘以 255 再除以 65535,因为 65535 = 255*257。相反,我们只除以 257。

    我也找不到任何软件将 16 位/通道图像拆分为两个 8 位/通道图像,所以这是我的代码,请随意使用,它将 16 位/通道 Tiff 拆分为两个 8 位/通道PNG:

    https://github.com/czero69/ImageSplitter

    【讨论】:

    • 这违反直觉,但正确!绝对值得 +1。
    【解决方案3】:

    PNGToy 是一个非常有特色的库,用于使用 javascript 提取几乎所有深度和通道模式的 PNG 块(真正的客户端/没有 node.js,只是 Promise.js 依赖项)。 decode 方法将返回所需的缓冲区。以下是 16 位灰度 PNG 的示例(16 位 RGB 也应该可以):

    var dataObj;
    var img = new PngImage();
    var buffer;
    
    img.onload = function() {
    
        var pngtoy = this.pngtoy;
    
        dataObj = pngtoy.decode().then(function(results) {
    
            buffer = new Uint16Array(results.bitmap);
    
            for(var i = 0, j; i < buffer.length; i++) {
    
              j = buffer[i];
              buffer[i] = ((j & 0xff) << 8) | ((j & 0xff00) >>> 8); // needed to swap bytes for correct unsigned integer values  
            }
    
            console.log(buffer);
        });     
    };
    
    img.onerror = function(e) {
        console.log(e.message);
    };
    
    img.src = "image.png";
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    相关资源
    最近更新 更多