首页
/ Electron ColorSpace 对象参考:四维色彩空间描述符及其在共享纹理、离屏渲染中的源码实现

Electron ColorSpace 对象参考:四维色彩空间描述符及其在共享纹理、离屏渲染中的源码实现

2026-09-06 15:36:47作者:秋泉律Samson

本文系统梳理 Electron API 中的 ColorSpace 结构对象:完整覆盖其 primariestransfermatrixrange 四个字段的全部取值、sRGB / Display P3 / HDR10 / HLG 等标准与 HDR 色彩空间定义,并结合 Electron 源码中的 gin 类型转换器、nativeImage.toBitmap()sharedTexture 模块与 Offscreen Rendering(OSR)实现,说明该对象在进程间色彩信息传递中的真实调用链与默认值行为,帮助你在做视频纹理导入、位图导出和离屏渲染时精确控制色彩语义。

ColorSpace 对象的结构

ColorSpace 是 Electron API 文档中的一个结构对象(structure),用于在 API 层描述一个完整的色彩空间。它由四个字符串字段组成,每个字段都是受限枚举值:

字段 含义
primaries 色彩空间的主色(color primaries),定义红/绿/蓝三原色在 CIE 色度图中的位置
transfer 传输函数(transfer function),定义信号值与相对亮度之间的映射关系
matrix 色彩矩阵(color matrix),定义颜色分量到亮度/色度分量的线性变换
range 色彩范围(color range),定义采样值的实际数值区间

这四个维度共同对应 Chromium 中 ui/gfx/color_space.h 提供的 gfx::ColorSpace 类——从源码结构看,Electron 的 ColorSpace 对象本质上是 gfx::ColorSpace 在 V8 值层的序列化形式,由通用类型转换器负责双向映射(见下文 gin 转换器实现)。

primaries 字段取值

primaries string - 色彩空间的主色,可取以下值:

  • bt709 - BT709 primaries(也用于 sRGB)
  • bt470m - BT470M primaries
  • bt470bg - BT470BG primaries
  • smpte170m - SMPTE170M primaries
  • smpte240m - SMPTE240M primaries
  • film - Film primaries
  • bt2020 - BT2020 primaries
  • smptest428-1 - SMPTEST428-1 primaries
  • smptest431-2 - SMPTEST431-2 primaries
  • p3 - P3 primaries
  • xyz-d50 - XYZ D50 primaries
  • adobe-rgb - Adobe RGB primaries
  • apple-generic-rgb - Apple Generic RGB primaries
  • wide-gamut-color-spin - Wide Gamut Color Spin primaries
  • ebu-3213-e - EBU 3213-E primaries
  • custom - 自定义 primaries
  • invalid - 无效的 primaries

transfer 字段取值

transfer string - 色彩空间的传输函数,可取以下值:

  • bt709 - BT709 transfer function
  • bt709-apple - BT709 Apple transfer function
  • gamma18 - Gamma 1.8 transfer function
  • gamma22 - Gamma 2.2 transfer function
  • gamma24 - Gamma 2.4 transfer function
  • gamma28 - Gamma 2.8 transfer function
  • smpte170m - SMPTE170M transfer function
  • smpte240m - SMPTE240M transfer function
  • linear - Linear transfer function
  • log - Log transfer function
  • log-sqrt - Log Square Root transfer function
  • iec61966-2-4 - IEC61966-2-4 transfer function
  • bt1361-ecg - BT1361 ECG transfer function
  • srgb - sRGB transfer function
  • bt2020-10 - BT2020-10 transfer function
  • bt2020-12 - BT2020-12 transfer function
  • pq - PQ(Perceptual Quantizer)transfer function
  • smptest428-1 - SMPTEST428-1 transfer function
  • hlg - HLG(Hybrid Log-Gamma)transfer function
  • srgb-hdr - sRGB HDR transfer function
  • linear-hdr - Linear HDR transfer function
  • custom - 自定义传输函数
  • custom-hdr - 自定义 HDR 传输函数
  • scrgb-linear-80-nits - scRGB Linear 80 nits transfer function
  • invalid - 无效的传输函数

matrix 字段取值

matrix string - 色彩空间的色彩矩阵,可取以下值:

  • rgb - RGB 矩阵
  • bt709 - BT709 矩阵
  • fcc - FCC 矩阵
  • bt470bg - BT470BG 矩阵
  • smpte170m - SMPTE170M 矩阵
  • smpte240m - SMPTE240M 矩阵
  • ycocg - YCoCg 矩阵
  • bt2020-ncl - BT2020 NCL 矩阵
  • ydzdx - YDzDx 矩阵
  • gbr - GBR 矩阵
  • invalid - 无效的矩阵

range 字段取值

range string - 色彩空间的取值范围,可取以下值:

  • limited - 限制范围(RGB 值从 16 到 235)
  • full - 完整范围(RGB 值从 0 到 255)
  • derived - 范围由传输函数和矩阵共同推导定义
  • invalid - 无效范围

常用 ColorSpace 定义

Electron 文档给出了一组可直接复用的标准定义,按用途分为三类。

标准色彩空间

sRGB

const cs = {
  primaries: 'bt709',
  transfer: 'srgb',
  matrix: 'rgb',
  range: 'full'
}

Display P3

const cs = {
  primaries: 'p3',
  transfer: 'srgb',
  matrix: 'rgb',
  range: 'full'
}

XYZ D50

const cs = {
  primaries: 'xyz-d50',
  transfer: 'linear',
  matrix: 'rgb',
  range: 'full'
}

HDR 色彩空间

Extended sRGB(将 sRGB 扩展到所有实数域):

const cs = {
  primaries: 'bt709',
  transfer: 'srgb-hdr',
  matrix: 'rgb',
  range: 'full'
}

scRGB Linear(全实数域线性传输函数):

const cs = {
  primaries: 'bt709',
  transfer: 'linear-hdr',
  matrix: 'rgb',
  range: 'full'
}

scRGB Linear 80 Nits(SDR 白电平为 80 nits):

const cs = {
  primaries: 'bt709',
  transfer: 'scrgb-linear-80-nits',
  matrix: 'rgb',
  range: 'full'
}

HDR10(BT.2020 主色 + PQ 传输函数):

const cs = {
  primaries: 'bt2020',
  transfer: 'pq',
  matrix: 'rgb',
  range: 'full'
}

HLG(BT.2020 主色 + HLG 传输函数):

const cs = {
  primaries: 'bt2020',
  transfer: 'hlg',
  matrix: 'rgb',
  range: 'full'
}

视频色彩空间

Rec. 601(SDTV):

const cs = {
  primaries: 'smpte170m',
  transfer: 'smpte170m',
  matrix: 'smpte170m',
  range: 'limited'
}

Rec. 709(HDTV):

const cs = {
  primaries: 'bt709',
  transfer: 'bt709',
  matrix: 'bt709',
  range: 'limited'
}

JPEG(JPEG 图片的典型色彩空间):

const cs = {
  primaries: 'bt709',
  transfer: 'srgb',
  matrix: 'smpte170m',
  range: 'full'
}

从源码结构看,"主色/传输函数"组合决定色彩域与色调映射语义,"矩阵"决定分量间如何混色,"范围"决定 8-bit 采样值的实际映射区间——例如视频流普遍使用 limited 范围(16–235),而 sRGB 图形内容使用 full 范围(0–255),这也是 Rec. 601/709 定义与 sRGB 定义的关键差异之一。

在 Electron API 中的使用场景

ColorSpace 对象本身不是独立的顶层 API,而是作为若干图形相关 API 的输入/输出参数出现。仓库文档中引用它的接口主要有三处:

nativeImage.toBitmap(options)

native-imagetoBitmap() 方法接受 scaleFactorcolorSpace 两个选项,指定导出位图时使用的色彩空间。源码实现见 electron_api_native_image.cc

v8::Local<v8::Value> NativeImage::ToBitmap(gin::Arguments* args) {
  // ...
  float scale = 1.0f;
  gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
  gin_helper::Dictionary options;
  if (args->GetNext(&options)) {
    options.Get("scaleFactor", &scale);
    options.Get("colorSpace", &color_space);
  }

  const auto src = image_.AsImageSkia().GetRepresentation(scale).GetBitmap();
  const auto dst_info = SkImageInfo::MakeN32Premul(
      src.dimensions(), color_space.ToSkColorSpace());
  // ... readPixels 将像素转换到目标色彩空间后写入 ArrayBuffer
}

要点:

  • 不传 colorSpace 时默认使用 gfx::ColorSpace::CreateSRGB(),即上文的 sRGB 定义;
  • 传入的 ColorSpace 对象经 gin 转换器解析为 gfx::ColorSpace 后,通过 ToSkColorSpace() 交给 Skia 的 readPixels() 完成色彩转换——也就是说,位图导出时会真实发生色彩空间变换,而不是仅仅携带元数据。

sharedTexture.importSharedTexture(options)

shared-texture 模块(实验性 API)支持把平台相关的共享纹理句柄导入为 VideoFrame。其参数结构 SharedTextureImportTextureInfo 中的 colorSpace 字段为可选,用于描述纹理的色彩空间,与 pixelFormatbgra / rgba / rgbaf16 / nv12 / nv16 / p010le)配合使用——对 10-bit YUV 这类 HDR 格式,colorSpace(如 HDR10 的 bt2020 + pq)是解码器正确还原色彩所必需的元数据。

源码见 electron_api_shared_texture.cc

// The color space of the video frame.
gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();

即缺省回落到 sRGB;解析处(L640)通过 dict.Get("colorSpace", &out->color_space) 直接复用下文要介绍的 Converter<gfx::ColorSpace>::FromV8。解析后的色彩空间随后被写入 VideoFrameL259raw_frame->set_color_space(...))并用于创建 SharedImageL771-L800),保证纹理在 WebGPU/渲染管线中的色彩语义与源帧一致。

Offscreen Rendering 的 OffscreenSharedTexture

开启 offscreen: true 时,web-contents'render-process-gone' 之外还有离屏纹理输出通道:OffscreenSharedTexturetextureInfo 中包含 colorSpace 字段,描述当前视频帧的色彩空间。该字段由 OSR 层填充:osr_paint_event.h 中携带 gfx::ColorSpace color_space,经 osr_converter.ccdict.Set("colorSpace", val.color_space) 序列化为 ColorSpace 对象交给 JS 侧。

源码实现:JS 字符串如何映射为 gfx::ColorSpace

ColorSpace 对象与 Chromium 类型之间的双向转换集中在 gfx_converter.cc,这是理解该结构行为的关键:

序列化方向(C++ → JS):ToV8

Converter<gfx::ColorSpace>::ToV8L237-L439)通过四组 switch 语句分别把 GetPrimaryID()GetTransferID()GetMatrixID()GetRangeID() 枚举映射为文档所列的字符串字面量(如 PrimaryID::BT709 -> "bt709"TransferID::PQ -> "pq"RangeID::LIMITED -> "limited"),最终生成含 primaries / transfer / matrix / range 四个键的 JS 字典。文档中列出的每一个取值都能在此处找到对应的枚举分支。

反序列化方向(JS → C++):FromV8 的默认值与边界行为

Converter<gfx::ColorSpace>::FromV8L441-L594)有三个值得注意的实现事实:

  1. 默认值与 sRGB 一致。任何字段缺省时均回落到:

    // Default values if not specified
    gfx::ColorSpace::PrimaryID primaries = gfx::ColorSpace::PrimaryID::BT709;
    gfx::ColorSpace::TransferID transfer = gfx::ColorSpace::TransferID::SRGB;
    gfx::ColorSpace::MatrixID matrix = gfx::ColorSpace::MatrixID::RGB;
    gfx::ColorSpace::RangeID range = gfx::ColorSpace::RangeID::FULL;
    

    因此一个空对象 {} 等价于文档中的 sRGB 定义。

  2. custom 取值不支持反序列化。虽然 ToV8 能输出 custom(primaries)与 custom / custom-hdr(transfer),但 FromV8 在遇到这些字符串时会抛出 TypeError"'custom' not supported." / "'custom', 'custom-hdr' not supported."L457-L462L500-L504)。也就是说,自定义色彩空间只能作为输出元数据被读取,不能作为 API 输入构造。

  3. 未知字符串落到 invalid。未被识别的值(而非 custom)不会抛错,而是映射到 INVALID 枚举,最终构造出无效的 gfx::ColorSpaceL592*out = gfx::ColorSpace(primaries, transfer, matrix, range))。使用时应以文档列出的枚举为准。

实践建议

  • 图形内容默认 sRGBnativeImage.toBitmap() 不传 colorSpace 即为 sRGB;如需导出到宽色域工作流(如 P3 校色),传入 { primaries: 'p3', transfer: 'srgb', matrix: 'rgb', range: 'full' } 即可让 Skia 在导出时完成转换。
  • HDR 纹理导入务必显式指定:使用 sharedTexture.importSharedTexture() 导入 p010le(BT.2020 10-bit YUV)等 HDR 格式时,colorSpace 应显式给出 HDR10(bt2020 + pq)或 HLG(bt2020 + hlg)定义,否则按 sRGB 处理会导致色调与色域错误;SDR 视频则可用 Rec. 709 limited 定义。
  • 区分 limitedfull:广播电视素材(Rec. 601/709)使用 limited(16–235),桌面图形内容使用 full(0–255),混用会造成对比度与黑场偏差。
  • 注意 API 成熟度sharedTexture 模块在文档中明确标注为 Experimental(可能在未来版本移除或变更),其 colorSpace 相关用法适用前提是该模块在当前 Electron 版本可用;相关行为可通过 api-shared-texture-spec.tsapi-native-image-spec.ts 等测试文件在仓库中进一步验证。

参考文档与源码索引

登录后查看全文
热门项目推荐
相关项目推荐