Når PDFXCompliance er sat til 'X-1a', validerer HotPDF indholdets farver helt til sidst i jobbet: EndDoc kalder THotPDF.EnsurePDFX1aContentColorSpaces, som afviser alt DeviceRGB-, CalRGB- eller ICCBased RGB-indhold hvor som helst på enhver side og udløser en exception, der navngiver den overtrædende ressource. Filen bliver aldrig skrevet som et PDF/X-1a-dokument, som et trykkeri ville afvise
Den sidste del er poenget. En PDF/X-1a-fil med ét uvedkommende RGB-logo ser helt fint ud på skærmen, består et hurtigt gennemsyn og fejler så preflight hos trykkeriet to dage før presetidspunktet. At fange det i dit Delphi-build, med en besked, der fortæller dig hvilken side og hvilket billede, er langt billigere end at få det at vide fra en irriteret prepress-operatør
Hvorfor afviser PDF/X-1a RGB-indhold?
PDF/X-1a afviser RGB, fordi formatet lover, at hver farve allerede er endelig for én bestemt CMYK-tryktilstand. ISO 15930-1:2001 §6.2.3 begrænser indholdsfarver til DeviceCMYK, DeviceGray og spotfarvestoffer, altså Separation- og DeviceN-rum, hvis alternativer er CMYK eller Gray. Den indlejrede GTS_PDFX OutputIntent navngiver den tryktilstand, for eksempel FOGRA39 coated offset, og det modtagende workflow har ret til at sende tallene direkte til trykpladerne uden nogen farvekonvertering
RGB bryder den kontrakt. En RGB-værdi beskriver en farve relativt til en skærm eller et arbejdsrum, ikke en trykfarveopskrift, så nogen downstream måtte beslutte, hvordan den skal separeres, og X-1a findes netop for at tage den beslutning fra modtageren. ISO 32000-1 §8.6 grupperer PDF-farverum i device-, CIE-based- og special-familier, og RGB-medlemmerne optræder i mere end én familie: DeviceRGB er et device-rum, CalRGB og ICCBased med tre komponenter er CIE-based, og et Indexed- eller Separation-rum kan skjule en RGB-base eller et RGB-alternativ nedenunder. Et tjek, der kun leder efter rg-operatoren, misser de fleste af dem. Den senere PDF/X-1a:2003-udgave (ISO 15930-4) beholder samme farveregel; bemærk at HotPDFs 'X-1a'-værdi skriver PDF/X-1a:2001-identifikationen ind i XMP-pakken
Hvis dit indhold reelt er RGB og skal forblive det, er X-1a det forkerte mål. HotPDF afgrænser dette tjek til 'X-1a' alene, så 'X-3' og 'X-4', som tillader ICC-based og kalibreret farve, er upåvirkede
Hvad EnsurePDFX1aContentColorSpaces faktisk tjekker
EnsurePDFX1aContentColorSpaces kombinerer et tegnetidsflag med et rekursivt gennemløb af hver sides ressourcer og kører sidst i PDF/X-porten. EndDoc håndhæver først de generelle PDF/X-krav: Title skal være sat, Trapped skal være 'True', 'False' eller 'Unknown', en GTS_PDFX OutputIntent skal findes (EnsurePDFXOutputIntent), og hver side skal have en TrimBox eller ArtBox (EnsurePDFXPageBoxes). Først efter de er bestået, kører farvetjekket
Den første vej er et dokumentbredt flag. HotPDFs RGB-farvesættere, bitmapbillede-indlejring og annotationsfarveposter noterer DeviceRGB-forbrug, mens du tegner, hvilket dækker inline rg- og RG-operatorer, der aldrig optræder i en ressource-dictionary. Den anden vej går hver sides /Resources igennem og inspicerer:
- Navngivne farverum i
/ColorSpace, inklusiv inline-billedforkortelsenRGBsom synonym for DeviceRGB /ColorSpacefor hvert Image XObject- Form XObjects og tiling Patterns, ved at rekursere ned i deres egne nestede
/Resources - Shading Patterns og poster i sidens
/Shading-dictionary, via shadingens/ColorSpace - Indexed baserum, Separation- og DeviceN-alternativer og Pattern-baserum, fulgt ned til en nestingdybde på 8
Tre ting afvises: DeviceRGB, CalRGB og ICCBased-rum, hvis profilstream deklarerer N = 3. Ressource-dictionaries delt mellem Form XObjects og patterns besøges én gang, så et gensidigt refererende sæt former ikke sender gennemløbet ind i en løkke. Metoden er offentlig på THotPDF, men i normal brug kalder du den aldrig selv, for EndDoc gør det for dig
At tegne en X-1a-side i Delphi, der består tjekket
Et overensstemmende HotPDF X-1a-dokument skal bruge en CMYK OutputIntent, en TrimBox på hver side og farver sat udelukkende gennem CMYK-, Gray- og spot-API'erne. Skelettet nedenfor bruger FOGRA39-profilen; AddPDFXOutputIntent tager outputtilstand-identifikatoren, en info-streng, ICC-profilstreamen, dens komponentantal og alternativrummet
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); // påkrævet på hver side
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); // DeviceGray-tekst
Pdf.CurrentPage.SetFont('Arial', [], 14);
Pdf.CurrentPage.TextOut(72, 560, 0, 'Spring catalog, press edition');
Pdf.EndDoc; // farvetjekket kører her
finally
Pdf.Free;
end;
end;
Ethvert TColor-baseret kald er en fælde i den her kontekst. SetRGBFillColor, SetRGBStrokeColor og SetRGBColor tager alle en GDI-farve og udsender DeviceRGB, så en hjælperutine skrevet for år siden til skærmorienterede rapporter tilsmudser et printjob, i samme sekund den genbruges. Brug SetCMYKFillColor, SetCMYKStrokeColor eller SetCMYKColor med komponenter i området 0 til 1, eller Gray-ækvivalenterne
Spotfarver og CMYK-gradients
Spotfarvestoffer er tilladt i X-1a, så længe deres alternativ er CMYK eller Gray. RegisterSeparation bygger Separation-rummet og returnerer dets ressourcenavn, og RegisterAxialGradient vælger shading-farverummet ud fra det antal komponenter, du giver, med fire komponenter betydende DeviceCMYK
var
SpotCS, Ramp: AnsiString;
begin
// Spotfarve med en tilnærmet CMYK-opbygning som alternativ
SpotCS := Pdf.RegisterSeparation('Corporate Red', 'DeviceCMYK',
[0, 1, 0.8, 0.05]);
Pdf.CurrentPage.SetFillColorSpace(SpotCS);
Pdf.CurrentPage.SetFillColor([1.0]); // 100 % tint
Pdf.CurrentPage.Rectangle(72, 420, 200, 80);
Pdf.CurrentPage.Fill;
// 4 komponenter pr. stop: shadingen er DeviceCMYK, ikke 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;
Giver du tre komponenter til det samme gradientkald, får du en DeviceRGB-shading, som ressourcegennemløbet afviser under shading-patternets navn. Det samme gælder en Separation registreret med 'DeviceRGB' som alternativ: spotnavnet ser uskyldigt ud, men gennemløbet følger alternativet og finder RGB nedenunder. Hvordan sådanne spotfarver kompositeres, når en viewer eller RIP falder tilbage til alternativet, er dækket i artiklen om rendering af Separation- og DeviceN-spotfarver i Delphi
Rasterbilleder behøver samme disciplin. HotPDF låser Flate-komprimerede bitmaps til DeviceRGB, mens en JPEG indlejret med icJpeg beholder sit eget komponentantal, så en firekomponent CMYK JPEG eller en grayscale JPEG er fint, og en almindelig RGB JPEG er ikke. Konvertér artworket til trykprofilen i din imaging-pipeline, før det når PDF'en
Hvorfor redder /DefaultRGB ikke en PDF/X-1a-fil?
/DefaultRGB hjælper ikke X-1a, for reglen handler om, hvad presset modtager, ikke om RGB'en er karakteriseret. Til PDF/A lader HotPDF RegisterDefaultColorSpace('DefaultRGB', ...) absorbere DeviceRGB-forbrug: når et Default-farverum mapper DeviceRGB til en ICC-profil, er indholdet device-uafhængigt, og PDF/A-konsistenstjekket accepterer det. Udviklere, der har været igennem det workflow, har tendens til at prøve samme løsning her
EnsurePDFX1aContentColorSpaces ignorerer bevidst den mapping. En karakteriseret RGB-værdi er stadig RGB, og X-1a OutputIntent er en CMYK-tryktilstand, så nogen måtte alligevel konvertere den. Skal du huske én forskel mellem de to arkiv- og trykprofiler, så lad det være denne: PDF/A spørger, om en farve er entydig, PDF/X-1a spørger, om den allerede er trykfarve
Tegnerækkefølgen og den sideopsætning, der ikke tæller
Fordi tjekket kører ved EndDoc over allerede skrevet indhold, betyder rækkefølgen, du satte tingene op i, ingenting. RGB tegnet, før PDFXCompliance blev tildelt, eller før OutputIntent blev registreret, fanges stadig. Det betyder noget for kode, der bygger sider i delte rutiner og beslutter outputprofilen sent, nogle gange ud fra en brugerindstilling valgt, efter halvdelen af dokumentet findes
Pdf.BeginDoc;
// ... OutputIntent og TrimBox som før ...
Pdf.CurrentPage.SetRGBFillColor(clRed); // legacy-hjælper, udsender DeviceRGB
Pdf.CurrentPage.Rectangle(72, 72, 200, 100);
Pdf.CurrentPage.Fill;
Pdf.PDFXCompliance := 'X-1a'; // besluttet efter tegning
Pdf.EndDoc; // udløser stadig fejl: DeviceRGB registreret
Et tegnetidsflag har én fælde, du bør kende, hvis du bygger et lignende tjek selv. Hver ny side initialiseres med en sort graphics state gennem SetRGBColor(0), som udsender et 0 0 0 rg- og 0 0 0 RG-par, og hvis den sideopsætningsboilerplate måtte sætte DeviceRGB-flaget, ville hvert dokument se RGB-tilsmudset ud, både for dette tjek og for PDF/A-farvekonsistenstjekket. HotPDF gemmer og gendanner flaget omkring den initialisering, så kun farver, du faktisk tegner, tæller
Hvordan finder du RGB-indholdet, når EndDoc udløser en fejl?
Læs placeringen i starten af exception-beskeden, for den fortæller dig, hvilken af de to veje, der fandt problemet. Beskeden har formen PDFXCompliance 'X-1a': <where> uses <what>, efterfulgt af ISO 15930-1-referencen og rådet om at konvertere til CMYK eller Gray eller skifte til X-3 eller X-4. Validatoren udløser en almindelig Exception ved den første overtrædelse, så match på teksten i stedet for på en exception-klasse
document content uses DeviceRGB (rg/RG operators, RGB images or annotation colours recorded during drawing)betyder, at tegnetidsflaget slog til. Der er intet sidetal, for flaget er dokumentbredt og tjekkes før gennemløbet. Søg din tegnekode efterSetRGB*-kald, Flate-komprimerede bitmaps, RGB-JPEG'er ogTColor-annotationsfarverpage 3 image XObject /Im2 uses DeviceRGB contentellerpage 1 shading Pattern /P1 uses DeviceRGB contentkommer fra ressourcegennemløbet og peger på en præcis ressourcenøgleuses an ICCBased RGB colour space (N=3)efter enColorSpace /...-placering er det typiske resultat af at registrere en sRGB-profil medRegisterICCProfileog vælge den gennemSetFillColorSpace, en vej, tegnetidsflaget ikke ser- Nestede placeringer kæder sig sammen, for eksempel
page 2 Form XObject /Fm1 ColorSpace /CS1, så du kan følge vejen fra siden ned til den ressource, der bærer RGB-rummet
try
Pdf.EndDoc;
except
on E: Exception do
begin
if Pos('X-1a', E.Message) > 0 then
LogPrepressFailure(Pdf.FileName, E.Message); // din egen logger
raise;
end;
end;
Fordi kun den første overtrædelse rapporteres, er det at rette et job med flere RGB-kilder iterativt: ret, genbyg, læs næste besked. Til batchjobs betaler det sig at logge hele beskeden pr. fil og holde en kort liste over kendte syndere, som et logo-bitmap eller en chart-hjælper, der stadig tager TColor
Hvor RGB-porten passer ind i din preflight
EnsurePDFX1aContentColorSpaces er en målrettet RGB-port, der kører inde i dit build, og den parres med en fuld PDF/X-1a-preflight frem for at erstatte én. Den dækker RGB-familierne gennem ressourcegennemløbet fra hver sides /Resources og gennem tegnetidsflaget, som HotPDFs farvesættere vedligeholder for inline rg- og RG-operatorer; nestede farverum følges til dybde 8 som sikring mod misdannede cykler, og den første overtrædelse rapporteres pr. EndDoc. Andre farvefamilier som Lab eller CalGray er en sag for den fulde preflight, så kør den færdige fil gennem en ekstern validator som del af dit build for at få den komplette konformitetsvurdering. Det bredere billede af konformitetsoutput er i guiden til PDF/A-, PDF/X- og PDF/UA-output med HotPDF, og tilkobling af en validator i en uovervåget pipeline er dækket i automatisering af PDF-preflight-tjek i Delphi
HotPDF er en native VCL PDF-komponent til Delphi og C++Builder med PDF/X-, PDF/A- og PDF/UA-output, CMYK- og spotfarve-API'er og ICC OutputIntent-understøttelse. Detaljer, licensering og trial-download findes på HotPDF Delphi PDF component-productsiden