iOS Metal。为什么简单地更改colorPixelFormat可以使图像更明亮?

时间:2019-01-18 14:42:01

标签: ios metal gamma

在iOS的Metal中,默认的colorPixelFormat为bgra8Unorm。当我将格式更改为rgba16Float时,所有图像都会变亮。为什么?

一个例子:

艺术品

enter image description here

MTKView,格式为bgra8Unorm。  纹理映射的四边形。用SRGB=false创建的纹理。

enter image description here

MTKView,格式为rgba16Float。  纹理映射的四边形。用SRGB=false创建的纹理。

enter image description here

为什么{strong> 的所有内容都比rgba16Float更亮。我的理解是SRGB=false表示在导入图稿时不进行伽玛校正。假设艺术品没有没有伽玛

这是怎么回事?

1 个答案:

答案 0 :(得分:0)

如果您的图稿具有伽玛值(每上传一张图片都具有伽玛值),则要在线性空间中使用它,必须将其转换为线性伽玛值。

这里发生的事情是您在线性工作空间中显示图像的伽玛编码值,而没有使用颜色管理或转换来转换这些

但:阅读您的一些评论后,纹理不是图像而是.svg吗?您是否将颜色值转换为线性空间?

实际情况是: RGB值是无意义的数字,除非您定义这些RGB值与给定空间的关系。

例如,sRGB中的

#00FF00是与Adobe98中的#00FF00不同的颜色。您的情况是线性的,但是什么是原色?仍在使用sRGB原色? P3小学?我没有看到真正的色调变化,所以我假设您在第二个示例中使用的是sRGB原色和线性传递曲线。

该说的是,中上等孩子的绿色衬衫的RGB值为#8DB54F,归一化为0-1,即0.553 0.710 0.310。这些数字本身不知道它们是否是伽玛编码与否。

sRGB,Y和光之间的关系:

出于讨论的目的,我们假设SIMPLE sRGB伽玛为1 / 2.2,而不是分段版本。对于L *,相同

在sRGB中,当#8DB54F在带有sRGB伽玛曲线的sRGB显示器上显示时,亮度(Y)为39

可以通过

找到

(0.553^2.2)*0.2126 + (0.710^2.2)*0.7152 + (0.310^2.2)*0.0722

0.057 + 0.33 + 0.0061 = 0.39 and 0.39 * 100 = 39 (Y)

但是,如果告诉颜色管理这些值是线性的,则将放弃伽玛校正,并且(或多或少):

0.553*0.2126 + 0.710*0.7152 + 0.310*0.0722

0.1175 + 0.5078 + 0.0223 = 0.65 and 0.65 * 100 = 65 (Y)

(假设使用相同的系数。)

像光一样,亮度(Y)是线性的。但是人的感知不是,sRGB值也不是。

Y是CIEXYZ的线性亮度,尽管它是根据眼睛对不同波长的响应进行光谱加权的,但亮度方面并不均匀。在0-100的范围内,18.4被认为是中间值。

L *是CIELAB的感知亮度(L * a * b *),它是(的简化曲线):

L* = Y^0.42在0-100的范围内,L * 50是“感知中间”值。因此,当Y 39的绿色衬衫在解释并显示为sRGB时为L * 69,Y 65约为L * 84(这些数字是基于数学原理,这是我MacBook上每个颜色选择器的值): / p>

sRGB Green Shirt linear green shirt

sRGB是伽马编码的信号,旨在充分利用每个通道8位的有限位深度。有效的伽玛曲线类似于人的感知,因此随着人的感知对黑暗区域的亮度变化更加敏感,更多的位用于定义较暗的区域。如上所述,这是一条简化的曲线:

sRGB_Video = Linear_Video^0.455 (需要注意的是,MONITOR添加了约1.1的指数)

因此,如果0%是黑色,而100%是白色,则中间是灰色,大多数人会说的是在0%和100%之间的点是:

Y 18.4%. = L* 50% = sRGB 46.7%

也就是说,sRGB十六进制值#777777将显示18.4 Y的亮度,并且等效于50 L *的感知亮度。中灰。

等等,还有更多

所以发生了什么,您正在告诉 MTKView,您正在向其发送引用 linear 值的图像数据。但是您实际上是实际向其发送 sRGB 值,由于应用了伽玛校正,该值更轻。然后色彩管理将其认为是线性值,并将其转换为输出显示所需的值。

颜色管理需要知道 mean 值是什么,它们与什么颜色空间有关。设置SRGB=false时,它告诉您它正在发送的是线性值,而不是伽玛编码值。

但是,您显然将伽玛编码的值发送到线性空间,而无需将这些值转换/解码为线性。除非您隐式执行线性化,否则不会发生线性化。

解决方案

线性化图像数据或设置标志SRGB=true

如果您还有其他问题,请告诉我。而且,您可能希望查看Poynton Gamma FAQ或颜色常见问题解答以进行说明。

另外,对于您的灰色:线性值0.216等于sRGB(0-1)值0.500