我正在编写PNG解码器并且我遇到了具有位深度<的灰度图像的问题。 8。
我不知道如何才能获得全彩色范围。
例如,假设图像使用4位深度,而数据字节为:10110010
我有2个像素,1011
和0010
。现在,我将第二个像素移位4位以占据高位。这就是问题所在。我应该复制位,以便2个像素为10111011
和00100010
,或者我应该只扩展最后一位,以便像素为10111111
和00100000
。我在PNG规范中找不到相关信息。
答案 0 :(得分:1)
为什么这会符合规格?您正在转换输出值,并且规范不应该关心您对输出数据的处理方式。尽管如此,正如Glenn Randers-Pehrson所说,official specification包含了相关的建议。 Concepts: 4.3.6 Sample depth scaling介绍了基础知识。编码器和解码器的建议在12.5 Sample depth scaling中用于编码器(将外部数据扩展到支持的PNG格式)和13.12 Sample depth rescaling用于解码器(将PNG格式扩展为所需的输出格式)。
那就是说,假设你想要一个4位值1111
线性转换为8位值1111.1111
,那么公式为
output = 255 * input / 15
将公式应用于0..15范围,即可获得
0: 0000 -> 00000000
1: 0001 -> 00010001
2: 0010 -> 00100010
3: 0011 -> 00110011
4: 0100 -> 01000100
5: 0101 -> 01010101
6: 0110 -> 01100110
7: 0111 -> 01110111
8: 1000 -> 10001000
9: 1001 -> 10011001
10: 1010 -> 10101010
11: 1011 -> 10111011
12: 1100 -> 11001100
13: 1101 -> 11011101
14: 1110 -> 11101110
15: 1111 -> 11111111
如您所见,前四位始终在低位重复。那是完全上面的公式!
255 * input / 15
= input * 255 / 15
= input * 17
= input + input * 16
我们最终以
结束output = (input<<4) + input
这可以扩展到上采样(和下采样)任何值到另一个基数:
newvalue = (oldvalue * max_new) / max_old
由于max_new
通常对于位值是奇数,为了获得适当的舍入,您可以使用
newvalue = (2 * oldvalue * max_new + max_old) / (2*max_old)