14

色彩空间。好了,大家都知道RGB了:在[0.0,1.0]范围内归一化的三个值,分别代表颜色分量Red Green Blue的强度;这种强度是线性的,不是吗?

伽玛。据我所知,伽玛是将RGB颜色分量映射到另一个值的函数。谷歌搜索,我看到了线性函数和非线性函数......线性函数似乎可以缩放 RGB 分量,所以它似乎可以调整图像亮度;非线性函数似乎可以“解压缩”较暗/较亮的组件。

现在,我开始实现一个图像查看器,它将不同的图像格式显示为纹理。我想修改这些图像的伽玛,所以我应该建立一个片段着色器并在纹理四边形上运行。很好,但我如何确定正确的伽马校正?

OpenGL 使用线性 RGB 颜色空间,使用浮点组件。实际上,我可以从这些值开始计算伽马校正值(具有特殊的浮点精度),因此它们在钳位伽马校正值后显示。

首先,我将确定伽马斜坡。我怎么能确定呢?(分析或使用查找表)

然后,我开始研究 OpenGL 扩展 EXT_framebuffer_sRGB,这似乎与扩展EXT_texture_sRGB非常相关。

EXT_texture_sRGB 引入了一种新的纹理格式,用于将文本值线性化到 RGB 线性空间中。(脚注1)通过这种方式,我知道sRGB色彩空间并将其用作线性RGB色彩空间。

相反,EXT_framebuffer_sRGB 扩展允许我将线性 RGB 值编码到 sRGB 帧缓冲区,而不用担心它。

...

等等,所有这些信息是为了什么?如果我可以使用 sRGB 帧缓冲区并加载 sRGB 纹理,则无需 sRGB 转换即可处理该纹理……我为什么要更正伽玛?

也许即使在 sRGB 缓冲区上,我也可以同样校正伽玛?或者我最好不要?以及亮度和对比度:它们应该在伽马校正之前还是之后应用?

信息量很大,我现在很困惑。希望你们中的某个人能更多地向我解释所有这些概念!谢谢你。

...

还有一个问题。如果设备伽玛不同于“标准”2.2,我如何“累积”不同的伽玛校正?我不知道是否清楚:如果图像 RGB 值已经针对伽马值为 2.2 的显示器进行了校正,但显示器的伽马值为 2.8,我该如何校正伽马?


(1) 这里有一些摘录来强调我的意思:

sRGB 色彩空间基于昏暗办公室中预期的典型(非线性)显示器特性。它已被国际电工委员会 (IEC) 标准化为 IEC 61966-2-1。sRGB 颜色空间大致对应于 2.2 伽马校正。


此扩展是否提供任何类型的 sRGB 帧缓冲区格式或保证使用 sRGB 纹理渲染的图像在输出到支持 sRGB 颜色空间的设备时“看起来不错”?

   RESOLVED:  No.

  Whether the displayed framebuffer is displayed to a monitor that
    faithfully reproduces the sRGB color space is beyond the scope
    of this extension.  This involves the gamma correction and color
    calibration of the physical display device.

    With this extension, artists can author content in an sRGB color
    space and provide that sRGB content for use as texture imagery
    that can be properly converted to linear RGB and filtered as part
    of texturing in a way that preserves the sRGB distribution of
    precision, but that does NOT mean sRGB pixels are output
    to the framebuffer.  Indeed, this extension provides texture
    formats that convert sRGB to linear RGB as part of filtering.

    With programmable shading, an application could perform a
    linear RGB to sRGB conversion just prior to emitting color
    values from the shader.  Even so, OpenGL blending (other than
    simple modulation) will perform linear math operations on values
    stored in a non-linear space which is technically incorrect for
    sRGB-encoded colors.

    One way to think about these sRGB texture formats is that they
    simply provide color components with a distribution of values
    distributed to favor precision towards 0 rather than evenly
    distributing the precision with conventional non-sRGB formats
    such as GL_RGB8.
4

3 回答 3

8

不幸的是,OpenGL 本身并没有定义颜色空间。只是定义了传递给 OpenGL 的 RGB 值形成一个线性向量空间。然后将渲染帧缓冲区的值原样发送到显示设备。OpenGL只是通过值。

Gamma 服务于两个目的:

  • 感官知觉是非线性的
  • 在过去,显示设备具有非线性响应

伽马校正用于补偿两者。

转换只是“线性值 V 到某个幂 Gamma”,即 y(v) = v^gamma

色彩空间转换涉及从输入值到发送到显示器的完整链,因此这包括伽马校正。这也意味着您不应该自己操纵伽马斜坡。

很长一段时间以来,典型的 Gamma 值曾经是 2.2。然而,这导致了一些不希望的低值量化,因此 Adob​​e 引入了一个新的色彩空间,称为 sRGB,它具有低值的线性部分和较高值的指数约 2.3 的幂函数。如今,大多数显示设备都使用 sRGB。如今,大多数图像文件也是 sRGB 格式。

因此,如果您有一个 sRGB 图像,并在 sRGB 显示设备上按原样显示,并在设备上配置了线性伽马斜坡(即视频驱动程序 gamma=1),那么您只需使用 sRGB 纹理和帧缓冲区而不做还要别的吗。

由于评论而编辑

简单总结一下:

如果您的系统不支持 sRGB 帧缓冲区:

于 2011-06-18T18:09:45.867 回答
6

等等,所有这些信息是为了什么?如果我可以使用 sRGB 帧缓冲区并加载 sRGB 纹理,则无需 sRGB 转换即可处理该纹理……我为什么要更正伽玛?

一般来说,你不会。sRGB 纹理和帧缓冲区的目的是让您不必手动进行伽马校正。来自 sRGB 纹理的读取被转换为线性色彩空间,写入 sRGB 帧缓冲区采用线性 RGB 值并将它们转换为 sRGB 值。这一切都是自动的,而且在性能方面更重要

唯一需要进行 gamma 校正的情况是显示器的 gamma 与 2.2 gamma 的 sRGB gamma 近似值不匹配。很少有显示器可以做到这一点。

您的纹理不必sRGB 颜色空间中。但是,大多数图像创建应用程序会将图像保存在 sRGB 中并使用 sRGB 中的颜色,因此无论您是否希望它们是,您的大多数纹理都可能已经在 sRGB 中。sRGB 纹理功能只允许您实际获得正确的颜色值,而不是您一直到现在为止的颜色值。

以及亮度和对比度:它们应该在伽马校正之前还是之后应用?

我不知道你说的亮度和对比度是什么意思。这应该由监视器设置,而不是您的应用程序。但实际上,您想要对图像数据执行的所有数学运算都应该在线性色彩空间中完成。因此,如果给定 sRGB 颜色空间中的图像,则需要对其进行线性化,然后才能对其进行任何数学运算。sRGB 纹理功能使这一切变得免费,而不必进行复杂的着色器数学运算。

于 2011-06-18T18:18:44.590 回答
0

RGB

RGB:在[0.0,1.0]范围内归一化的三个值,表示颜色分量Red Green Blue的强度;这种强度是线性的,不是吗?

不。除非定义了与特定空间/编码的相关性,否则 RGB 值是无意义的数字。它们可能是线性的、伽马编码的或对数编码的,或者使用像 Rec709 和 sRGB 规范这样的复合传输曲线。

此外,它们与颜色空间中定义的原色和白点相关,例如,sRGB 中的#00FF00 与 DCI-P3 中的#00FF00 是不同的颜色。

要定义 RGB 像素值应如何显示,您不仅需要 RGB 三元组,还需要知道它打算用于的色彩空间,其中需要包括主坐标、白点和传输曲线。

sRGB 是用于 Web 和通用计算的默认“标准”RGB 颜色空间。它HDTV 的标准色彩空间 Rec709 有关。

GAMMA 又名转移曲线

伽玛。据我所知,伽玛是将RGB颜色分量映射到另一个值的函数。

图像伽玛利用人类感知的非线性来充分利用每通道图像 8 位的有限数据大小。人眼对较暗颜色的变化更敏感,因此更多位 ae 用于定义伽马编码图像中的较暗颜色。

在数字化之前,伽玛也被用于 NTSC 广播系统,以抑制信号中的明显噪声,其方式类似于图像伽玛如何防止每通道 8 位图像出现“条带”伪影。

首先,我将确定伽马斜坡。我怎么能确定呢?(分析或使用查找表)

伽玛曲线。sRGB 伽玛曲线很容易访问。这是从 sRGB 到线性的Wikipedia 链接。您还可以使用简单地使用 2.2 指数曲线的“简化”方法:

linearVideo = sRGBvideo^2.2和简化的逆,回到 sRGB:

sRGBvideo = linearVideo^0.4545

使用简化版会引入一些轻微的 Gamma 错误,建议在关键操作或图像将多次“往返”的情况下使用“正确”曲线。

还有一个问题。如果设备伽玛不同于“标准”2.2,我如何“累积”不同的伽玛校正?我不知道是否清楚:如果图像 RGB 值已经针对伽马值为 2.2 的显示器进行了校正,但显示器的伽马值为 2.8,我该如何校正伽马?

2.8 ???那是什么显示器?朋友?这很不寻常——虽然 PAL 规范这么说,但 2.8 并不“实用”。监视器通常在 2.3 到 2.5 左右,具体取决于它们的设置方式。当您调整黑电平和对比度(白电平)时,您实际上是在调整感知伽马以匹配观看环境(房间照明)。

仅供参考,虽然 sRGB“信号”的编码伽马为 1/2.2,但显示器通常会增加约 1.1 的指数

对于 Rec709,编码信号的有效伽马约为 1/1.9 ish,但参考观看环境中的监视器约为 2.4

在这两种情况下,都有一个有意的系统伽马增益。

如果您想使用 2.8 显示器的 gamma 对图像进行编码并且您不希望系统 gamma 增益,则指数为 1/2.8

常用的“最高”伽马用于数字电影(以及 Rec2020),为 2.6 对于那些认为 PAL 和 2.8 的人,我鼓励您阅读有关该主题的 Poynton:

强烈推荐阅读

Charles Poynton 的 Gamma FAQ很容易阅读,并且完整地描述了这些问题以及它们在图像管道中的重要性。还可以在同一链接阅读他的颜色常见问题解答。

关于线性与 sRGB 的几句话

在线性工作空间中处理图像通常是理想的,因为它不仅简化了数学运算,而且模拟了现实世界中的光线。世界上的光以线性方式(加法)工作。但如果以线性方式工作,则需要足够的位深度,而 8 位是不够的。

人类感知是非线性的。图像伽玛编码利用非线性来充分利用 8 位图像容器。当您转换为线性时,您需要更多的位。每个通道 12 位被认为是最低要求,但 16 位浮点数是线性工作空间的最低“推荐最佳实践”。

如果在线性渲染环境中使用纹理,则需要将这些纹理转换为线性空间(通常是更深的位深度)。虽然添加的位增加了数据带宽,但简化的数学运算通常允许更快的计算。

sRGB 是一个 DISPLAY REFERRED 空间,它用于 DISPLAY 目的,并用于以紧凑的“显示就绪”状态存储图像。黑0白255,传递曲线接近1/2.2

sRGB 基于 Rec709 (HDTV),并使用相同的原色和白点。但传输曲线和数据编码不同。Rec709 旨在在黑暗的客厅中显示在较高伽马监视器上,并在 16 处编码黑色,在 235 处编码白色。

于 2019-04-30T03:59:44.493 回答