希望在Javascript/WebGL中访问16位图像数据

Tre*_*vor 7 javascript image-processing webgl

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

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

Kam*_*ski 7

如果合并两个 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);
Run Code Online (Sandbox Code Playgroud)

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

解释

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

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

在此处输入图片说明

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

https://github.com/czero69/ImageSplitter


小智 5

PNGToy是一个非常有特色的库,用于使用 javascript 提取几乎所有深度和通道模式的 PNG 块(真正的客户端/没有 Node.js,只有 Promise.js 依赖项)。解码方法将返回所需的缓冲区。以下是 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";
Run Code Online (Sandbox Code Playgroud)


and*_*wmu 4

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

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

highp float val = texture2d(samplerTop8bits, tex_coord) * (256.0 / 257.0);
val += texture2d(samplerBottom8bits, tex_coord) * (1.0 / 257.0);
Run Code Online (Sandbox Code Playgroud)

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

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

  • 有人可以举个具体的例子吗?非常感谢! (4认同)
  • 我做了类似的事情,但使用 RGB PNG 并在 R 和 G 通道中编码 2 个字节,然后在着色器中解码。 (3认同)