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 写入)。然后使用索引将每个亮度值作为普通数组访问。
但是,如果您打算进行大量处理,我建议您使用浮点缓冲区而不是标准化值,使用 Float32Array
或 Float64Array
- 前者更快,后者更准确。这也将允许您根据需要将动态范围推入和推出,除非您需要限制每次通过的值。
标准化(显而易见,但为了记录):
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 的回答。
我正在将类型为 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 写入)。然后使用索引将每个亮度值作为普通数组访问。
但是,如果您打算进行大量处理,我建议您使用浮点缓冲区而不是标准化值,使用 Float32Array
或 Float64Array
- 前者更快,后者更准确。这也将允许您根据需要将动态范围推入和推出,除非您需要限制每次通过的值。
标准化(显而易见,但为了记录):
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 的回答。