我将类型为TYPE_USHORT_GRAY的Java BufferedImage编码为base64,通过REST api将其提供给Javascript客户端。
我可以在服务器端清楚地检查适当范围(0到65k)中的不同像素值,但是canvas api似乎只提供rgba像素,导致我的用例无法接受的精度损失。 / p>
客户端Javascript是否可以通过画布或其他一些API读取和操作(但不显示)无符号短灰度图像的像素值?
答案 0 :(得分:2)
是的,您可以将像素存储在Uint16Array
缓冲区中,然后从中读取和写入亮度值。请注意,字节顺序(网络/大端与小端)很重要 - DataView
可以帮助您,或者只是在输入缓冲区是大端时交换字节顺序。
另请注意,超出范围的值正在进行模数处理,因此您需要手动剪切它们(或使用掩码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;
如果source使用gamma,则需要在处理之前将gamma转换为线性,完成后重新应用gamma。
你总是可以做一个面具/转移操作。但那不会那么准确。
(Canvas将始终使用基于8位的RGBA缓冲区)。
答案 1 :(得分:0)
为了便于实现,我们决定以一种捕获我们所需的全部值的方式将图像重新编码为一组RGB值:基本上,将每个像素视为一个3位数的基数256。 / p>
这种方式回避了这个问题,所以无论如何我都会接受Ken Fyrstenberg的回答。