技術文章

在 Delphi 中將 PDF 轉換為單一色彩空間

RecolorDocument 把整份 PDF 移到單一色彩空間,而 RecolorPage 針對單一頁面做同樣的事。兩者都接受 1 代表灰階、2 代表 RGB、3 代表 CMYK,並回傳有多少個色彩被轉換。幾何形狀、文字與圖片留在原處不動;變動的只有色彩

這是你把作品送往一台只接受單一空間的印刷機之前會想做的一次操作,或是一份彩色文件必須在不重新產生的情況下變成灰階文件時。另一種做法——用目標空間從來源資料重建文件——只有在你仍然握有來源資料時才行得通,而對任何從外部收到的東西,你並不握有

哪些東西會被轉換,順序為何

先轉換色彩運算子:頁面在繪製時設定的填色與筆畫。已經在目標空間裡的色彩會被原樣留下,所以一個色彩無需變動的頁面,會保留它的原始位元組,而不會被改寫成相同的值。在大文件上,這個性質比聽起來更重要,因為沒被動到的物件在檔案裡就保持沒被動到

接著是圖片,而這正是過去缺漏的部分。一份只轉換了運算子就變灰階的文件,會在灰階頁面上繼續顯示彩色圖片,這比任何一種極端做法都糟。一張圖片在帶有每元件八位元、裝置色彩空間、且沒有壓縮或只採用單純 Flate 壓縮時,會被轉換

索引式圖片透過它們的色彩表轉換:色盤被轉換,而每一個取樣保留它已經持有的索引。這涵蓋了截圖或圖表通常儲存成的色盤圖片,而且無論取樣是用什麼方式打包或壓縮都能轉換,因為取樣本身從不改變

var
  Lib: TPDFlib;
  Converted: Integer;
begin
  Lib := TPDFlib.Create;
  try
    Lib.LoadFromFile('brochure.pdf', '');
    Converted := Lib.RecolorDocument(1);       // 1 grey, 2 RGB, 3 CMYK
    Log(Format('%d colours converted', [Converted]));
    Lib.SaveToFile('brochure-grey.pdf');
  finally
    Lib.Free;
  end;
end;

為什麼 JPEG 會被原樣留下?

因為轉換它的色彩意味著要重新編碼它,而重新編碼是另一種操作,會帶來不同的後果。JPEG 或傳真圖片保留自己的位元組:解碼、轉換再重新壓縮,會改變圖片資料本身、引入第二代的失真雜訊,並以呼叫端並未要求的方式改變檔案大小

柔遮罩與鏤空遮罩被原樣留下,則是另一個原因。兩者都被當作覆蓋率讀取,而非當作色彩讀取,轉換其中一個會讓頁面把遮罩當成一張圖片顯示——把一個透明遮罩,渲染成本來應該塑造的內容上方的一塊灰階美工圖。讓它們保持原樣不是要繞過的限制;它是正確的結果

透過 ICCBased、Separation、Indexed 或 Pattern 空間設定的色彩,在運算子層級也保持原樣。在不讀取設定檔的情況下轉換它們,會改變頁面看起來的樣子、而非保存它,而一道整個承諾就是「保存」的重新上色程序,不能憑空猜測設定檔

漸層連同它背後的停駐點一起轉換

一個漸層是一個色彩空間加上一個在其中產生色彩的函式,把其中一者轉換而不轉換另一者,會產生無意義的結果——一個被轉換了卻留下停駐點的漸層,會被讀成把某個色頻誤認為某個灰階等級,而在頁面上看起來就是一道顏色完全錯誤的色帶。漸層的色彩空間與它背後的停駐點會一起移動

無論漸層住在哪裡都會被找到:擁有自己的物件、寫在繪製它們的花紋裡,或落在頁面的著色資源中。這份涵蓋範圍很重要,因為設計工具散布它們的方式各不相同,而一個只處理單一配置的轉換器,會讓文件被轉換一半,失敗之間還找不到明顯的規律

有兩種刻意保持原樣。由取樣函式或 PostScript 函式建構的漸層保留自己的定義,網格類型也是如此,因為它們把色彩裝在串流裡而不是函式裡。改寫這兩者與轉換一個色彩是不同的操作,若在一次重新上色程序裡悄悄進行,會令人措手不及

// Convert a single page - useful when only the cover needs to change
Lib.SelectPage(1);
Lib.RecolorPage(3);          // this page to CMYK
Lib.SaveToFile('cover-cmyk.pdf');

重新上色在送印前的哪個位置最合適

把它當作一個正規化步驟,而不是色彩管理。重新上色是在裝置空間之間轉換數值;它不會套用 ICC 設定檔、不會遵守演算用途、也不會模擬印刷狀況。對於必須對上合約打樣的稿件,答案是由設定檔驅動的工作流程,而重新上色頂多是那道先把所有東西放進同一個空間的步驟

它真正派上用場的地方,是普通的生產問題:一份必須是灰階、卻帶著一個 RGB 標誌送來的稿件、一份絕不能以彩色列印的內部文件、一批必須先變成同一個空間、預檢步驟才肯收的檔案。為它搭配一道檢查——PDF/A 與 PDF/UA 預檢以及合規與簽章工作台的筆記,涵蓋了如何把判定當成同一項工作的一部分來執行

如果文件還需要被檢視向量美工圖、而不是被轉換,向量圖形、著色器與漸層的逐步解說涵蓋了這些物件一開始是如何建構的,這對於理解一次重新上色程序能及於何處、不能及於何處,是有用的脈絡

PDFlibPas 是一套原生 Pascal PDF 函式庫,支援 Delphi、C++Builder 與 Lazarus,沒有外部執行階段,所以一道色彩正規化步驟會在你自己的服務內執行,而不需要外部呼叫一個轉換器——完整的文件處理 API 請見 PDFlibPas 產品頁