Skip to content

device-cmyk() の DeviceCMYK 変換: CSS パターン別の調査結果 #774

@munepi

Description

@munepi

概要

まずは、本件の概要は、Vivliostyle CLI の CMYK 変換パイプライン(device-cmyk()color(srgb) → Chromium PDF → 後処理で rg/RGk/K)について、CSS パターン別に変換の成否を調査いたしました。

CSS device-cmyk() to /DeviceCMYK conversion works correctly for most patterns (text, background, border, shadow, outline, opacity), but CSS gradients (linear-gradient, radial-gradient) remain as /DeviceRGB in Shading objects. This is a structural limitation of Chromium's PDF backend (Skia), not a bug in Vivliostyle's post-processing.

調査環境

  • vivliostyle-cli 10.3.1(ローカルビルド)
  • Chromium 146.0.7680.153
  • 検証方法: qpdf --qdf で PDF をQDF形式に変換し、content stream 内のカラーオペレータを確認いたしました。

再現例:テスト HTMLとビルドされたPDF

vivliostyle.config.js

export default {
  entry: 'cmyk-conversion-audit.html',
  output: [
    {
      path: 'cmyk-conversion-audit.pdf',
      pdfPostprocess: {
        cmyk: {
          warnUnmapped: true,
        },
      },
    },
  ],
};

結果

変換成功(DeviceCMYK に変換された)

# CSS パターン PDF 内のオペレータ
1 color: device-cmyk(1 0 0 0) 1 0 0 0 k
2 background-color: device-cmyk(0 1 0 0) 0 1 0 0 k
3 border: 3px solid device-cmyk(0 0 1 0) 0 0 1 0 k
5 text-shadow: 2px 2px 4px device-cmyk(1 0 0 0)
6 box-shadow: 4px 4px 8px device-cmyk(0 0 0 0.5) 0 0 0 0.5 k
7 color: device-cmyk(1 0 0 0); opacity: 0.5 1 0 0 0 k + ExtGState ✓
8 outline: 3px solid device-cmyk(0 0.8 0.8 0) 0 0.8 0.8 0 k
9 複数背景

変換漏れ(DeviceRGB のまま残った)

# CSS パターン PDF 内の状態 原因
4 linear-gradient(device-cmyk(...), device-cmyk(...)) Shading オブジェクト /ColorSpace /DeviceRGB Chromium が Shading dict に RGB を凍結
10 radial-gradient(device-cmyk(...), device-cmyk(...)) 同上 同上

原因の分析

gradient の変換漏れ:Chromium (Skia) の構造的制約

Chromium の PDF バックエンド(Skia)は、CSS gradient を PDF の Shading オブジェクトとして出力します。
Shading オブジェクトでは、色情報が PDF ストリームではなく、辞書内の関数オブジェクトに凍結されます。

%% Shading object (from qpdf --qdf output)
/Shading <<
  /ColorSpace /DeviceRGB    ← ここが問題!!!!!
  /Coords [ 0 0 5140 0 ]
  /Function <<
    /C0 [ 0 1 1 ]           ← RGB に変換済み(元は device-cmyk(1 0 0 0) = Cyan)
    /C1 [ 1 0 1 ]           ← RGB に変換済み(元は device-cmyk(0 1 0 0) = Magenta)
    /Domain [ 0 1 ]
    /FunctionType 2
    /N 1
  >>
  /ShadingType 2
>>

現在の Vivliostyle CLI の後処理は、content stream の rg/RG オペレータを k/K に書き換える方式のため、Shading オブジェクト内部の色には到達できません。

これは、最近、わたし自身がLaTeXパッケージとして開発いたしました spotxcolor パッケージ で指摘している「Shading は色が PDF オブジェクトに凍結されるため、content stream レベルでのインターセプトが不可能」という問題と、基本的に同型です(に見えます)。

対応案

現状、対応する方法を考えていますが、

  • Shading オブジェクト内の /ColorSpace /DeviceRGB/DeviceCMYK の変換と、
  • Function オブジェクト内の RGB → CMYK 値の書き換えを

後処理に追加することで、本件を対応可能だと考えています。
ちょっと、こちらで修正を考えてみたいと思います。

具体的には、

  1. PDF 内の Shading オブジェクトを走査し、/ColorSpace /DeviceRGB を検出
  2. Function 内の /C0, /C1 等の RGB 値を CmykMap で CMYK に変換
  3. /ColorSpace/DeviceCMYK に書き換え

ただし、gradient の中間色(ブラウザが RGB 空間で補間した値)は、CmykMap に登録されていないため、
RGB → CMYK の直接変換式が必要になりそうと思っています。
この点について、設計上の検討が必要そうです。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions