PDF 色彩保真工程实践【2】:用底层 PDF Object API 精准控制 PDF 色彩空间
本文是系列文章的第 2 篇。上一篇《PDF 色彩保真工程实践【1】聊聊 CMYK 色彩损失为什么你的 PDF 图片“变色”了》我们讲清了“为什么要在 PDF 中原样保留 CMYK”。这一篇我们把一张“PDF 里的图像”彻底拆开看清它由哪些对象构成并说明我们的技术选型。本项目完整源码https://github.com/AmyLin2013/pdf-cmyk-image本篇你将学到一张 PDF 图像Image XObject到底由哪些键值组成/ColorSpace [/ICCBased ...]是什么它如何承载 CMYK ICC为什么我们选择“底层对象 API”而刻意绕开高层图片接口整体技术选型libtiff 解码 zlib 压缩 福昕 PDF Object API 组装。一张“PDF 里的图像”长什么样在 PDF 里一张位图图像是一个Image XObject——本质是一个带字典的流对象。它的关键键值大致如下 /Type /XObject /Subtype /Image /Width 像素宽 /Height 像素高 /ColorSpace 色彩空间 /BitsPerComponent 8 /Filter /FlateDecode % 图像数据用什么方式压缩 /Length 压缩后字节数 stream ...(压缩后的图像采样数据)... endstream其中最关键的就是/ColorSpace。它决定了“流里那一串字节应该被当作什么颜色来解释”。如果是/DeviceRGB每像素 3 通道按 RGB 解释如果是/DeviceCMYK每像素 4 通道按 CMYK 解释如果是[/ICCBased ...]则按内嵌的 ICC 特性文件来精确解释颜色。要“无损保留 CMYK”我们要做的就是让/ColorSpace保持 CMYK且带上原始 ICC同时让流里的字节就是源图的 CMYK 采样值。/ColorSpace [/ICCBased ...]把 ICC 装进 PDFICCBased色彩空间是一个数组第二个元素指向一个ICC 流对象/ColorSpace [ /ICCBased 10 0 R ] % 10 0 R 指向下面这个 ICC 流而那个 ICC 流对象长这样 /N 4 % 4 个颜色分量 CMYK /Alternate /DeviceCMYK % 无法用 ICC 时的回退色彩空间 /Filter /FlateDecode /Length 压缩后字节数 stream ...(压缩后的原始 ICC Profile 字节)... endstream/N 4表示 4 分量正好对应 CMYK/Alternate /DeviceCMYK是回退方案流内容就是源 TIFF 里那份 ICC Profile 的原始字节——我们要做到逐字节保留。 这就是“无损”的两个技术支点ICCBased 的 ICC 流字节 源 ICCImage 流字节 源 CMYK 采样。后续第 6 篇会用 SHA-256 来证明这两点。为什么刻意不用“高层图片接口”很多 SDK包括福昕都提供“往页面上加一张图”的高层便捷接口。它们很好用但为了通用性内部常常会把图像归一化成 RGB/RGBA 位图再处理。这恰恰是色彩损失的根源。所以我们的选择是只用底层 PDF Object API自己动手构造 ICC 流、ICCBased 色彩空间、Image XObject并把它们挂接到页面。这样每一个字节都在我们的掌控之中不给隐式转换任何机会。这也是本系列想传达的一个观点当你需要确定性时底层对象 API 提供的“精确控制”比“便捷但黑盒”的高层接口更可靠。福昕 PDF SDK 的底层对象接口正好提供了这种控制力。技术选型全景于是整套方案就清晰了三块拼图各司其职环节选型作用解码 CMYK TIFFlibtiff仅 scanline API取出原始 CMYK 采样与内嵌 ICC绝不走 RGB 路径压缩流数据zlibFlate把 ICC 与图像数据压成 PDF 的FlateDecode流组装 PDF 对象福昕 PDF Object API构造 ICC 流、ICCBased、Image XObject 并挂接页面用一张图表示对象之间的关系ICC 流 ◄──[/ICCBased ...]── ColorSpace 数组 ▲ ▲ │ │ └───────────── Image XObject ───┘ ▲ │ /XObject /ImCMYKn 页面 /Resources ▲ │ q cm /ImCMYKn Do Q 页面 /Contents内容流小结PDF 图像是一个带/ColorSpace的流对象色彩空间决定字节如何被解释[/ICCBased ...]让我们把 CMYK 与原始 ICC 一并、精确地写入 PDF为避免隐式 RGB 转换我们只用底层对象 API 手工组装选型libtiff 解码 zlib 压缩 福昕对象 API 组装。上一篇《PDF 色彩保真工程实践【1】聊聊 CMYK 色彩损失为什么你的 PDF 图片“变色”了》下一篇预告第 3 篇《PDF 色彩保真工程实践【3】上手实践工程结构、依赖集成与一键构建运行》我们会把工程 clone 下来装好 libtiff/zlib 和福昕 SDK告诉你怎么跑起来一条命令构建并跑出满屏的 PASS。关于本系列完整源码https://github.com/AmyLin2013/pdf-cmyk-image关于福昕 PDF SDK开发者站点 支持 Windows/Linux/Mac多语言绑定可以免费申请试用本系列文章专栏PDF 色彩保真工程实践