Quando PDFXCompliance è impostato a 'X-1a', HotPDF valida il colore dei contenuti proprio alla fine del lavoro: EndDoc chiama THotPDF.EnsurePDFX1aContentColorSpaces, che rifiuta qualunque contenuto DeviceRGB, CalRGB o ICCBased RGB in qualunque punto di qualunque pagina e solleva un'eccezione che nomina la risorsa colpevole. Il file non viene mai scritto come documento PDF/X-1a che una tipografia rimbalzerà
Quell'ultima parte è il punto. Un file PDF/X-1a con un logo RGB sfuggito sembra perfettamente a posto sullo schermo, supera una revisione distratta, e poi fallisce il preflight in tipografia due giorni prima dello slot di stampa. Beccarlo nella vostra build Delphi, con un messaggio che dice quale pagina e quale immagine, costa molto meno che scoprirlo da un operatore prepress infastito
Perché PDF/X-1a rifiuta i contenuti RGB?
PDF/X-1a rifiuta RGB perché il formato promette che ogni colore è già definitivo per una precisa condizione di stampa CMYK. ISO 15930-1:2001 §6.2.3 limita il colore dei contenuti a DeviceCMYK, DeviceGray e coloranti spot, cioè spazi Separation e DeviceN i cui alternativi sono CMYK o Gray. L'OutputIntent GTS_PDFX incorporato nel file nomina quella condizione di stampa, per esempio FOGRA39 coated offset, e il flusso ricevente ha il diritto di mandare i numeri dritti alle lastre senza alcuna conversione di colore
RGB rompe quel contratto. Un valore RGB descrive un colore relativo a un display o a uno spazio di lavoro, non una ricetta di inchiostro, quindi qualcuno a valle dovrebbe decidere come separarlo, e X-1a esiste proprio per togliere quella decisione al ricevente. ISO 32000-1 §8.6 raggruppa gli spazi colore PDF nelle famiglie device, CIE-based e speciali, e i membri RGB compaiono in più di una famiglia: DeviceRGB è uno spazio device, CalRGB e ICCBased a tre componenti sono CIE-based, e uno spazio Indexed o Separation può nascondere sotto una base o un alternativo RGB. Un checker che cerca solo l'operatore rg se ne perde la maggior parte. L'edizione successiva PDF/X-1a:2003 (ISO 15930-4) mantiene la stessa regola sul colore; notate che il valore 'X-1a' di HotPDF scrive l'identificazione PDF/X-1a:2001 nel pacchetto XMP
Se il vostro contenuto è davvero RGB e deve restarlo, X-1a è il bersaglio sbagliato. HotPDF delimita questo controllo al solo 'X-1a', quindi 'X-3' e 'X-4', che consentono colore ICC-based e calibrato, non sono toccati
Cosa verifica davvero EnsurePDFX1aContentColorSpaces
EnsurePDFX1aContentColorSpaces combina una flag al momento del disegno con una passeggiata ricorsiva nelle risorse di ogni pagina, e corre per ultimo nel gate PDF/X. EndDoc prima impone i requisiti generali PDF/X: Title deve essere impostato, Trapped deve essere 'True', 'False' o 'Unknown', deve esistere un OutputIntent GTS_PDFX (EnsurePDFXOutputIntent), e ogni pagina vuole una TrimBox o ArtBox (EnsurePDFXPageBoxes). Solo dopo che questi passano corre il controllo sul colore
Il primo percorso è una flag estesa a tutto il documento. I setter di colore RGB di HotPDF, l'incorporamento di immagini bitmap e le voci di colore delle annotation registrano l'uso di DeviceRGB mentre disegnate, il che copre gli operatori inline rg e RG che non compaiono mai in un dizionario risorse. Il secondo percorso percorre il /Resources di ogni pagina e ispeziona:
- gli spazi colore nominati in
/ColorSpace, inclusa l'abbreviazione inline-imageRGBcome sinonimo di DeviceRGB - il
/ColorSpacedi ogni Image XObject - i Form XObject e i tiling Pattern, ricorrendo nei loro
/Resourcesannidati - i Shading Pattern e le voci nel dizionario
/Shadingdella pagina, via il/ColorSpacedello shading - le basi degli spazi Indexed, gli alternativi Separation e DeviceN, e le basi dei Pattern, seguiti fino a una profondità di annidamento di 8
Tre cose vengono rifiutate: DeviceRGB, CalRGB, e gli spazi ICCBased il cui profile stream dichiara N = 3. I dizionari risorse condivisi tra Form XObject e pattern vengono visitati una volta sola, così un insieme di form che si riferiscono a vicenda non manda la passeggiata in loop. Il metodo è pubblico su THotPDF, ma nell'uso normale non lo chiamate mai voi, perché lo fa EndDoc per voi
Disegnare in Delphi una pagina X-1a che passa il controllo
Un documento X-1a HotPDF conforme vuole un OutputIntent CMYK, una TrimBox su ogni pagina, e colore impostato solo tramite le API CMYK, Gray e spot. Lo scheletro qui sotto usa il profilo FOGRA39; AddPDFXOutputIntent prende l'identificatore della condizione di output, una stringa info, lo stream del profilo ICC, il numero di componenti, e lo spazio alternativo
var
Pdf: THotPDF;
Profile: TFileStream;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'brochure-x1a.pdf';
Pdf.Title := 'Spring brochure, press edition';
Pdf.Trapped := 'False';
Pdf.PDFXCompliance := 'X-1a';
Pdf.BeginDoc;
Profile := TFileStream.Create('CoatedFOGRA39.icc', fmOpenRead or fmShareDenyWrite);
try
Pdf.AddPDFXOutputIntent('FOGRA39 (ISO 12647-2:2004)',
'Coated FOGRA39 offset', Profile, 4, 'DeviceCMYK');
finally
Profile.Free;
end;
Pdf.CurrentPage.SetTrimBox(0, 0, 612, 792); // richiesto su ogni pagina
Pdf.CurrentPage.SetCMYKFillColor(0, 0.5, 0.8, 0.1);
Pdf.CurrentPage.Rectangle(72, 600, 468, 120);
Pdf.CurrentPage.Fill;
Pdf.CurrentPage.SetGrayFillColor(0.2); // testo DeviceGray
Pdf.CurrentPage.SetFont('Arial', [], 14);
Pdf.CurrentPage.TextOut(72, 560, 0, 'Spring catalog, press edition');
Pdf.EndDoc; // il controllo del colore corre qui
finally
Pdf.Free;
end;
end;
Ogni chiamata basata su TColor è una trappola in questo contesto. SetRGBFillColor, SetRGBStrokeColor e SetRGBColor prendono tutte un colore GDI ed emettono DeviceRGB, così una routine di servizio scritta anni fa per report orientati allo schermo inquina un lavoro di stampa nel momento in cui viene riusata. Usate SetCMYKFillColor, SetCMYKStrokeColor o SetCMYKColor con componenti nell'intervallo 0 a 1, o gli equivalenti Gray
Colori spot e gradienti CMYK
I coloranti spot sono ammessi in X-1a finché il loro alternativo è CMYK o Gray. RegisterSeparation costruisce lo spazio Separation e ne restituisce il nome risorsa, e RegisterAxialGradient sceglie lo spazio colore dello shading dal numero di componenti che passate, con quattro componenti che significano DeviceCMYK
var
SpotCS, Ramp: AnsiString;
begin
// Inchiostro spot con una composizione CMYK approssimata come alternativo
SpotCS := Pdf.RegisterSeparation('Corporate Red', 'DeviceCMYK',
[0, 1, 0.8, 0.05]);
Pdf.CurrentPage.SetFillColorSpace(SpotCS);
Pdf.CurrentPage.SetFillColor([1.0]); // tinta al 100%
Pdf.CurrentPage.Rectangle(72, 420, 200, 80);
Pdf.CurrentPage.Fill;
// 4 componenti per stop: lo shading è DeviceCMYK, non DeviceRGB
Ramp := Pdf.RegisterAxialGradient(72, 300, 540, 300,
[0, 0, 0, 0], [1, 0.6, 0, 0.2]);
Pdf.CurrentPage.SetFillPattern(Ramp);
Pdf.CurrentPage.Rectangle(72, 260, 468, 80);
Pdf.CurrentPage.Fill;
end;
Passate tre componenti alla stessa chiamata di gradiente e ottenete uno shading DeviceRGB, che la passeggiata delle risorse rifiuta sotto il nome del shading pattern. Lo stesso vale per una Separation registrata con 'DeviceRGB' come alternativo: il nome spot sembra innocuo, ma la passeggiata segue l'alternativo e trova RGB sotto. Come questi inchiostri spot vengono composti quando un viewer o un RIP ripiega sull'alternativo è trattato nell'articolo su rendering di colori spot Separation e DeviceN in Delphi
Le immagini raster chiedono la stessa disciplina. HotPDF vincola le bitmap compresse Flate a DeviceRGB, mentre un JPEG incorporato con icJpeg conserva il suo numero di componenti, quindi un JPEG CMYK a quattro componenti o un JPEG in scala di grigi va bene e un JPEG RGB ordinario no. Convertite le artwork al profilo di stampa nella vostra pipeline di imaging prima che raggiungano il PDF
Perché /DefaultRGB non salva un file PDF/X-1a?
/DefaultRGB non aiuta X-1a perché la regola riguarda ciò che la stampa riceve, non se l'RGB è caratterizzato. Per PDF/A, HotPDF lascia che RegisterDefaultColorSpace('DefaultRGB', ...) assorba l'uso di DeviceRGB: una volta che uno spazio colore Default mappa DeviceRGB su un profilo ICC, il contenuto è device-independent e il controllo di coerenza PDF/A lo accetta. Gli sviluppatori passati per quel flusso tendono a provare la stessa cura qui
EnsurePDFX1aContentColorSpaces ignora deliberatamente quella mappatura. Un valore RGB caratterizzato è pur sempre RGB, e l'OutputIntent X-1a è una condizione di stampa CMYK, quindi qualcuno dovrebbe comunque convertirlo. Se ricordate una sola differenza tra i due profili, d'archivio e di stampa, fate che sia questa: PDF/A chiede se un colore è non ambiguo, PDF/X-1a chiede se è già inchiostro
Ordine di disegno, e il setup di pagina che non conta
Poiché il controllo corre a EndDoc su contenuto già scritto, l'ordine in cui impostate le cose non conta. L'RGB disegnato prima che PDFXCompliance fosse assegnato, o prima che l'OutputIntent fosse registrato, viene comunque beccato. Questo conta per il codice che costruisce pagine in routine condivise e decide il profilo di output tardi, a volte da un'impostazione utente scelta dopo che mezzo documento esiste
Pdf.BeginDoc;
// ... OutputIntent e TrimBox come prima ...
Pdf.CurrentPage.SetRGBFillColor(clRed); // helper legacy, emette DeviceRGB
Pdf.CurrentPage.Rectangle(72, 72, 200, 100);
Pdf.CurrentPage.Fill;
Pdf.PDFXCompliance := 'X-1a'; // deciso dopo il disegno
Pdf.EndDoc; // solleva comunque: DeviceRGB registrato
Una flag al momento del disegno ha una trappola che vale conoscere se costruite un controllo simile da soli. Ogni nuova pagina viene inizializzata con uno stato grafico nero tramite SetRGBColor(0), che emette una coppia 0 0 0 rg e 0 0 0 RG, e se quel boilerplate di setup pagina potesse impostare la flag DeviceRGB, ogni documento sembrerebbe inquinato da RGB, sia per questo controllo sia per il controllo di coerenza colore PDF/A. HotPDF salva e ripristina la flag attorno a quell'inizializzazione, così conta solo il colore che disegnate davvero
Come trovate il contenuto RGB quando EndDoc solleva?
Leggete la posizione all'inizio del messaggio di eccezione, perché dice quale dei due percorsi ha trovato il problema. Il messaggio ha la forma PDFXCompliance 'X-1a': <where> uses <what>, seguita dal riferimento ISO 15930-1 e dal consiglio di convertire in CMYK o Gray o passare a X-3 o X-4. Il validatore solleva una semplice Exception alla prima violazione, quindi fate match sul testo piuttosto che su una classe di eccezione
document content uses DeviceRGB (rg/RG operators, RGB images or annotation colours recorded during drawing)significa che la flag del disegno è scattata. Non c'è numero di pagina, perché la flag è estesa a tutto il documento e viene controllata prima della passeggiata. Cercate nel vostro codice di disegno chiamateSetRGB*, bitmap compresse Flate, JPEG RGB e colori annotationTColorpage 3 image XObject /Im2 uses DeviceRGB contentopage 1 shading Pattern /P1 uses DeviceRGB contentarriva dalla passeggiata delle risorse e punta a una chiave risorsa esattauses an ICCBased RGB colour space (N=3)dopo una posizioneColorSpace /...è il risultato tipico della registrazione di un profilo sRGB conRegisterICCProfilee della sua selezione tramiteSetFillColorSpace, un percorso che la flag del disegno non vede- Le posizioni annidate si concatenano, per esempio
page 2 Form XObject /Fm1 ColorSpace /CS1, così potete seguire il percorso dalla pagina fino alla risorsa che porta lo spazio RGB
try
Pdf.EndDoc;
except
on E: Exception do
begin
if Pos('X-1a', E.Message) > 0 then
LogPrepressFailure(Pdf.FileName, E.Message); // il vostro logger
raise;
end;
end;
Dato che viene riportata solo la prima violazione, sistemare un lavoro con diverse fonti RGB è iterativo: correggete, ricompilate, leggete il messaggio successivo. Per i lavori batch conviene registrare il messaggio completo per file e tenere una breve lista dei colpevoli noti, come una bitmap di logo o un helper di grafici che prende ancora TColor
Dove sta il gate RGB nel vostro preflight
EnsurePDFX1aContentColorSpaces è un gate RGB mirato che gira dentro la vostra build, e si abbina a un preflight PDF/X-1a completo invece di sostituirlo. Copre le famiglie RGB, tramite la passeggiata delle risorse dal /Resources di ogni pagina e tramite la flag del disegno che i setter di colore di HotPDF mantengono per gli operatori inline rg e RG; gli spazi colore annidati vengono seguiti fino a profondità 8 come guardia contro cicli malformati, e la prima violazione viene riportata per EndDoc. Le altre famiglie di colore come Lab o CalGray sono affare del preflight completo, quindi passate il file finito attraverso un validatore esterno come parte della build per avere il verdetto di conformità completo. Il quadro più ampio dell'output di conformità è nella guida all'output PDF/A, PDF/X e PDF/UA con HotPDF, e cablare un validatore in una pipeline non presidiata è trattato in automazione dei controlli preflight PDF in Delphi
HotPDF è un componente PDF VCL nativo per Delphi e C++Builder con output PDF/X, PDF/A e PDF/UA, API di colore CMYK e spot, e supporto OutputIntent ICC. Dettagli, licenze e download di prova sono sulla pagina del prodotto HotPDF Delphi PDF component