När PDFXCompliance sätts till 'X-1a' validerar HotPDF innehållsfärgen alldeles i slutet av jobbet: EndDoc anropar THotPDF.EnsurePDFX1aContentColorSpaces, som avvisar alla DeviceRGB-, CalRGB- eller ICCBased-RGB-innehåll var som helst på vilken sida som helst och kastar ett exception som namnger den trassliga resursen. Filen skrivs aldrig ut som ett PDF/X-1a-dokument som ett tryckeri studsar
Den sista delen är poängen. En PDF/X-1a-fil med en enstaka friarande RGB-logo ser helt fin ut på skärmen, klarar en tillfällig granskning, och faller sedan i preflighten hos tryckeriet två dagar innan pressen rullar. Att fånga den i din Delphi-build, med ett meddelande som talar om vilken sida och vilken bild, är betydligt billigare än att få höra det av en irriterad prepress-operatör
Varför avvisar PDF/X-1a RGB-innehåll?
PDF/X-1a avvisar RGB för formatet lovar att varje färg redan är slutgiltig för ett specifikt CMYK-tryckvillkor. ISO 15930-1:2001 §6.2.3 begränsar innehållsfärg till DeviceCMYK, DeviceGray och spotfärgsämnen, alltså Separation- och DeviceN-rymder vars alternativ är CMYK eller Gray. Den i filen inbäddade GTS_PDFX OutputIntenten namnger det tryckvillkoret, till exempel FOGRA39 coated offset, och det mottagande arbetsflödet har all rätt att skicka talen rakt till plåtarna utan någon färgkonvertering
RGB bryter kontraktet. Ett RGB-värde beskriver en färg i förhållande till en skärm eller en arbetsyta, inte ett bläckrecept, så någon nedströms skulle behöva avgöra hur den separeras, och X-1a finns just för att ta det beslutet från mottagaren. ISO 32000-1 §8.6 grupperar PDF-färgrymder i device-, CIE-baserade och special-familjer, och RGB-medlemmarna dyker upp i mer än en familj: DeviceRGB är en device-rymd, CalRGB och ICCBased med tre komponenter är CIE-baserade, och en Indexed- eller Separation-rymd kan gömma en RGB-bas eller alternativ under sig. En kontrollant som bara letar efter rg-operatorn missar de flesta. Den senare upplagan PDF/X-1a:2003 (ISO 15930-4) behåller samma färgregel; notera att HotPDF:s 'X-1a'-värde skriver PDF/X-1a:2001-identifieringen i XMP-paketet
Om ditt innehåll faktiskt är RGB och ska förbli så är X-1a fel mål. HotPDF avgränsar den här kontrollen till 'X-1a' bara, så 'X-3' och 'X-4', som tillåter ICC-baserad och kalibrerad färg, är opåverkade
Vad kontrollerar EnsurePDFX1aContentColorSpaces egentligen?
EnsurePDFX1aContentColorSpaces kombinerar en rit-tidsflagga med en rekursiv genomgång av varje sidas resurser, och den körs sist i PDF/X-porten. EndDoc driver först de allmänna PDF/X-kraven: Title måste vara satt, Trapped måste vara 'True', 'False' eller 'Unknown', en GTS_PDFX OutputIntent måste finnas (EnsurePDFXOutputIntent), och varje sida behöver en TrimBox eller ArtBox (EnsurePDFXPageBoxes). Först efter att de klarats körs färgkontrollen
Den första vägen är en dokumentvid flagga. HotPDF:s RGB-färgsättare, inbäddning av bitmapbilder och annoteringens färgposter registrerar DeviceRGB-användning medan du ritar, vilket täcker inline rg- och RG-operatorer som aldrig syns i en resursdictionary. Den andra vägen går igenom varje sidas /Resources och inspekterar:
- Namngivna färgrymder i
/ColorSpace, inklusive inline-bildförkortningenRGBsom synonym för DeviceRGB /ColorSpaceför varje Image XObject- Form XObjects och tiling Patterns, genom att rekursera in i deras egna nästade
/Resources - Shading Patterns och poster i sidans
/Shading-dictionary, via shadings/ColorSpace - Indexed-basrymder, Separation- och DeviceN-alternativ, och Pattern-basrymder, följda ner till ett nästningsdjup av 8
Tre saker avvisas: DeviceRGB, CalRGB, och ICCBased-rymder vars profilström deklarerar N = 3. Resursdictionaryer delade mellan Form XObjects och patterns besöks en gång, så en ömsesidigt refererande uppsättning former skickar inte genomgången in i en loop. Metoden är publik på THotPDF, men i normal användning anropar du den aldrig själv, för EndDoc gör det åt dig
Rita en X-1a-sida i Delphi som klarar kontrollen
Ett överensstämmande HotPDF X-1a-dokument behöver en CMYK-OutputIntent, en TrimBox på varje sida, och färg satt bara genom CMYK-, Gray- och spot-API:erna. Skelettet nedan använder FOGRA39-profilen; AddPDFXOutputIntent tar utskriftsvillkorets identifierare, en infosträng, ICC-profilströmmen, dess komponentantal, och alternativrymden
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); // krävs på varje sida
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-text
Pdf.CurrentPage.SetFont('Arial', [], 14);
Pdf.CurrentPage.TextOut(72, 560, 0, 'Spring catalog, press edition');
Pdf.EndDoc; // färgkontrollen körs här
finally
Pdf.Free;
end;
end;
Varje TColor-baserat anrop är en fälla i det här sammanhanget. SetRGBFillColor, SetRGBStrokeColor och SetRGBColor tar alla en GDI-färg och avger DeviceRGB, så en hjälprutin skriven för år sedan för skärmorienterade rapporter smutsar ner ett tryckjobb i samma stund den återanvänds. Använd SetCMYKFillColor, SetCMYKStrokeColor eller SetCMYKColor med komponenter i intervallet 0 till 1, eller Gray-motsvarigheterna
Spotfärger och CMYK-gradienter
Spotfärgsämnen tillåts i X-1a så länge deras alternativ är CMYK eller Gray. RegisterSeparation bygger Separation-rymden och returnerar dess resursnamn, och RegisterAxialGradient plockar shadingens färgrymd utifrån antalet komponenter du skickar, med fyra komponenter som betyder DeviceCMYK
var
SpotCS, Ramp: AnsiString;
begin
// Spotbläck med en ungefärlig CMYK-uppbyggnad som alternate
SpotCS := Pdf.RegisterSeparation('Corporate Red', 'DeviceCMYK',
[0, 1, 0.8, 0.05]);
Pdf.CurrentPage.SetFillColorSpace(SpotCS);
Pdf.CurrentPage.SetFillColor([1.0]); // 100 % ton
Pdf.CurrentPage.Rectangle(72, 420, 200, 80);
Pdf.CurrentPage.Fill;
// 4 komponenter per stopp: shadingen är DeviceCMYK, inte 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;
Skicka tre komponenter till samma gradientanrop och du får en DeviceRGB-shading, som resursgenomgången avvisar under shading-patterns namn. Samma gäller en Separation registrerad med 'DeviceRGB' som alternativ: spotnamnet ser harmlöst ut, men genomgången följer alternativet och hittar RGB under. Hur sådana spotbläck komponeras när en viewer eller RIP faller tillbaka till alternativet tas upp i artikeln om att rendera Separation- och DeviceN-spotfärger i Delphi
Rasterbilder behöver samma disciplin. HotPDF spikar Flate-komprimerade bitmaps till DeviceRGB, medan en JPEG inbäddad med icJpeg behåller sitt eget komponentantal, så en fyra-komponents CMYK JPEG eller en gråskale-JPEG är fin och en vanlig RGB JPEG är det inte. Konvertera grafiken till pressprofilen i din bildpipeline innan den når PDF:en
Varför räddar /DefaultRGB inte en PDF/X-1a-fil?
/DefaultRGB hjälper inte X-1a för regeln handlar om vad pressen tar emot, inte om RGB:en är karakteriserad. För PDF/A låter HotPDF RegisterDefaultColorSpace('DefaultRGB', ...) absorbera DeviceRGB-användning: när en Default-färgrymd en gång mappar DeviceRGB till en ICC-profil är innehållet device-oberoende och PDF/A-konsekvenskontrollen accepterar det. Utvecklare som varit igenom det arbetsflödet tenderar att prova samma fix här
EnsurePDFX1aContentColorSpaces ignorerar den mappningen medvetet. Ett karakteriserat RGB-värde är fortfarande RGB, och X-1a-OutputIntenten är ett CMYK-tryckvillkor, så någon skulle ändå behöva konvertera det. Om du ska minnas en skillnad mellan de två arkiverings- och tryckprofilerna, låt det bli den här: PDF/A frågar om en färg är entydig, PDF/X-1a frågar om den redan är bläck
Ritordning, och den siduppsättning som inte räknas
Eftersom kontrollen körs vid EndDoc över redan skrivet innehåll spelar ordningen du sätter upp saker i ingen roll. RGB ritad innan PDFXCompliance tilldelats, eller innan OutputIntenten registrerades, fångas ändå. Det spelar roll för kod som bygger sidor i delade rutiner och bestämmer utdataprofilen sent, ibland från en användarinställning vald efter att halva dokumentet finns
Pdf.BeginDoc;
// ... OutputIntent och TrimBox som tidigare ...
Pdf.CurrentPage.SetRGBFillColor(clRed); // äldre hjälprutin, avger DeviceRGB
Pdf.CurrentPage.Rectangle(72, 72, 200, 100);
Pdf.CurrentPage.Fill;
Pdf.PDFXCompliance := 'X-1a'; // beslutat efter ritandet
Pdf.EndDoc; // kastar ändå: DeviceRGB registrerad
En rit-tidsflagga har en fälla värd att känna till om du bygger en liknande kontroll själv. Varje ny sida initieras med ett svart graphics state via SetRGBColor(0), som avger ett 0 0 0 rg- och 0 0 0 RG-par, och om den siduppsättningskittet fick sätta DeviceRGB-flaggan skulle varje dokument se RGB-nedsmutsat ut, både för den här kontrollen och för PDF/A-färgkonsekvenskontrollen. HotPDF sparar och återställer flaggan runt den initieringen, så bara färg du faktiskt ritar räknas
Hur hittar du RGB-innehållet när EndDoc kastar?
Läs platsen i början av exceptionmeddelandet, för den talar om vilken av de två vägarna som hittade problemet. Meddelandet har formen PDFXCompliance 'X-1a': <where> uses <what>, följt av ISO 15930-1-referensen och rådet att konvertera till CMYK eller Gray eller byta till X-3 eller X-4. Validatorn kastar ett vanligt Exception vid första överträdelsen, så matcha på texten snarare än på en exceptionklass
document content uses DeviceRGB (rg/RG operators, RGB images or annotation colours recorded during drawing)betyder att rit-tidsflaggan slog till. Det finns inget sidnummer, för flaggan är dokumentvid och kontrolleras före genomgången. Sök din ritkod efterSetRGB*-anrop, Flate-komprimerade bitmaps, RGB-JPEG:er ochTColor-annoteringfärgerpage 3 image XObject /Im2 uses DeviceRGB contentellerpage 1 shading Pattern /P1 uses DeviceRGB contentkommer från resursgenomgången och pekar på en exakt resursnyckeluses an ICCBased RGB colour space (N=3)efter enColorSpace /...-plats är det typiska resultatet av att registrera en sRGB-profil medRegisterICCProfileoch välja den viaSetFillColorSpace, en väg rit-tidsflaggan inte ser- Nästade platser kedjas ihop, till exempel
page 2 Form XObject /Fm1 ColorSpace /CS1, så du kan följa vägen från sidan ner till resursen som bär RGB-rymden
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;
Eftersom bara den första överträdelsen rapporteras är fixande av ett jobb med flera RGB-källor iterativt: fixa, bygg om, läs nästa meddelande. För batchjobb lönar det sig att logga hela meddelandet per fil och hålla en kort lista över kända synder, som en logobitmap eller en diagramhjälp som fortfarande tar TColor
Var RGB-porten passar in i din preflight
EnsurePDFX1aContentColorSpaces är en riktad RGB-port som körs inuti din build, och den paras med en fullständig PDF/X-1a-preflight i stället för att ersätta en. Den täcker RGB-familjerna, genom resursgenomgången från varje sidas /Resources och genom rit-tidsflaggan som HotPDF:s färgsättare underhåller för inline rg- och RG-operatorer; nästade färgrymder följs ner till djup 8 som skydd mot felformade cykler, och den första överträdelsen rapporteras per EndDoc. Andra färgfamiljer som Lab eller CalGray är en fråga för hela preflighten, så kör den färdiga filen genom en extern validator som del av din build för att få hela överensstämmelsedomslutet. Den bredare bilden av överensstämmelseutdata finns i guiden till PDF/A-, PDF/X- och PDF/UA-utdata med HotPDF, och att koppla in en validator i en obemannad pipeline tas upp i att automatisera PDF-preflightkontroller i Delphi
HotPDF är en nativ VCL PDF-komponent för Delphi och C++Builder med PDF/X-, PDF/A- och PDF/UA-utdata, CMYK- och spotfärg-API:er, och stöd för ICC OutputIntent. Detaljer, licensiering och testnedladdningen finns på produktsidan för HotPDF Delphi PDF-komponenten