我正在尝试从服务器下载16位图像数据,并将其推送到没有浏览器插件的WebGL纹理中。 texImage2d将使用:ImageData,HTMLImageElement,HTMLCanvasElement或HTMLVideoElement。我正在寻找一些javascript(一个库或代码示例),它可以将16位TIFF或类似的(hdf5等)图像数据解码为其中一种对象类型。
通过使用加载PNG,这样做每通道8位RGB是没有问题的,但这不适用于每通道16位数据,因为没有任何“标准”浏览器支持的图像格式是16位。
答案 0 :(得分: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);
(注意:您需要高精度才能在16位范围内正确表示数据)
只有在目标浏览器中支持浮点纹理时,才能使用另一种方法。您可以在浏览器中将两个PNG图像组合成浮点纹理,然后正常访问。这可能不会更快,并且可能会使用两倍的纹理内存量。
答案 1 :(得分:4)
如果组合两个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来实现。因此,分割值属于范围< 0,1>。
如果每通道16位,我们希望将其除以65535,以从范围<0,1>获得正确的数字。
我们想要的是16位颜色值减小到范围&lt; 0,1&gt;
让low
和up
为范围0..255的颜色值。 up
是前8位,low
是低8位
要获得16位值,我们可以计算:low + up*256
。现在我们的数字在0..65535范围内。从范围&lt; 0,1&gt;获得值我们将它除以65535.注意,WebGL使用范围&lt; 0,1&gt;的颜色值工作。 ,它是Lw=low/255
和Uw=up/255
。因此,我们不必将它乘以255并将其除以65535,因为65535 = 255 * 257。相反,我们只是除以257。
另外我找不到任何软件将16位/通道图像分成两个8位/通道图像,所以这是我的代码,随意使用它,它将16位/通道Tiff分成两个8位/通道PNG格式:
答案 2 :(得分:2)
PNGToy是一个非常有特色的库,用于使用javascript(实际上是客户端/没有node.js,只是Promise.js依赖项)提取几乎所有深度和通道模式的PNG块。 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";