色彩空间和转换






4.98/5 (32投票s)
一个用于颜色模型和色彩空间、正确颜色转换和颜色差计算的库。
介绍
我偶然发现了许多颜色转换库/工具,它们没有考虑到 RGB 颜色本身并没有被明确定义。了解 RGB 颜色值所属的确切 RGB 色彩空间(例如 sRGB
、AdobeRGB
或 ProPhotoRGB
)非常重要,因为它们具有不同的参考白点、不同的伽马值和不同的色度坐标。同样,其他颜色模型也同样重要。
由于我需要为另一个软件提供这些功能,想多了解一些关于颜色方面的知识,并让互联网变得更好,所以我写了这个库。
还有一些小型 GUI:
- 转换:与所有支持的颜色模型进行相互转换
- 颜色差:以多种方式计算两种颜色之间的差异
- 速度:测量从一种颜色模型转换为另一种颜色模型所需的时间
背景
库中包含几种不同的颜色模型和色彩空间
- CIE XYZ (CIE 1931 2°)
- CIE Yxy (CIE 1931 2°)
- CIE L*a*b* (CIE 1976)
- CIE L*u*v* (CIE 1976)
- CIE LCHab
- CIE LCHuv
- DIN99 (LCH99)
- DIN99b (LCH99b)
- DIN99c (LCH99c)
- DIN99d (LCH99d)
- RGB
- NTSCRGB
- BruceRGB
- CIERGB
- AdobeRGB
- AppleRGB
- ProPhotoRGB
- sRGB
- WideGamutRGB
- BestRGB
- BetaRGB
- ColorMatchRGB
- DonRGB4
- EktaSpacePS5
- PAL_SECAMRGB
- SMPTE_C_RGB
- HSV
- HSL
- CMY
- CMYK
- YCbCr
- ITU-R BT.601-625
- ITU-R_BT.601-525
- ITU-R-BT.709-1125
- ITU-R BT.709-1250
- Gray
- DEF
- Bef
- BCH
- X-Channel Color (with X from 2 to 15)
- ICC Profiles (alpha status)
还可以进行色度适应并更改参考白点。
这些颜色模型之间的转换如下所示
如果您想了解更多关于转换如何工作的信息:
- 阅读我 **包含所有公式和代码的 PDF **
- CIE 颜色:访问 Bruce Lindbloom 的网站
- HSV/HSL:维基百科文章
- YCbCr:维基百科文章或 ITU 主页以获取确切规范
- RGB 色彩空间:查看此通用 RGB 色彩空间维基百科文章中每个色彩空间的特定文章
- DIN99:这篇 Yang Xue 的 PDF
- DEF, Bef, BCH:这篇 Sergey Bezryadin 的 PDF
- ICC:查看 官方规范
#region Conversions
)或者直接问我。使用代码
使用该库非常简单,但仍为您提供了定义或转换颜色的所有可能性。
让我们看一下 ColorConverter
类的静态部分。有一些设置将在不另行指定的情况下使用。这些设置是
-
ChromaticAdaptionMethod
:用于转换的色度适应方法 -
ReferenceWhite
:如果不另行指定,将用于颜色的参考白点 -
StandardColorspace
:如果不另行指定,将使用的标准色彩空间 -
PreferredRenderingIntent
:如果不另行指定且在 ICC 配置文件中可用,将使用的首选渲染意图 -
StandardYCbCrSpace
:如果不另行指定,将用于 YCbCr 颜色的标准色彩空间
另外,在开始使用该库之前,您应该初始化 ColorConverter
类。如果您不初始化,不会出错,但这样一切都将得到受控的运行
ColorConverter.Init();
以下是一些创建新颜色的示例。还有一些其他可能性,您可以根据需要进行尝试。代码已记录,您将看到解释。
ColorRGB color = new ColorRGB(RGBSpaceName.sRGB); //new RGB color in sRGB space
ColorRGB color = new ColorRGB(0, 0.5, 1); //new RGB color in standard RGB space from settings
ColorRGB color = new ColorRGB(RGBSpaceName.sRGB, 0, 0.5, 1, true); //new linear RGB color in sRGB
ColorRGB color = new ColorRGB(new ICC("profile.icc")); //new RGB color from an ICC profile
ColorLab color = new ColorLab(50, 12, -12); //new Lab color with reference white from settings
ColorLab color = new ColorLab(new Whitepoint(WhitepointName.D50)); //new Lab color with D50 reference white
ColorCMYK color = new ColorCMYK(new ICC("CMYKprofile.icc")); //CMY(K) colors have to have an ICC profile
要将一种颜色转换为另一种颜色,请使用 ColorConverter
类。请注意,如果使用多线程,每个线程都必须拥有自己的 ColorConverter
类实例!
ColorConverter Converter = new ColorConverter(); //create a new instance of a ColorConverter
ColorLab lab = new ColorLab(50, 12, -12); //create a Lab color
ColorRGB rgb = Converter.ToRGB(lab, RGBSpaceName.sRGB); //convert it to an RGB color in AdobeRGB colorspace
ColorConverter Converter = new ColorConverter(); //create a new instance of a ColorConverter
ColorRGB rgb = new ColorRGB(RGBSpaceName.AdobeRGB, 0, 0.5, 1); //create an RGB color
ColorLab lab = Converter.ToLab(rgb, WhitepointName.D50); //convert it to a Lab color with D50 reference white
ColorLab lab = Converter.ToLab(rgb); //or convert it to a Lab color with the default reference white
使用 ICC 配置文件进行转换有点不同,可能尚未正确工作。由于缺乏不同的配置文件和与正确值的比较,我尚未对其进行彻底测试。尽管如此,我还是将其包含在此处,如果您发现任何错误/bug,请向我报告。
ColorConverter Converter = new ColorConverter(); //create a new instance of a ColorConverter
ColorLab lab = new ColorLab(50, 12, -12); //create a Lab color
ColorRGB rgb = (ColorRGB)Converter.ToICC(lab, new ICC("profile.icc")); //convert a color with an ICC profile
要查找两种颜色之间的差异,请使用 ColorDifference
类(非多线程安全)
ColorLab lab1 = new ColorLab(0.5, 30, -12); //create the first Lab color
ColorLab lab2 = new ColorLab(0.5, 40, -2); //create the second Lab color
double difference = ColorDifference.GetDeltaE_CIEDE2000(lab1, lab2); //calculate the difference with CIE DE 2000 method
或者使用 Din99c 方法
ColorLCH99c din1 = new ColorLCH99c(50, 12, 120); //create the first DIN99c color
ColorLCH99c din2 = new ColorLCH99c(50, 16, 140); //create the second DIN99c color
double difference = ColorDifference.GetDeltaE_DIN99(din1, din2); //calculate the difference with the DIN99 method
对于某些方法,您也可以使用 GetDeltaC
来获取 Chroma
(色度)差,使用 GetDeltaH
可以获取 Hue(色相)差。
对于色度适应,只需从一种 XYZ 颜色转换为另一种
ColorConverter Converter = new ColorConverter(); //create a new instance of a ColorConverter
ColorXYZ xyz = new ColorXYZ(new Whitepoint(WhitepointName.D50), 0, 0.5, 1); //create a XYZ color with D50 reference white
xyz = Converter.ToXYZ(xyz, WhitepointName.D65); //convert it to a XYZ color with a different reference white
如果需要在转换过程中进行色度适应,例如从 RGB 到 Lab,这当然会自动完成,您不必担心。我只是想提一下,您也可以显式地进行。
自 3.0 版本以来,还有一个 Light
命名空间可用。它包含一些颜色模型,这些模型将所有值存储为字节(8 位 - BColor
)或 ushort(16 位 - UColor
),并且通常比标准颜色类更轻量级。轻量级类的工作方式与普通类相同,并且 ColorConverter
类也可用于转换。
使用 GUI
转换
如果您只是想知道某种颜色在其他色彩空间中的表示方式,可以使用此 GUI。输入您已知颜色的值,然后按框旁边的“Convert”按钮。
- 点击此方块可从颜色选择器中选择 RGB 值
- 通用设置
- 每种颜色的特定设置
颜色差
要比较两种颜色,请使用此 GUI 以不同的方式查看计算出的差异。右侧是通用设置。要计算差异,请选择并设置您要比较的两种颜色,然后单击“Compare”。要设置值,请选择通道,然后在上面的文本框中输入值。结果将在下方显示。Delta E 是差异,Delta H 是色相差,Delta C 是色度差。
速度
要查看转换速度,请使用此 GUI。您还可以看到多线程带来的差异。在右侧,您可以设置迭代次数、通用设置以及要使用的线程数。设置好颜色后,单击“Start”并等待结果。总时间是指所有迭代所花费的时间(以毫秒为单位),每次迭代的时间是指一次转换所需的平均时间(以微秒为单位)。
限制
如前所述,ICC 配置文件仍处于 alpha 状态,尚未经过彻底测试。如果您对 ICC 配置文件及其转换工作原理有所了解,我将非常感谢您的帮助。 而且由于它尚未真正完成,因此使用 ICC 配置文件进行转换的速度相当慢(与正常转换相比)。
关注点
好吧,学习所有这些色彩空间的工作原理确实让我好几次头疼,但现在(我认为)我理解了。所以,如果您对这里的任何内容的工作原理有任何疑问,请随时提问。
计划
对于未来的版本,我计划
- 超出范围警告/检查
- 渲染意图计算
- 更好、更快的 ICC 支持
历史
- 2013 年 7 月 - 版本 1.0(库和 GUI)
- 2013 年 9 月 - 版本 2.0(库和三个 GUI)
- 更改了 RGB 颜色的结构
- 将转换从颜色类分离到新的转换类
- 添加了几个新的颜色模型
- 添加了 ICC 支持
- 添加了色度适应
- 添加了颜色差类
- 为颜色差和速度测量添加了 GUI
- 大大提高了转换速度
- 2013 年 11 月 - 版本 3.0(库和三个 GUI)
- 修复了 LCHuv 计算中的一个错误
- 修复了 Delta E CMC 计算中的一个错误
- 修复了其他小错误
- 修复了一个错误并在 Color.Copy() 中添加了 DIN99 颜色
- 修复了 ColorDifference CMC 方法:Lab 需要 D65 参考白点
- 添加了带自定义 l:c 值的 Delta E CMC 计算
- 添加了从 DIN99c 和 DIN99d 到所有其他颜色模型的转换
- 为颜色添加了 Light 版本:以字节或 ushort 存储值以减小内存占用
- 添加了 DEF、Bef 和 BCH 颜色模型以及所有转换