改进网络上的色彩

过去几年,显示技术取得了显著进步。首先是屏幕分辨率的提升,从移动设备开始,然后是台式机和笔记本电脑。Web 开发者必须了解高 DPI 并知道如何实现利用额外分辨率的页面设计。显示器领域的下一个革命性改进正在发生:更好的色彩再现。在这里,我将解释这意味着什么,以及作为 Web 开发者,您如何检测此类显示器并为您的用户提供更好的体验。

我们把您已经使用了十多年的典型电脑显示器称为 sRGB 显示器。Apple 最近的硬件,包括 2015 年末的 Retina iMac 和 2016 年初的 iPad Pro,能够显示比 sRGB 显示器更多的色彩。这类显示器被称为 广色域(我将在下面解释 sRGB 和色域的含义)。

这为什么有用呢?广色域系统通常能更准确地再现原始色彩。例如,我的同事 @hober 有一些非常时髦的鞋子。

hober's bright orange shoes

不幸的是,您上面看到的图片并没有真正传达出这双鞋有多么时髦!问题在于鞋子的面料使用了 sRGB 显示器无法表示的颜色。拍摄这张照片的相机(Sony a6300)有一个能够捕捉更准确颜色信息的传感器,并且这些数据包含在原始文件中,但显示器无法显示。以下是这张照片的一个版本,其中所有超出典型显示器色彩范围的像素都被浅蓝色替换了

hober's bright orange shoes, but with all the out-of-gamut pixels replaced by blue

如您所见,鞋面面料和大部分草地的颜色都超出了 sRGB 显示器的范围。事实上,照片中只有不到一半的像素得到了准确呈现。作为一名 Web 开发者,您应该对此感到关注。假设您是一家销售这些鞋子的在线商店。您的顾客将无法确切知道他们订购的颜色,并且在收到商品时可能会感到惊讶。

使用广色域显示器可以减轻这个问题。如果您有上述提到的设备之一,或者类似的设备,这里有一个版本的照片可以向您展示更多颜色

hober's bright orange shoes, this time with a color profile embedded

对于使用广色域显示器的用户,您会看到鞋子呈现更鲜艳的橙色,绿草的颜色变化也略微更多。不幸的是,如果您没有广色域显示器,您看到的可能与上面的第一张图片非常接近。在这种情况下,我能提供的最好帮助就是那张着色图片,它突出显示了您所缺失的图像部分。

总之,这是个好消息!广色域显示器更加生动,能更准确地描绘现实。显然,您会希望确保为用户提供利用这项技术的图像内容。

这里是另一个例子,这次是用生成的图像。对于 sRGB 显示器用户来说,下方有一个均匀的红色方块。然而,这其中有点小把戏。那张图片中实际上有两种不同色调的红色,其中一种只有在广色域显示器上才能区分开。在这样的显示器上,您会在红色方块内看到一个模糊的 WebKit 标志。

A red square with a faint WebKit logo

有时,普通图像和广色域图像之间的差异很细微。有时则更为显著。

演示

请查看这个示例页面,它允许您在不同版本的图像之间切换进行比较,并向您展示图像中哪些像素超出了 sRGB 显示器的范围。还有一个稍微更具交互性的版本,可以并排显示不同的图像。

定义

以下是关于您在讨论色彩时经常会听到的一些术语的快速解释。

色彩空间:色彩空间是您定义和比较色彩的环境。存在几种类型的色彩空间,每种都使用不同的参数集来描述色彩。例如,灰度色彩空间只有一个参数,用于控制从黑到白的亮度级别。您可能熟悉 RGB 类型的色彩空间,它使用红、绿、蓝作为参数,代表显示器中组合形成最终颜色的光线。印刷工作流程通常使用 CMYK 类型的色彩空间,其中青色、品红色、黄色和黑色是代表油墨颜色的参数。

色彩配置文件:1993 年,一群供应商组建了 ICC,旨在定义一个描述色彩空间的标准。色彩配置文件是定义设备色彩空间的数据,可用于在不同空间之间进行转换。常见的色彩配置文件都有名称,例如 sRGB(或更正式地,IEC 61966-2-1)。我上面使用 sRGB 的含义现在更明确了:这种显示器能够显示与 sRGB 色彩空间相对应的颜色。色彩配置文件数据可以写入文件,或直接嵌入到图像中,这使得计算机能够理解图像中的色彩值实际表示什么。

色域:色域是设备可以处理的颜色范围,或者说色彩空间可以定义的颜色范围。对于电脑显示器来说,色域是它能准确显示的所有颜色。可视化色域有点复杂,但它与您在设计软件中看到的拾色器有些相似。想象一下所有可能颜色应用于一个表面的范围,原色位于不同的极端。当您朝红色极端移动时,颜色会变得更红。朝蓝色移动时,颜色会变得更蓝,依此类推。色域是这个想象表面上的一个区域,代表设备在所有方向上所能达到的最远范围。您可能会看到色域用这样的图表表示,其中彩色形状显示了典型人眼所能看到的范围,白色三角形显示了 sRGB 色彩空间的范围(正如您所注意到的,它比人眼能检测到的范围小得多)。

Diagram showing the sRGB gamut
图片来源:维基百科

这些图表可能会有些误导,因为它们向您展示了您显然能看到的颜色,然后又告诉您某个色域不包含这些颜色。然而,它们确实提供了一种很好的方式来比较不同色域的大小。另请注意,这里您看到的是色域表面的二维表示,而实际上它是一个三维或四维空间(这一切都相当复杂——我们只是想提供一个简单的介绍)。

广色域:这是一个行业中用来描述色域大于 sRGB 的设备或色彩空间的非正式术语,sRGB 是过去十年来几乎所有电脑显示器所使用的色域。更广色域的显示器已经存在一段时间了,但主要局限于专业用途。现在它们正逐渐面向普通消费者,这意味着有更多的颜色可用。有时广色域也被称为 扩展色域。现代的 Apple 显示器支持 Display P3 色彩空间,它比 sRGB 宽约 25%。 (更新:Chris Lilley 指出 P3 的体积约为 120 万 Lab 单位,而 sRGB 约为 80 万,因此 P3 大约大 50%)

色彩深度:计算机可以使用不同级别的精度或深度来表示颜色。这与描述颜色范围的色域不同。色彩深度是指在色域内可以定义的独立颜色的数量。Web 开发者可能熟悉 CSS 的 rgb() 语法,它为红色、绿色和蓝色取值 0-255。这意味着每个通道有 8 位深度,总共可以表示 16,777,216 种不同的颜色。如果您加入 alpha/不透明度,则可以将颜色存储在 32 位中。如果您使用每个通道 8 位的深度,无论您使用什么色彩空间——它都只能表示相同数量的颜色,只是颜色集合不同。如果您选择每个通道 16 位,您将拥有更深的色彩空间,并且可以在色域内表示更多颜色。一个很好的例子是当您在相似颜色之间绘制渐变时:您会看到 色带 现象,这是因为计算机和显示器没有足够的深度来显示终点之间平滑的颜色范围。

这是一个示例,展示了色彩深度不足如何产生色带现象,即使终点之间的所有颜色都在色域内(这是一个为了夸大效果的人工示例)。

较小的色彩深度可能会在相似颜色之间显示出明显的跳跃。

A light red to dark red gradient with distinct bands

拥有更大的色彩深度,跳跃现象则会明显减少。

A light red to dark red gradient without distinct bands

在介绍了这些概念之后,让我们深入探讨网络上的色彩细节以及 WebKit 为帮助您开发更注重色彩的内容而进行的最新改进。我们还将介绍我们向 W3C 提出的一些功能,这些功能将使您能够更好地利用这种新的显示技术。

网络上的色彩

网络在正确处理颜色方面一直面临挑战。我相信有些读者会痛苦地回忆起 网络安全色!虽然我们已经摆脱了那个时代,但我们仍然存在局限性,例如 HTML 和 CSS 被定义为只能在 sRGB 色彩空间中工作。就像上面 hober 的鞋子的例子一样,这意味着您的 CSS、图像和 Canvas 无法表示许多颜色。如果您想向家人展示花园里盛开的春花,或者购买一辆鲜红色的跑车来缓解中年危机,这都会成为一个问题。

因此,当我们展示上面的鞋子照片时,sRGB 显示器将所有超出 sRGB 色域的颜色压缩到它能显示的颜色中。但像 Display P3 这样的广色域显示器则无需压缩到 sRGB。这里有一个视觉表示,展示了 sRGB 和 Display P3 色彩空间之间的差异。

sRGB P3 gamut comparison

彩色三角形是 sRGB 空间。白色三角形显示了 Display P3 空间的覆盖范围,它比 sRGB 大得多,特别是在更饱和的红色、黄色、紫色和绿色方面。黑色轮廓显示了典型人眼的能力。

还记得那个带有模糊 WebKit 标志的红色方块吗?那是通过在 Display P3 色彩空间中创建图像,将其填充为 100% 红色,即 rgb(255, 0, 0),然后用略有不同的红色 rgb(241, 0, 0) 绘制标志而生成的。在 sRGB 显示器上,您看不到该标志,因为 Display P3 中所有高于 241 的红色值都超出了 sRGB 中的最高红色值,所以 241 红色和 255 红色最终显示为相同的颜色。

注意:我在 Twitter 上看到一些关于此的困惑,所以让我们尝试另一种解释。基本上,Display P3 色彩空间中介于 241/255 和 255/255 之间的所有纯红色值在 sRGB 中显示时是无法区分的。这并不意味着 Display P3 的 241 红色与 sRGB 的 255 红色相同——不幸的是,它没有那么简单,我也不想在这篇介绍性文章中过于深入。对于感兴趣的人,macOS 上有一个名为 Color Sync Utility 的应用程序,它允许您以不同方式在色彩空间之间进行转换,以及比较色域。

所以现在您明白了为什么应该关注色彩,以及为什么应该利用这项技术为用户提供更好的体验。这就是背景——接下来我们来谈谈这对 WebKit 意味着什么。

图像色彩匹配

我们上面提到,Web 被定义为使用 sRGB。WebKit/Safari 在 Mac 上已经在这个色彩空间中运行多年,这意味着您将在不同的显示器上获得一致的颜色(截至撰写本文时,大多数其他浏览器引擎仅在所谓的设备色彩空间中运行,这意味着它们在将颜色值传递给显示硬件之前不进行处理)。

WebKit 在 iOS 和 macOS 上都会对所有图像进行色彩匹配。这意味着如果图像包含色彩配置文件,我们将确保图像中的颜色在显示器上得到准确呈现,无论显示器是普通色域还是广色域。这非常有用,因为许多数码相机在其原始格式中不使用 sRGB,因此简单地将红、绿、蓝值解释为 sRGB 很可能无法产生正确的颜色。通常,您无需做任何事情即可获得这种色彩匹配。几乎所有图像处理软件都允许您为图像标记色彩配置文件,并且许多软件默认会这样做。

通过上面链接的示例,您正在 Safari(OS X 10.11.3 及更高版本)以及 iOS 9.3 及更高版本(Retina 设备)上看到这种色彩匹配的实际效果。我所要做的就是确保图像已标记了相应的色彩配置文件。

如果图像没有标记配置文件,WebKit 会假定它是 sRGB。这使得您生成的艺术作品,如边框和背景图像,很容易与您在 CSS 中定义的颜色匹配。也就是说,CSS 值 rgb(255, 0, 0) 将与相应的完整 sRGB 红色值匹配。

注意:这是另一个引发了一些评论的观点,有人建议未标记的图像不应被假定为 sRGB。我们这样做的原因已在上面解释:这是为了确保图像中的颜色与页面中的 CSS 颜色匹配。

这对于过去十年的显示技术来说没有问题。但现在我们有了支持更广色域的显示器,您会希望对内容的显示方式有更多的控制。

检测显示器

我在上面解释了为什么您应该优先向使用广色域显示器的用户提供广色域图像。如果您向非广色域显示器用户提供广色域图像,WebKit 将对图像进行色彩匹配并在 sRGB 空间中显示它们。然而,这种转换为 sRGB 的方式有多种,并且不能保证在其他浏览器或平台上完全相同。作为一位有洞察力的 Web 开发者或设计师,您会希望离线转换您的图像,以便更好地控制最终用户所看到的内容。此外,嵌入色彩配置文件会稍微增加文件大小,因此如果非必要,您可能不希望发送这些额外数据。

最好的解决方案是当用户使用广色域显示器时提供广色域图像,当用户不使用广色域显示器时提供 sRGB 图像。这只是响应式图像的又一个案例,也正是元素和媒体查询被设计用来处理的。

WebKit 现在支持(CSS Color Level 4 新增的)color-gamut 媒体查询。以下是它的使用方法

<picture>
  <source media="(color-gamut: p3)" srcset="photo-wide.jpg">
  <img src="photo-srgb.jpg">
</picture>

您也可以在样式表中使用此查询

.main {
  background-image: url("photo-srgb.jpg");
}

@media (color-gamut: p3) {
  .main {
    background-image: url("photo-wide.jpg");
  }
}

或脚本

if (window.matchMedia("(color-gamut: p3)").matches) {
  // Do especially colorful stuff here.
}

color-gamut 查询接受 p3rec2020 作为值,这些术语有意模糊地指定了系统(包括浏览器引擎和显示硬件)支持的颜色范围。默认情况下,由于几乎所有显示器都支持 sRGB,因此无需测试该功能。但是,典型的现代广色域显示器可以支持 DCI P3 空间或近似范围内的颜色,并会通过媒体查询。例如,我上面提到的 Display P3 空间是 DCI P3 的一个变体。rec2020 值表示系统拥有的显示器支持更广的色域,其范围大致由 Rec. 2020 空间定义(目前,Web 上很少有硬件真正支持 Rec. 2020,所以您可能还不需要为此担心)。

由于媒体查询具有优雅的降级机制,您可以立即开始使用 color-gamut,为广色域用户提供更美观的色彩,同时也能兼顾尚未拥有兼容浏览器或硬件的用户。

未来方向

提供和渲染广色域图像相对简单,但如果您想将其与其他页面元素(如背景颜色)结合,或者将图像绘制到 canvas 元素中呢?这些是标准机构正在努力解决的一些挑战,我想谈谈它们的发展方向。

CSS 中的广色域颜色

我上面展示了 Display P3 中的 rgb(241, 0, 0) 在 sRGB 中对应 rgb(255, 0, 0)。如果您想让 CSS 中定义的颜色与广色域图像中的某个颜色匹配,该怎么办?我们目前还无法在 CSS 中指定这些颜色。

这是 WebKit 项目成员为 CSS 提出的建议。目前的想法是添加一个名为 color() 的新函数,它可以接受色彩配置文件以及定义颜色的参数。

/* NOTE: Proposed syntax. Not yet implemented. */
strong {
  color: color(p3 1.0 0 0); /* 100% red in the P3 color space */
}

实际应用中,您可能会将其与 @supports 规则结合使用。

strong {
  color: rgb(255, 0, 0); /* 100% red in the sRGB color space */
}

@supports (color: color(p3 0 0 0)) {
  strong {
    color: color(p3 1.0 0 0); /* 100% red in the P3 color space */
  }
}
注意:我最初有一个错误的输入,将语法显示为 color(p3, 255, 0, 0)。这是现有 rgb() 函数的烦人之处之一。新的 color() 函数将接受浮点数作为参数,而不是 8 位整数。

CSS 将定义一些已知的色彩配置文件名称,以便您轻松找到所需的颜色值。目前仍在讨论是否允许作者链接到外部配置文件,或者指向具有嵌入式配置文件的图像。

此外,CSS 可能会决定允许您在现有 rgb() 函数中指定超出 0-255(或 0-100%)范围的值。例如,rgb(102.34%, -0.1%, 4%) 将是一种红色更多、绿色更少且略带蓝色的颜色。这里的问题在于,理解这些值可能会令人困惑(负绿色是什么意思?)。

另一个建议是能够为整个文档定义一个色彩空间,这意味着所有常规的 CSS 颜色值都将在该空间中进行解释。带有嵌入式配置文件的外部图像仍将进行色彩匹配。

这些讨论目前正在 W3C CSS 工作组中进行。您的意见非常宝贵——该工作组需要更多来自 Web 开发者的输入。如果您有兴趣参与,请在 www-style 邮件列表上查找主题以 “[css-color]” 开头的电子邮件。

WebKit 希望在确信这些功能稳定后尽快实现它们。

HTML 中的广色域颜色

虽然 CSS 处理了 HTML 文档的大部分呈现,但仍然有一个重要的区域不在其范围之内:canvas 元素。2D 和 WebGL 的 Canvas 都假定它们在 sRGB 色彩空间中操作。这意味着即使在广色域显示器上,您也无法创建能够充分利用所有颜色范围的 Canvas。

提议的解决方案是向 getContext 函数添加一个可选标志,用于指定 Canvas 应匹配的色彩空间。例如

// NOTE: Proposed syntax. Not yet implemented.
canvas.getContext("2d", { colorSpace: "p3" });

还有其他需要考虑的问题,那就是如何创建一个具有更大色彩深度的 Canvas。例如,在 WebGL 中,您可以使用 半浮点 纹理,每个颜色通道提供 16 位的精度。然而,即使您在 WebGL 中使用这些更深的纹理,当您将 WebGL 绘制到文档中时,您仍然受限于 8 位的精度。

需要有一种方法让开发者指定 Canvas 元素的颜色缓冲区深度。

当与 getImageData/putImageData 函数(或 WebGL 中等效的 readPixels)结合使用时,这会变得更加复杂。对于目前每个通道 8 位的缓冲区,数据进出 Canvas 不会损失精度。此外,传输效率也很高,无论是性能还是内存方面,因为 Canvas 和程序端的数据类型相同。但是,当颜色深度可变时,这可能就不行了。例如,WebGL 的半浮点缓冲区在 JavaScript 中没有等效类型,这意味着数据读写时需要进行一些转换,同时需要使用更多内存来存储数据,或者您将不得不使用原始 ArrayBuffer 并进行尴尬的位掩码数学运算。

这些讨论目前正在 WhatWG GitHub 上进行,不久也将在 W3C 上进行。再次强调,我们非常欢迎您参与讨论。

总结

广色域显示器已经到来,它们是计算设备的未来。随着使用这些精美显示器的用户群体不断增长,您将希望利用其提供的惊艳色彩范围,并为用户提供更具吸引力的 Web 体验。

WebKit 非常高兴通过色彩匹配和色域检测为开发者提供改进的色彩功能,这些功能现已在 Safari 技术预览版以及 macOS Sierra 和 iOS 10 测试版中可用。我们还热衷于开始实现更高级的色彩功能,例如在 CSS 中指定广色域颜色、使用配置文件标记 Canvas 元素以及允许更大的色彩深度。

如果您有任何评论、问题、美味的饼干或垃圾邮件,可以通过 dino@apple.com@grorgwork 联系我。您也可以通过 web-evangelist@apple.com@jonathandavis 联系 Jonathan Davis,或将一般性评论发送至 @webkit Twitter 账户。