【问题标题】:How to best display 30+ bpp graphics on a 24 bpp display?如何在 24 bpp 显示器上最好地显示 30+ bpp 图形?
【发布时间】:2013-03-25 11:55:18
【问题描述】:

在常规 24 bpp 显示器上显示每通道超过 8 位的最忠实图形的最佳方式是什么?

【问题讨论】:

    标签: algorithm image-processing graphics dithering


    【解决方案1】:

    我能想到的最佳解决方案是基于改变每一帧的随机抖动。这结合了抖动与不具有固定抖动模式的优点,并且由于给定像素每秒多次更改值,因此您认为更接近这些不同值的平均值,这更接近原始“深色”值而不是任何给定的 24 bpp 值。

    外观

    绿色渐变,无抖动,抖动(显示 10 帧),然后以相同的方式增强可见性:

    抖动

    抖动是通过将每个通道的伽马压缩深色值与随机值相加,然后四舍五入到最接近的 8 位值来实现的。使用在 -0.5 和 0.5 之间均匀分布的随机数似乎很自然(我所说的单位相当于 8 位伽马压缩值中的 1,例如 0 和 1 或 254 和 255 之间的差异) ,但是这会导致一种带状伪影,其中接近 8 位值的梯度值几乎没有噪声,而离任何 8 位值最远的值会显示更多的噪声。高斯噪声更合适,因为它提供了更平滑的噪声水平。我选择了 1.0 的 sigma,但为了减少噪音,0.8 的 sigma 可能会做。

    您可以通过取两个随机数 n1n2 来创建高斯 PRNG,将它们分别拟合在 [-1 , 1] 范围内,如果它们代表单位圆内的一个点(如果总和sum他们的方格小于等于1,否则重新开始)返回sqrt(-2. * log(sum) / sum) * n1

    实际实现

    我选择通过将每通道 15 位的线性 RGB 帧缓冲区转换为每通道 8 位的 sRGB 帧缓冲区来实现这一点。 sRGB 的线性部分只是一个细节,我使用查找表将线性值转换为 gamma 压缩值(我选择使这些中间值使用 13 位,您可以将其视为 sRGB 值的 8.5 定点符号)。

    不用说,您不会为每个像素生成一个新的随机高斯数,您需要预先计算一堆并将它们放入循环缓冲区中。我选择了 16384 个,是的,只有 16384 个,我通过在这个缓冲区中选择一个随机入口点来避免任何重复模式,一个随机长度(在 100 到 1123 之间,这是非常任意的),当我到达长度的结束我选择了一个新的随机起点和一个新的随机长度。通过这种方式,我可以从相对较小的数字缓冲区中获得相当随机的非重复模式。缓冲区中的数字以 2.5 定点格式存储,这样它们都在 -4.0 和 4.0 之间,涵盖了我想要的高斯随机数范围。只需确保将 0.5 添加到您的随机数上,因为这将在以后四舍五入到最接近的整数。

    这基本上是每个像素和每个通道的工作原理:

    15 位线性值--通过 LUT--> 13 位(8.5 定点)伽马压缩值,然后添加 2.5 定点随机数,然后向右 SHIFT 5 位。

    现在你得到一个介于 -4 和 260 之间的整数值,你可以使用 if()s 来限制这些值,但是使用 264 元素 LUT 会更快,它为负数返回 0(你可以使用负数作为通过分配缓冲区然后执行 buffer = &buffer[4] 来创建索引,我猜会为您节省一个加法)并且对于 255 以上的数字返回 255。此外,我对三个颜色通道中的每一个都使用相同的随机数,这样可以避免色度噪声,虽然可以说,如果这三个使用独立的数字,结果可能看起来不那么嘈杂。

    对于单个像素的红色通道,我的代码如下所示: sfb[i].r = bytecheck_l.lutb[lsrgb_l.lutint[fb[i].r] + dither_l.lutint[id] >> 5]; sfb 是 sRGB 24 bpp 缓冲区,fb 是 45 bpp 线性 RGB 缓冲区,lsrgb_l.lutint[] 是线性到伽马压缩 LUT,dither_l.lutint[] 包含 2.5 定点格式的随机高斯数和 bytecheck_l 的 LUT .lutb[] 返回剪辑为 [0 , 255] 的值。

    性能

    我在 1400x820 SDL 窗口中获得超过 50 FPS 的测试梯度,仅使用 2.4 GHz Core 2 Quad Q6600 的一个内核和双通道 800 MHz DDR2 内存,按当前标准来看,这台机器有点平庸,所以这个解决方案看起来肯定适用于现代计算机。

    如果我的任何解释需要澄清,请告诉我。

    【讨论】:

    • 24 位系统中的相邻级别非常难以区分 - 为什么需要抖动?如果你使用抖动,为什么静态抖动不够好?
    • 我不同意,这是一个真正的问题,如果你在 Photoshop 的每通道 16 位 RGB 模式下使用渐变,你可以自己看看(因为与 8 位不同,它不会抖动你的看,Photoshop 在 8 位模式下抖动所有内容是有原因的,因为您可以看到条带)。并且清除“动态”抖动比静态抖动提供更好的结果,并且不会将它使您的图像更好的功能与您的图像实际包含的内容融合在一起,因为它不会误导您相信您的图像确实包含那种噪音。
    • 顺便说一句,问题是关于如何最好地显示“深色”内容,我可以理解为什么人们会认为“真彩色”对于大多数事情来说已经足够了,但这不是关于更高深度是否有用的问题,它们确实有用,而且由于大多数计算机显示器限制为 24 bpp,我认为尝试确定显示深色内容的最佳方式是有用的,而不是“最好的”方式。
    • 马克赎金,真的吗?您从未在您的生活中看到过 8 位渐变中的条带?啊,好吧,我不是第一个听到你这么说的人,但这总是有点令人惊讶,主要来自精通图形编程的程序员,尽管我也曾经认为 8 位就足够了。好吧,每件事都有第一次,所以我给你做了一个,很难不看到,你甚至可以很容易地计算波段,至少在校准的屏幕上:obvious_banding.png。现在我希望你能明白为什么有时 8 位可能不够用。
    • @MichelRouzic,感谢您提供的这个简单而有效的示例!我再也不会质疑超过 8 位/通道的需求了。有趣的是,我可以看到大多数乐队的过渡,但不是全部,这让我想知道我的显示器是否在做一些棘手的事情。我仍然质疑运动抖动的必要性,因为我发现静态抖动就足够了,即使是在 16 位和 24 位时 - 请参阅我在 stackoverflow.com/a/3963150/5987stackoverflow.com/a/11650801/5987 的示例。我希望我能抽出时间用你的例子复制这些结果。
    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 2011-01-31
    • 2021-10-11
    • 1970-01-01
    • 2021-07-11
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    相关资源
    最近更新 更多