PDFium Delphi Component Docs

文档 ICC 颜色转换

ConvertPdfDocumentColours 读取 PDF 当前有效修订,通过 IPdfColourTransform 转换原始分量操作数和图像采样,并向独立输出流追加一致的新修订

支持 DeviceGray、DeviceRGB、DeviceCMYK 和 ICCBased 空间中的文本及矢量填充/描边操作符、继承的页面资源、命名默认色彩空间别名、嵌套 Form XObjects,以及使用 8-bit 或 16-bit 分量的原始或通用过滤器图像

内容数组共用一个操作数解析器和图形状态栈,流之间插入空格;整个转换过程中,q/Q、默认色彩空间和分量数始终关联原始源空间

CMYK 操作数直接来自 PDF 内容和图像流,不使用渲染后的 RGB getter;没有配置文件的 DeviceCMYK 源须提供 DeviceCMYKProfile

源 ICCBased 配置文件从原始资源作用域解析;仅支持缺省或默认的 /Range [0 1 ...],图像 /Decode 数组则在转换前应用,并从转换后的图像中移除

16-bit 图像采样保留 PDF 大端字节序;分配采样缓冲区前会验证精确字节几何和目标数据扩展量,不会凭空添加步长或填充字节

PreserveAllSpotColours 默认为 true;否则需在 PreservedSpotColours 中填入解码后的 PDF 着色剂名称,只有所有列出的着色剂都被选中时,Separation 或 DeviceN 空间才会保留

保留的专色操作符、色调函数和资源保持原样;未选中的专色需要专用转换后端,否则报告为不支持

图像模板遮罩和被引用的遮罩数据保持原样;颜色键遮罩、显式遮罩及软遮罩底色分量需要另行制定策略

不支持的范围包括缺少原始分量解码器的 DCT/JPX 图像、1/2/4-bit 图像及其行填充、非默认 ICC 范围、Indexed/Cal/Lab/Pattern 空间、内联图像、渐变函数、Type3 字形程序、注解字典颜色、表单默认外观指令、XFA 颜色内容、透明组、非 normal 混合、叠印,以及图形传递函数或渲染意图

自带资源的 Form 须在裸 sc/scn 操作数前建立色彩空间;共享 Form 或图像若继承到不同的源上下文,会报告为不支持,缓存的失败也会传播到每个调用作用域

FailOnUnsupported 默认为 true,失败时保留目标;设为 false 可独立应用受支持的更新,同时将 Complete 设为 false,部分转换绝不会写入新的 OutputIntent

部分结果可能保留源文件已有的 OutputIntent;OutputIntentWritten 专门表示本次操作是否安装了新的目标声明

完整结果会嵌入传入的目标 ICC 配置文件,并按指定标识写入 OutputIntent;这不代表通过 PDF/X、PDF/A 或其他一致性认证

源流与目标流必须不同;操作会恢复源流位置,准备阶段失败不会修改目标,取消操作保留 EPdfOperationCancelled

发布准备好的结果时通过目标流 API 替换内容;截断或写入异常可能留下部分输出,需要文件原子发布的调用方应先写临时文件,成功后再重命名

加密和已有签名要求先另行准备未加密、未签名的源文档;增量颜色转换不会保留签名有效性

除有效对象读取器预算外,默认还允许每个解码内容/图像流 64 MiB、输出暂存 512 MiB、10,000 条问题报告和深度 64

累积每次更新前,输出预算会保守计入源字节、暂存替换对象和预留的 xref/trailer 开销;序列化前计入完整 trailer 长度,受限输出流会在扩大逻辑大小前拒绝超预算写入

该预算限制的是逻辑输出暂存,不是进程全部内存或分配器向上取整的容量;发布前还会再次检查最终序列化大小

实际 RGB、CMYK 和 ICCBased 图像转换、文本/矢量转换、嵌套 Form、Separation 和 DeviceN 保留、OutputIntent、压缩对象流及 PDF 保存/重新打开/渲染,均已在 Delphi 和 FPC 的 Win32、Win64 目标上验证

示例

ProviderOptions := TPdfLittleCmsOptions.Default;
Provider := CreatePdfLittleCmsColourTransform(LibraryPath, ProviderOptions);
Options := TPdfDocumentColourOptions.Default;
Options.DeviceCMYKProfile := SourceCmykProfile;
TargetProfile := CreatePdfLittleCmsGrayProfile(LibraryPath);
if not ConvertPdfDocumentColours(Source, Destination, pcsDeviceGray,
  TargetProfile, Provider, Options, Report, CancellationToken) then
  raise Exception.Create(Report.ErrorText);

公开声明

type
  TPdfSpotColourNames = array of AnsiString;
  TPdfDocumentColourOptions = record
    ReadOptions: TPdfActiveObjectReadOptions;
    MaxDecodedStreamBytes: Integer;
    MaxOutputBytes: Int64;
    MaxIssues: Integer;
    MaxDepth: Integer;
    FailOnUnsupported: Boolean;
    PreserveAllSpotColours: Boolean;
    PreservedSpotColours: TPdfSpotColourNames;
    DeviceGrayProfile, DeviceRGBProfile, DeviceCMYKProfile: TBytes;
    OutputIntentIdentifier: string;
    class function Default: TPdfDocumentColourOptions; static;
  end;
  TPdfDocumentColourIssue = record
    ObjectNumber: Integer;
    Reason: string;
  end;
  TPdfDocumentColourIssues = array of TPdfDocumentColourIssue;
  TPdfDocumentColourReport = record
    Succeeded: Boolean;
    Complete: Boolean;
    ContentStreamsConverted, FormsConverted, ImagesConverted: Integer;
    ColourOperatorsConverted, PreservedSpotSelections, PreservedMasks: Integer;
    UnsupportedCount: Integer;
    OutputIntentWritten: Boolean;
    Issues: TPdfDocumentColourIssues;
    ErrorText: string;
  end;

function ConvertPdfDocumentColours(Source, Destination: TStream;
  TargetSpace: TPdfColourSpace; const TargetProfile: TBytes;
  Transform: IPdfColourTransform; const Options: TPdfDocumentColourOptions;
  out Report: TPdfDocumentColourReport;
  CancellationToken: IPdfCancellationToken = nil): Boolean;