Technical Article

使用類型 0 取樣函式的 PDF 3D 色彩 LUT

PDF 函式是規格書中較不引人注目的角落之一。大多數開發人員只見過它們一次(作為類型 2 軸向著色在兩個顏色之間淡出所需的東西),就再也沒有看過。這很遺憾,因為函式機制是一個小型通用評估器,該格式將其重複用於著色、轉換函式、網屏特別點函式、特別色色調和虛化遮罩轉換曲線。在四種函式類型中,類型 0 功能最強大,但也最不為人所理解。它是一個取樣函式:讀者在其中進行插值的多維度輸出值網格。因為網格可以保存您放入其中的任何數字,所以類型 0 函式可以表示任意非線性對應,這正是色彩對照表 (color lookup table) 的精確形狀。

本文將介紹 ISO 32000-1 在 §7.10.2 中定義的類型 0 字典,然後展示在檔案管線中最重要的兩個案例:三輸入的 RGB 到 RGB 色彩校正 LUT,以及單輸入的特別色色調轉換。同一個取樣函式建立器同時適用於兩者,它們之間的差異完全在於網格具有多少個輸入。

取樣函式是讀者進行插值的網格

類型 0 函式透過在常規網格上儲存樣本並在它們之間進行插值,將 m 輸入向量對應到 n 輸出向量。ISO 32000-1 §7.10.2 列出了描述該網格的鍵。/Domain 為每個輸入保存兩個數字,即每個輸入軸的下限和上限。/Range 為每個輸出元件保存兩個數字。/Size 是一個包含 m 個整數的陣列,給出沿每個輸入軸的樣本數,因此在三維空間中每邊有 12 個樣本的網格具有 /Size [12 12 12] 並儲存 1,728 個網格點。/BitsPerSample 設定每個儲存值的精確度;HotPDF 接受 1、2、4、8、12、16、24 和 32 位元,與表 38 允許的值相符。

樣本資料流按固定順序讀取。第一個輸入維度變化最快,然後是第二個,依此類推,並且在每個網格點處,n 個輸出元件按順序儲存。對於 RGB 到 RGB 的對照表,這表示在 8 位元下每個網格點為 3 個位元組,佈局為紅色輸出、綠色輸出、藍色輸出,首先掃描紅色輸入。還有兩個鍵將連續的世界對應到整數網格。/Encode 將每個輸入從其 /Domain 區間對應到樣本索引範圍 0Size[i] - 1,而 /Decode 將儲存的原始整數對應回 /Range 區間。當您將它們保留為預設值時,跨越 [0 1] 的輸入會乾淨地落在整個網格上,並且 255 的已儲存位元組會解碼到其輸出範圍的頂部,這正是 [0,1] 標準化色彩 LUT 所需的。

階數 1 與 階數 3

在網格點之間,讀者必須進行插值,而 /Order 選擇如何進行。/Order 1 是多線性插值:沿一個軸為線性,跨兩個軸為雙線性,跨三個軸為三線性。它速度快,正是大多數檢視器中硬體所做的工作,而且對於平滑的色彩轉換,它通常與更花俏的演算法難以區分。/Order 3 要求三次樣條插值,這會在樣本之間擬合出更平滑的曲線,代價是需要更多的工作以及圍繞每個評估點的更寬支援區域。

權衡之處在於網格密度與曲線平滑度。當網格粗糙且對應具有可見的曲率時,三次階數發揮了作用,因為兩個遙遠樣本之間的直線會使色調曲線變平,而肉眼會在漸層上察覺到這一點。一旦網格密集,線段就足夠短,線性插值就能緊密追蹤曲線,三次插值帶來的好處微乎其微。實用的規則是,僅在網格較小或轉換陡峭時才使用 /Order 3,否則保留為線性預設值。請注意,/Order 僅適用於類型 0 函式,且 HotPDF 拒絕除 1 或 3 之外的任何值。

The 3D LUT: three inputs, three outputs

RGB 到 RGB 色彩校正是在色彩分級和裝置比對中使用的經典 3D LUT,是三輸入網格的教科書式案例。立方體的每個軸都是一個輸入通道,每個網格點儲存該輸入座標的已校正 RGB 三元組,且讀者會圍繞任何輸入顏色三線性插值角落樣本。此處三輸入是不可避免的,因為校正後的紅色可能取決於輸入的綠色和藍色,而不僅僅是輸入的紅色;每個通道的曲線無法表示通道的交互干擾,但立方體可以。

HotPDF 透過 RegisterSampledFunction 建立類型 0 資料流,該函式直接接受 /Domain/Range/Size/BitsPerSample 和樣本位元組,並傳回函式物件。對於標準標準化的立方體,您傳遞所有三個輸入軸和所有三個輸出上的 [0,1] 邊界、N x N x N 大小以及扁平化的樣本表。建立器驗證位元組計數是否與網格相符:對於位元組對齊的深度,它預期 OutputCount x (BitsPerSample div 8) x 大小的乘積,且如果陣列長度錯誤則引發異常,因此計算錯誤的間距會在註冊時大聲報錯,而不是稍後呈現為垃圾資料。

const
  N = 17;  // 17 x 17 x 17 cube, the common ICC LUT resolution
var
  LutFn: THPDFStreamObject;
  Samples: TBytes;
begin
  // Fill Samples with N*N*N grid points, 3 bytes each (R,G,B output),
  // red input varying fastest. Build the corrected triple for each
  // grid coordinate with your ICC-managed conversion, then store it.
  SetLength(Samples, N * N * N * 3);
  BuildCorrectedCube(Samples, N);   // your color-managed fill

  LutFn := Pdf.RegisterSampledFunction(
    [0,1, 0,1, 0,1],   // /Domain: three input axes on [0,1]
    [0,1, 0,1, 0,1],   // /Range:  three output channels on [0,1]
    [N, N, N],         // /Size:   the cube resolution per axis
    8,                 // /BitsPerSample
    Samples,
    1);                // /Order 1 = trilinear
end;

立方體的色度正確性存在於您如何填滿它,而不是存在於 PDF 函式中。正確的方法是透過 ICC 管理的轉換來計算每個網格點(驅動軟體打樣的同一個引擎),這樣網格中的數字相對於定義的來源和目標設定檔就有意義。使用 RegisterICCProfile 註冊限制轉換的設定檔,這會記錄基於 ICC 的色彩空間(1、3 或 4 個元件)並傳回一個資源名稱,您可以將該名稱附加到 LUT 提供的內容。類型 0 函式攜帶插值表;ICC 設定檔攜帶端點的意義。

1D 案例:特別色色調轉換

特別色空間依賴相同的機制來執行完全不同的工作。特別色空間(定義於 ISO 32000-1 §8.6.6.4)藉由將名稱與色調轉換配對,來代表單一著色劑(例如 Pantone 或上光油等特別色油墨):該轉換是一個函式,將一維色調值(無油墨為 0,滿油墨為 1)對應到裝置實際上可以轉譯的替代色彩空間(通常為 CMYK)。該色調轉換通常是類型 0 函式,此時網格正好有一個輸入軸。

這與 3D LUT 形成了鮮明的對比。特別色油墨是一個自由度,因此其色調轉換需要一個輸入,且網格是一行樣本,每個樣本包含該色調層級下的 CMYK(或其他替代)值。RGB 立方體需要三個輸入,因為其定義域是三維的,且通道之間會相互作用。相同的函式類型,相同的插值規則,不同的維度;規格書重複使用一個評估器,並讓 /Size 決定您是在走線條、平面還是立方體。HotPDF 將整個特別色包裝在 RegisterSeparationLUT 中,該函式在內部從扁平位元組陣列建立單輸入類型 0 色調轉換,並傳回色彩空間資源名稱。

var
  SpotCS: AnsiString;
begin
  // Four CMYK output bytes per tint grid point, tint domain [0..1].
  // Here 0% ink -> all zero, 100% ink -> a rich spot build,
  // with two interior steps; the tint transform interpolates between.
  SpotCS := Pdf.RegisterSeparationLUT(
    'PANTONE 286 C',         // colorant name
    'DeviceCMYK',            // alternate color space
    [  0,   0,   0,   0,     // tint 0.00 -> 0,0,0,0
      90,  60,   0,   0,     // tint 0.33
     100,  80,   0,  10,     // tint 0.66
     100,  72,   0,  18]);   // tint 1.00 -> full ink build
  // Use SpotCS with SetFillColorSpace / SetFillColor on a page.
end;

樣本計數必須是網格點的整數:替代空間的元件數的正倍數,且至少要有兩個點以便有線段進行插值。在 CMYK 替代空間下傳遞每點三個位元組,該呼叫會拒絕它,這與 3D 建立器套用的防禦性驗證相同,這正是您對於否則在列印時會無聲失敗的函式所期望的行為。

相同的機制在哪裡再次出現

一旦您將類型 0 視為通用的插值表,另外兩個裝置控制功能就不再看起來像特例。轉換函式在元件值前往輸出裝置的途中對其進行調整,這只是每個通道的函式;HotPDF 透過 RegisterTransferFunctionState 將其註冊為 ExtGState,該函式接受一個組合函式或每個通道函式的陣列。因為這些函式是普通的函式物件,所以您可以將 RegisterSampledFunction 傳回的 THPDFStreamObject 傳遞給它,並從取樣表而不是公式來驅動轉換曲線。

var
  ToneFn: THPDFStreamObject;
  GsName: AnsiString;
begin
  // A single-input, single-output sampled tone curve on [0,1].
  ToneFn := Pdf.RegisterSampledFunction(
    [0,1], [0,1], [256], 8, ToneCurveBytes, 1);

  // Apply it to all channels as a combined /TR2 transfer function.
  GsName := Pdf.RegisterTransferFunctionState(ToneFn, []);
  // Select GsName on the page before drawing the affected content.
end;

黑版產生 (black generation) 和底色去除 (undercolor removal) 屬於同一個系列。當裝置將 RGB 轉換為 CMYK 時,它會決定將多少灰色元件作為黑色油墨攜帶,而規格書將該決定表示為一個函式,即圖形狀態字典的 /BG2/UCR2 項目,每個都是從計算出的灰色到黑色數量的單輸入曲線。當您想要一條逆量曲線而不是解析曲線時,這些也是類型 0 函式,以相同的方式透過 RegisterSampledFunction 建立並置於圖形狀態中。值得記住的教訓是,PDF 函式絕不是色彩管理發生的生命線;它是攜帶您使用真實色彩引擎所做決定的對照表,而類型 0 是唯一足夠靈活以攜帶任何決定的函式類型。

如需字型、影像和色彩資源如何發送到完成的檔案中的更廣泛畫面,請參閱我們的字型與影像報表輸出逐步解說。當輸出必須在封存或列印預檢中倖存時,PDF/A、PDF/X 和 PDF/UA 驗證指南中涵蓋的色彩空間和輸出目的規則將控管允許使用哪些此類函式以及如何標記裝置色彩。所有這些都隨附於適用於 Delphi 和 C++Builder 的 HotPDF 元件 中,同時也提供建立在相同類型 0 核心上的著色、ICC 和特別色 API。