HotPDF, HPDFResolveColorSpace aracılığıyla renk alanını çözümleyerek, ton dönüştürme işlevini HPDFEvalTintTransform ile değerlendirerek ve sonucu alternatif alan üzerinden ekran için RGB'ye dönüştürerek yüklü PDF sayfalarında Ayrım (Separation) ve DeviceN spot renklerini işler. Sürüm 2.375.0'dan bu yana bu süreç hattı, Type 4 PostScript hesaplayıcıları da dahil olmak üzere dört PDF işlev türünün tümünü değerlendirir, böylece Pantone mürekkepleri içeren basıma hazır bir dosya, geçici bir yer tutucu yerine gerçek renklerini görüntüler. Bu makale, süreç hattının nasıl çalıştığını ve aynı derecede faydalı olarak, onu oluştururken nasıl başarısız olduğunu adım adım incelemektedir
Tetikleyici durum her zaman aynıdır. Bir müşteri bir matbaadan PDF alır: Başlık adlandırılmış bir spot mürekkeple ayarlanmıştır, ambalaj resmi iki mürekkepli bir DeviceN karışımı kullanır ve gövde metni düz siyahtır. Acrobat'ta mükemmel görünür. Delphi uygulamanızda başlık siyah olarak işlenir veya daha kötüsü hiç işlenmez ve müşteri dosya yerine yazılımınız hakkında hata bildirimi yapar. Dosya gayet iyidir. İşleyici sadece dosyanın kullandığı renk alanlarını konuşamıyordur
Spot renkler bir PDF görüntüleyicide neden siyah olarak işlenir?
Spot renkler, işleyici yalnızca cihaz renk operatörlerini (rg, g, k) uyguladığında ve genel operatörleri yok saydığında siyah olarak işlenir veya kaybolur. ISO 32000-1 §8.6 üç renk alanı grubu tanımlar: Cihaz alanları (DeviceGray, DeviceRGB, DeviceCMYK), CIE tabanlı alanlar (CalGray, CalRGB, Lab, ICCBased) ve özel alanlar (Indexed, Separation, DeviceN, Pattern). Cihaz grubunun dışındaki her şey genel operatörlerle seçilir: cs ve CS, sayfa kaynak sözlüğünden adıyla bir alan seçer, ardından sc, SC, scn ve SCN bileşen değerlerini sağlar. Bu operatörleri atlayan bir işleyici, en son ayarlanan renk her neyse onu korur; bu da spot renkli başlığıyla başlayan bir sayfa için ilk DeviceGray siyahıdır
HotPDF, v2.333.0 sürümünde sayfa işleyicisine genel operatör setini ve birleşik bir çözümleme yolunu ekledi: İster çıplak bir ad, ister satır içi bir dizi veya dolaylı bir referans olsun, her /ColorSpace kaynak girişi tek bir THPDFColorSpace kaydında ayrıştırılır ve her dolgu veya vuruş rengi isteği tek bir HPDFResolveColor çağrısından geçer. Aile numaralandırması kapsamı bir bakışta gösterir
type
THPDFColorSpaceFamily = (csfDeviceGray, csfDeviceRGB, csfDeviceCMYK,
csfIndexed, csfCalGray, csfCalRGB, csfLab,
csfICCBased, csfSeparation, csfDeviceN,
csfUnsupported);
function HPDFResolveColorSpace(Obj: THPDFObject): THPDFColorSpace;
function HPDFResolveColor(const CS: THPDFColorSpace;
const Comps: THPDFColorComps; CompCount: Integer): THPDFRenderColor;
Bir tasarım kararı kendini defalarca kanıtlar: csfUnsupported bir hata değil, birinci sınıf bir ailedir. İşleyicinin yorumlayamadığı bir alan, sayfayı iptal etmek yerine tanımlanmış bir yedeğe (fallback) düşer; bu, ana akım görüntüleyicilerin davranışıyla eşleşir ve tek bir egzotik dolgunun, aksi takdirde işlenebilir olan bir belgeyi karartmasını önler
Ton dönüşümü (tint transform) bir mürekkep değerini nasıl gerçek bir renge dönüştürür?
Bir Ayrım (Separation) alanı üç parça bilgi taşır: Mürekkep adı, alternatif bir renk alanı ve ton dönüştürme işlevi. [/Separation /PANTONE485 /DeviceCMYK f] dizisi şunu söyler: İçerik akışı 0.8 scn yazdığında, 0.8 ton değerini f işlevine besleyin ve ortaya çıkan CMYK dörtlüsünü boyayın. DeviceN bunu N-girişli bir işlevle N adet mürekkebe genelleştirir. Mürekkep adının kendisi ekranda yalnızca tavsiye niteliğindedir; ton dönüşümü tüm işleme semantiğidir, bu nedenle alanı ayrıştıran ancak işlevi atlayan bir işleyici henüz yararlı bir şey yapmamıştır
HPDFEvalTintTransform bu adımın arkasındaki işlev motorudur. Sürüm v2.334.0'da eklenen bu motor; Type 2 üstel işlevleri (Alan ve Aralık sınırlamalı C0 + x^N * (C1 - C0)), Type 3 dikiş (stitching) işlevlerini (Kodlama yeniden eşlemesi ile Sınır seçimli alt işlev özyinelemesi) ve 8, 16 ve 32 bit örnekli Type 0 örneklenmiş işlevleri değerlendirir. Type 0, Type 0 renk LUT'ları oluşturma hakkındaki makalede yazma tarafında ele aldığımız arama tablosu mekanizmasının aynısıdır; işleme tarafı, çözülmüş örnek baytlarından bileşen değerlerine doğru aynı yapıyı tersine yürütür
Type 4 PostScript hesaplayıcı işlevleri son kaleydi. Sürüm v2.375.0'a kadar düzgün bir şekilde nötr bir yer tutucuya düşüyorlardı; v2.375.0'dan bu yana HPDFEvalPostScriptCalculator, sınırlı bir işlenen yığınında tam ISO 32000-1 §7.10.5 operatör setini yürütür: Aritmetik, karşılaştırma, mantıksal ve bit düzeyinde operatörler, roll dahil yığın manipülasyonu ve if/ifelse koşulları. Köşe semantikleri göründüğünden daha katıdır. PostScript round işlevi yarıyı daha büyük değere doğru yuvarlar, bu nedenle Delphi'nin bankacı yuvarlaması yapan Round işlevi kullanılamaz; trigonometrik operatörler derece cinsinden çalışır, atan [0, 360) aralığında değerler döndürür; ve exp, doğal üstel değil, iki işlenenli bir kuvvettir. Aynı değerlendirici, işlev tabanlı gradyan dolgularını da yönlendirir, bu nedenle eksenel ve radyal gölgeleme işlemleri aynı sürümde hesaplayıcı yönetimli rampaları almıştır
// Bir Ayrım/DeviceN ton dönüşümünü değerlendirin (Type 0/2/3/4).
function HPDFEvalTintTransform(FuncObj: THPDFObject;
const Inputs: THPDFColorComps; InputCount: Integer;
out AltComps: THPDFColorComps): Boolean;
// Type 4 PostScript hesap makinesi, ISO 32000-1 7.10.5 operatör seti.
function HPDFEvalPostScriptCalculator(const Prog: TBytes;
const Inputs: THPDFColorComps; InputCount: Integer;
var Outputs: THPDFColorComps; OutCount: Integer): Boolean;
Hassasiyet konusunda dürüstlük: Çift duyarlıkta (double precision) değerlendirilen bir yazılım hesaplayıcısı, bir RIP ile bit bit eşleşmeyecektir ve Aralık (Range) sınırındaki sınırlama, başka bir uygulamadan en önemsiz bit kadar farklılık gösterebilir. Ekran görüntüsü ve regresyon işlemleri için bunun önemi yoktur; renk yönetimi olan prova baskısı oluşturuyorsanız, ton dönüşümü yalnızca ilk aşamadır ve aşağı akışta gerçek bir CMM'e ihtiyacınız vardır
ICC motoru olmadan CalGray, CalRGB, Lab ve ICCBased
CIE tabanlı aileler, aynı çözümleyicinin diğer dalını alır. HotPDF, ters transfer işlevindeki 6/29 kırılma noktası küpü de dahil olmak üzere, Lab değerlerini standart Lab - XYZ - sRGB zinciri aracılığıyla dönüştürür; kanal başına gaması artı 3x3 doğrusal matrisi ile CalRGB'yi ve tek gaması ile CalGray'i işler. Performansla ilgili ayrıntı beyaz nokta yönetimidir: XYZ - sRGB dönüşüm matrisi, renk alanında beyan edilen beyaz noktaya Bradford uyarlamalıdır ve çözümlenmiş THPDFColorSpace kaydında önbelleğe alınır, böylece piksel başına yapılan iş, beyan edilen ışık kaynağı ne kadar egzotik olursa olsun tek bir 3x3 çarpımı olarak kalır
ICCBased alanları kasıtlı olarak pragmatik bir muamele görür. PDF spesifikasyonu, renk yönetimi motoru olmayan görüntüleyicilerin yine de mantıklı bir şekilde işleme yapabilmesi için her ICCBased akışının bir /Alternate alanı veya bileşen sayısı /N aracılığıyla zımni bir alan bildirmesini gerektirir. HotPDF, ICCBased alanını bu alternatif üzerinden çözümler veya giriş eksik olduğunda /N'nin 1, 3 veya 4 olmasından DeviceGray, DeviceRGB veya DeviceCMYK tahminini yapar ve profil baytlarını asla ayrıştırmaz. Bu, lcms bağımlılığı ve profil arama maliyeti olmadığı anlamına gelir, ancak renk ölçümü doğruluğu feda edilir: Profili alternatifinden güçlü bir şekilde sapan bir ICCBased alanı alternatif işlemeyi görüntüler. Ekranda görüntüleme ve küçük resimler için bu, her hafif görüntüleyicinin yaptığı ticaretin aynısıdır ve kendi belgelerinizde açıkça belirtmeniz gereken sınırdır
Her adlandırılmış renk alanı aramasının başarısız olmasına neden olan hata
Sürüm v2.333.0 operatör tesisatı, kırk iki sürüm boyunca görünmez kalan bir kusurla gönderildi: cs ve CS işleyicileri, öndeki eğik çizgisi sağlam olan işlenenlerini (/CS0), eğik çizgi olmadan saklanan kaynak sözlük anahtarlarına (CS0) karşı arıyordu. Her adlandırılmış renk alanı araması her zaman başarısız oluyordu ve kod sessizce varsayılan DeviceGray'e geri dönüyordu. Görünür semptom en kötü şekilde belirsizdi: 1 scn'lik bir Ayrım dolgusu, beyazı boyayan DeviceGray 1.0 haline geliyordu ve beyaz bir sayfa üzerindeki beyaz mürekkep kimsenin ekran görüntüsünü alacağı bir işleme hatası değildir. Sürüm v2.375.0'daki düzeltme, her işlenenden kaynağa aramada uygulanan paylaşılan bir ad normalleştirme yardımcısı oldu
Aynı incelemeden iki kardeş kusur ortaya çıktı. İlk olarak, dizi değerli nesnelere yapılan dolaylı referanslar çözümlenmeden döndürülüyordu: İşleyicinin belge erişiminde yalnızca akışlar ve sözlükler için tipli çözümleyiciler vardı, bu nedenle bağımsız bir [/Separation ...] dizisini gösteren /CS0 5 0 R ham referans olarak geri dönüyordu ve alan desteklenmiyor olarak ayrıştırılıyordu. İkinci olarak, HPDFReadNumericArray katı uzunluk semantiği uygulayarak PDF dizisinin en az sağlanan arabellek kadar uzun olmasını gerektiriyordu. Bir Type 2 işlevinin /C0 ve /C1 değerlerini dört elemanlı bir arabelleğe okumak, bir ve üç bileşenli alternatifler için başarısız oluyor, her iki diziyi de sıfırlıyordu ve v2.376.0 yumuşak HPDFReadNumericArrayUpTo okuyucusunu getirene kadar CMYK olmayan her üstel ton siyah olarak işleniyordu. Aktarılabilir ders şudur: Değişken uzunlukta bir sayısal dizi tuttuğu belgelenmiş olan herhangi bir PDF anahtarı, var olanı doldur okuyucusuyla okunmalıdır; çünkü katı eşleşmeli sabit boyutlu bir arabellek, geçerli dosyaları sessiz sıfırlara dönüştürür
Kendinizi kandırmadan spot renk işlemeyi nasıl test edersiniz?
Rahatsız edici soru, test paketinin tüm bunlara rağmen neden yeşil kaldığıdır. Orijinal regresyon testi olan SeparationRendersDistinguishable, yalnızca işlenen bit eşleminin tamamen siyah olmadığını doğruluyordu (assert). Her spot rengi DeviceGray'e düşüren bir süreç hattı, siyah olmayan gri ve beyaz çıktılar üretiyordu, bu nedenle tüm özellik ölü olmasına rağmen doğrulama geçiyordu. "Boş değil", "tamamı siyah değil" veya "özet sıfır dışı" biçimindeki zayıf doğrulamalar, çalışan bir işleyiciyi bozuk olandan ayıramaz, çünkü neredeyse her hata modu yine de bazı pikseller üretir
Bu hataları gerçekten yakalayan doğrulama stili beklenen rengi kilitler: Ayrım (Separation) mürekkebi bilinen bir tona çözümlenen el yapımı en küçük PDF'i işleyin, ardından o tonda baskın olan pikselleri sayın. İnceleme için bir bit eşlemine dönüştürme işlemi, sayfadan bit eşlemine dönüştürme kılavuzunda açıklanan aynı RenderLoadedPageToBitmap giriş noktasını kullanır
var
Pdf: THotPDF;
Bmp: TBitmap;
X, Y, RedHits: Integer;
Px: TColor;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('spot-red-fixture.pdf', '') > 0 then
begin
Bmp := Pdf.RenderLoadedPageToBitmap(0, 96);
try
RedHits := 0;
for Y := 0 to Bmp.Height - 1 do
for X := 0 to Bmp.Width - 1 do
begin
Px := Bmp.Canvas.Pixels[X, Y];
if (GetRValue(Px) > 180) and (GetGValue(Px) < 100) and
(GetBValue(Px) < 100) then
Inc(RedHits);
end;
// Beklenen mürekkebi kilitleyin: Kırmızı baskın piksellerden oluşan
// gerçek bir alan talep edin, asla "hepsi siyah değil" ile yetinmeyin.
Assert(RedHits > 500);
finally
Bmp.Free;
end;
end;
finally
Pdf.Free;
end;
end;
Test verisi (fixture), doğrulama kadar önemlidir. Tek bir Ayrım (Separation) dolgusuna sahip ve başka hiçbir şeyi olmayan birkaç yüz baytlık el yapımı bir PDF, beklenen çıktının ne olduğu konusunda hiçbir belirsizlik bırakmaz; gerçek dünya dosyası daha fazla kod çalıştırır ancak hangi aşamanın başarısız olduğunu söyleyemez. Artık beklenen renk piksellerini saymayı, herhangi bir işleme duman (smoke) testi için minimum çubuk olarak kabul ediyoruz, çünkü bu kusurları açığa çıkaran tek doğrulama stili budur
Spot renk ve CIE renk alanı işleme, yukarıda gösterilen işlev motoru, gölgeleme işleme ve bit eşlem dışa aktarma yollarının yanı sıra Delphi ve C++Builder için HotPDF Bileşeni'ndeki yüklü belge süreç hattının bir parçasıdır