【问题标题】:Unexpected RGB channel values for gray pixel in 48 bits bitmap48 位位图中灰色像素的意外 RGB 通道值
【发布时间】:2021-07-21 13:13:15
【问题描述】:

跟进this question

我已经设法使用Bitmap.LockBits 从位图实例中提取像素信息。 PixelFormatFormat48bppRbg,根据我的理解和 Peter's answer 对上述问题的理解,应该使用两个字节存储每个像素的 RGB 颜色通道。字节的组合值应等于 0 到 8192 之间的数字,表示 RBG 通道强度值。该值是通过将两个字节都传递给BitConverter.ToUInt16 方法获得的。

因此,在为以下 3 x 3 位图提取像素信息时(为清晰起见,此处放大):

我的第一行像素通道是这样的:

Pixel color Red intensity Green intensity Blue intensity
RED 8192 0 0
GREEN 0 8192 0
BLUE 0 0 8192

到目前为止一切顺利。

然而,在第二行,它是这样的:

Pixel color Red intensity Green intensity Blue intensity
WHITE 8192 8192 8192
GRAY (!) 1768 (!) 1768 (!) 1768 (!)
BLACK 0 0 0

白色和黑色像素通道值对我来说很有意义。

然而,灰色却没有。

如果你在上面的灰色像素上使用任何颜色选择器,你应该得到一个完美的中等灰色。在 24 位颜色中,它应该相当于 (R: 128, G: 128, B: 128),或十六进制形式的 #808080。

那么,为什么在Format48bppRpg 像素格式中,通道强度远低于预期的中间值 4096?这个基于 GDI+ 的 0-8192 范围不是应该像它的 8 位对应物一样工作吗,0 是最低强度,8192 是最高强度?我在这里错过了什么?

作为参考,这里是来自Visual Studio 调试器的屏幕截图,显示了原始字节索引和值,以及关于步幅、通道位置及其提取的强度值的附加说明,直到灰色像素:

【问题讨论】:

    标签: c# .net .net-core gdi+


    【解决方案1】:

    您陈述错误假设的部分是 #808080 是“完全中等灰色”。它不是,至少如果你从某种角度来看它不是(更多关于它here)。

    包括 sRGB 在内的许多颜色标准都使用gamma compression 在通常用于存储 RGB 颜色的 256 个值的范围内使较暗的颜色间隔更大。这大致意味着在编码该值之前取相对分量值的平方根(或 2.2 根)。原因是人眼(与其他感官一样)以对数方式感知亮度,因此即使是算术上很小的亮度变化也很重要,如果这意味着实际上将亮度翻倍。

    128 的字节值实际上约为全亮度的 21,95 % (128/255 ^ 2.2),这就是您在 16 位组件的情况下看到的。可能值的空间更大,因此 GDI(或格式)不再需要以特殊方式存储它们。

    如果您需要算法,取值的 2.2 根通常效果很好,但正确的公式有点不同,请参阅 here。根函数通常具有接近零的无限斜率,因此特定公式试图通过使该部分成为线性来解决此问题。一段代码可以很容易地从中派生出来:

    static byte TransformComponent(ushort linear)
    {
        const double a = 0.055;
        var c = linear / 8192.0;
        c = c <= 0.0031308 ? 12.92 * c : (1 + a) * Math.Pow(c, 1/2.4) - a;
        return (byte)Math.Round(c * Byte.MaxValue);
    }
    

    对于 1768 的值,这给出了 128。

    【讨论】:

    • 哇,这比预期的要难得多。我不知道下一步该做什么将每个值转换回最接近的 8 位等效值。我将尝试查找 8 位/16 位 RGB 转换算法的示例。也许再举几个例子,我就会有我的尤里卡时刻。如果您知道任何有关此的在线资源,请分享。非常感谢您的精彩回答!
    • @Crono 我已添加代码以转换回通常的 8 位值。 ;-)
    • 是的,就像一个魅力! :D 如果我敢再次给您带来负担,如果它们是变量,您将如何命名函数中的数字文字?我想在文档中处理这些信息。
    • @Crono 恐怕我不知道它们的任何正确或特定名称。这都是转换公式的一部分。
    猜你喜欢
    • 2014-11-03
    • 2020-05-15
    • 1970-01-01
    • 2014-10-30
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多