Javascript 无符号短灰度图像

Javascript Unsigned Short Grayscale Images

我正在将类型为 TYPE_USHORT_GRAY 的 Java BufferedImage 编码为 base64,通过 REST api 将其提供给 Javascript 客户端。

我可以在服务器端清楚地检查适当范围(0 到 65k)内的不同像素值,但是 canvas api 似乎只提供 rgba 像素,导致我的用例无法接受精度损失。

客户端 Java 脚本是否可以通过 canvas 或其他一些 [=19= 读取和操作(但不显示)无符号短灰度图像的像素值]?

是的,您可以将像素存储在 Uint16Array 缓冲区中,然后从中读取和写入亮度值。请注意,字节顺序(network/big-endian vs. little-endian)很重要 - DataView 可以帮助您解决这个问题,或者如果传入缓冲区是 big-endian,则只需交换字节顺序。

另请注意,超出范围的值正在接受模处理,因此您需要手动裁剪它们(或使用掩码 0xffff 写入)。然后使用索引将每个亮度值作为普通数组访问。

但是,如果您打算进行大量处理,我建议您使用浮点缓冲区而不是标准化值,使用 Float32ArrayFloat64Array - 前者更快,后者更准确。这也将允许您根据需要将动态范围推入和推出,除非您需要限制每次通过的值。

标准化(显而易见,但为了记录):

newLum = oldLum / 0xffff;

提示:要获得更准确的预览,如果您在此过程中需要,请使用以下方法进行缩小 - 原则上适用于任何深度:

var inDepth = Math.pow(2, 16) - 1;   // 65535
var outDepth = Math.pow(2, 8) - 1;   // 255

然后对于每个亮度值:

var r,g,b,a;
r = g = b = (lum * outDepth / inDepth + 0.5)|0;    // or, in this case -
r = g = b = (lum * 0.0038910505836575876 + 0.5)|0;
a = 255;

如果源使用 gamma,则需要在处理之前将 gamma 转换为线性,完成后,重新应用 gamma。

你总是可以做一个 mask/shift 操作。但这不会那么准确。

(Canvas 将始终使用基于 8 位的 RGBA 缓冲区)。

为了便于实施,我们决定将图像重新编码为一组 RGB 值,以捕获我们需要的所有值范围:基本上,将每个像素视为一个 3 位 256 进制数.

这种回避问题的方式,所以无论如何我都会接受 Ken Fyrstenberg 的回答。