【问题标题】:PNG Bit extensionPNG 位扩展
【发布时间】:2015-11-12 12:30:35
【问题描述】:

我正在编写 PNG 解码器,但我在处理位深

我不确定如何获得完整的颜色范围。

例如,假设图像使用 4 位深度,数据字节为:10110010 我有 2 个像素,10110010。现在,我将第二个像素向左移动 4 位以占据高位。这就是问题所在。我应该复制位以使 2 个像素成为 1011101100100010,还是应该只扩展最后一位以使像素成为 1011111100100000。我在 PNG 规范中找不到这方面的信息。

【问题讨论】:

    标签: bitmap bit-manipulation png pixel


    【解决方案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)
    

    【讨论】:

    • 实际上在PNG规范中有建议(标题为“样本深度缩放”和“样本深度重新缩放”的部分)相当于您的答案。
    • @Glenn:谢谢!我想这是我已经“知道”的事情,所以不必看到它写出来。运行一些快速测试,我还发现报告的“左位复制通常给出与线性缩放相同的值,并且从不超过一个”,这很奇怪。我真的无法解释为什么会发生这种情况......
    猜你喜欢
    • 2012-10-02
    • 1970-01-01
    • 2018-06-19
    • 2016-12-17
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多