赞
踩
据我所知,还不太可能找到从色温到RGB转换的一个可靠的公式。虽然,有很多算法实现了类似的功能,但是,大多是都是从色温转换到XYZ颜色空间。这之后你再可以根据需要从XYZ空间在转换到RGB颜色空间。这种算法的一种实现方式你可以在这找到。
很不幸的是,这种方式并不是真正意义上的数学公式,只是一种美化的查找表实现方式。在某些情况下,这是一种可靠地实现方式。但是,当涉及到XYZ->RGB转换的时候,对简单的实时色温调整而言,这种方式太慢了。
因此,我实现了一套色温到RGB转换的算法。这个算法转换相当不错。以下是我的一些思路。
下图是算法输出1000K到40000K的图像。
下图是摄影学感兴趣的色温范围:从1500K到15000K
算法实现思路
我的第一步工作是从Charity’s original blackbody values 逆向工程方式实现一个可靠的公式。
Charity’s original blackbody values 的数据用图表的形式表示为:
从图表可以看出,有一些上限值和下限值,使得我们的算法很容易实现。特别的:
为了更好地拟合这些数据,绿色分量被划分为两部分进行拟合。一部分是低于6600K;另一部分是高于6600K。
之后,我把数据分成独立的颜色分量进行拟合。(不包括那些总是为0和255的数据)。理想状态下,有一条曲线将经过每一个数据点。但现实情况,往往没这么理想。因为对于上图中X轴和Y轴的数据而言,它们的数值相差太大。X轴的数值都大于1000,对于Y轴而言,其数值范围在0到255之间。我们必须对X轴的数据做相应的转换才能更好的进行曲线拟合。为了达到最优拟合的目的,我对X轴的数据做了除100处理,并进行了相应的偏移。以下是每个分量的数据分布和最优的拟合曲线:
如上图所述,其曲线拟合的很好。
算法实现
以下是算法实现的伪代码:
- 输入:1000K到40000K的色温;色温和颜色分量的变量必须是双精度
-
- Set Temperature = Temperature \ 100
-
-
- Calculate Red:
-
- If Temperature <= 66 Then
-
- Red = 255
-
- Else
-
- Red = Temperature - 60
-
- Red = 329.698727446 * (Red ^ -0.1332047592)
-
- If Red < 0 Then Red = 0
-
- If Red > 255 Then Red = 255
-
- End If
-
-
- Calculate Green:
-
- If Temperature <= 66 Then
-
- Green = Temperature
-
- Green = 99.4708025861 * Ln(Green) - 161.1195681661
-
- If Green < 0 Then Green = 0
-
- If Green > 255 Then Green = 255
-
- Else
-
- Green = Temperature - 60
-
- Green = 288.1221695283 * (Green ^ -0.0755148492)
-
- If Green < 0 Then Green = 0
-
- If Green > 255 Then Green = 255
-
- End If
-
- Calculate Blue:
-
- If Temperature >= 66 Then
-
- Blue = 255
-
- Else
-
- If Temperature <= 19 Then
-
- Blue = 0
-
- Else
-
- Blue = Temperature - 10
-
- Blue = 138.5177312231 * Ln(Blue) - 305.0447927307
-
- If Blue < 0 Then Blue = 0
-
- If Blue > 255 Then Blue = 255
-
- End If
-
-
- End If
上述伪代码中,Ln()表示的是自然对数。
以下是VB的代码实现。以下代码未做优化,但是代码简短可读性好。
- Static tmpCalc As Double
-
-
- 'Temperature must fall between 1000 and 40000 degrees
-
- If tmpKelvin < 1000 Then tmpKelvin = 1000
-
- If tmpKelvin > 40000 Then tmpKelvin = 40000
-
-
-
- 'All calculations require tmpKelvin \ 100, so only do the conversion once
-
- tmpKelvin = tmpKelvin \ 100
-
-
-
- 'Calculate each color in turn
-
-
-
- 'First: red
-
- If tmpKelvin <= 66 Then
-
- r = 255
-
- Else
-
- 'Note: the R-squared value for this approximation is .988
-
- tmpCalc = tmpKelvin - 60
-
- tmpCalc = 329.698727446 * (tmpCalc ^ -0.1332047592)
-
- r = tmpCalc
-
- If r < 0 Then r = 0
-
- If r > 255 Then r = 255
-
- End If
-
- 'Second: green
-
- If tmpKelvin <= 66 Then
-
- 'Note: the R-squared value for this approximation is .996
-
- tmpCalc = tmpKelvin
-
- tmpCalc = 99.4708025861 * Log(tmpCalc) - 161.1195681661
-
- g = tmpCalc
-
- If g < 0 Then g = 0
-
- If g > 255 Then g = 255
-
- Else
-
- 'Note: the R-squared value for this approximation is .987
-
- tmpCalc = tmpKelvin - 60
-
- tmpCalc = 288.1221695283 * (tmpCalc ^ -0.0755148492)
-
- g = tmpCalc
-
- If g < 0 Then g = 0
-
- If g > 255 Then g = 255
-
- End If
-
-
- 'Third: blue
-
- If tmpKelvin >= 66 Then
-
- b = 255
-
- ElseIf tmpKelvin <= 19 Then
-
- b = 0
-
- Else
-
- 'Note: the R-squared value for this approximation is .998
-
- tmpCalc = tmpKelvin - 10
-
- tmpCalc = 138.5177312231 * Log(tmpCalc) - 305.0447927307
-
-
-
- b = tmpCalc
-
- If b < 0 Then b = 0
-
- If b > 255 Then b = 255
-
- End If
-
-
-
- End Sub
算法效果:
下图是色温调整算法实现的效果图。左侧是原始图像,有测试经过上述色温调整算法后的图像。
实际在工具中实现的效果如下图所示:
有选择的翻译至:http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。