veraPDF vlagt ISO 19005-1 6.2.3.3 op een bestand dat nooit RGB tekent, een kale re f ongecalibreerd noemt, of pagina 2 laat zakken terwijl een identieke pagina 1 slaagt. PDF/A beoordeelt die regels op wat elke pagina tekent, dus de PDF/A-validator van PDFium Component voor Delphi volgt elke pagina tot in forms, patterns, glyphs en annotaties voordat hij over kleur en transparantie oordeelt
Wat 6.2.3.3 en 6.2.4.3 werkelijk eisen
ISO 19005-1 6.2.3.3 propt drie onafhankelijke regels in één alinea. Een conform bestand mag DeviceRGB of DeviceCMYK gebruiken maar niet allebei; als een ongecalibreerde kleurruimte wordt gebruikt, moet het bestand een PDF/A-1 OutputIntent bevatten; en DeviceRGB is alleen toegestaan met een intent waarvan het profiel RGB is, DeviceCMYK alleen met een CMYK-variant. DeviceGray ontbreekt op die lijst omdat de clausule daarna uitlegt hoe grijs onder elk van beide intents wordt omgezet. De intent zelf is optioneel: 6.2.2 zegt dat een bestand er één mag opgeven, en telt alleen een OutputIntents-entry met /S /GTS_PDFA1 en een geldige ICC-profielstream in /DestOutputProfile mee. Een checker die van elk bestand een intent eist, wijst dus conforme documenten af die nooit devicekleur tekenen. Part 1 rept niet over DefaultRGB of DefaultCMYK, maar een kleur die erlangs is gemapt wordt gerenderd in een op CIE gebaseerde ruimte (ISO 32000-1 §8.6.5.6), wat voldoet aan de eis van deviceonafhankelijkheid uit 6.2.3.1; de veraPDF-testsuite voor 6.2.3.3 telt dat als gecalibreerd, en PDFium Component leest de clausule op dezelfde manier. Het mixverbod staat apart: een PDF/A-1-bestand dat zowel RGB als CMYK tekent zakt, ook wanneer Default-entries allebei calibreren. ISO 19005-2 6.2.4.3 schaft dat verbod af en calibreert elke ruimte op eigen kracht, zoals de rechterkolom hieronder laat zien, dus PDFium Component draait één scan per part en past de mixcontrole alleen op PDF/A-1-claims toe
| Getekende device-ruimte | PDF/A-1 (ISO 19005-1 6.2.3.3) | PDF/A-2 en later (ISO 19005-2 6.2.4.3) |
|---|---|---|
| DeviceRGB | DefaultRGB in scope of een RGB-intent; niet naast DeviceCMYK | DefaultRGB in scope, of een RGB OutputIntent |
| DeviceCMYK | DefaultCMYK in scope of een CMYK-intent; niet naast DeviceRGB | DefaultCMYK in scope, of een CMYK OutputIntent |
| DeviceGray | DefaultGray in scope, of enige PDF/A-1 OutputIntent | DefaultGray in scope, of enige PDF/A OutputIntent |
Wat telt als gebruik van een kleurruimte?
Een kleurruimte gebruiken betekent ermee tekenen op een pad dat een reader zal renderen. Het declareren is niet genoeg. De veraPDF-suite maakt dat punt met een 6.2.3.3-slaagbestand: een benoemde Form XObject zet CMYK met K en k, zit in de resourcedictionary van de pagina, wordt nooit vanuit de paginacontent aangeroepen, en de OutputIntent van het bestand is RGB. Een zoektocht door het hele bestand op devicenamen voor kleur laat dat bestand zakken, en mist er één dat uitsluitend DeviceRGB tekent onder een CMYK-intent, waar geen twee namen conflicteren. PDFium Component loopt in plaats daarvan door de tekengraaf, gebouwd op zijn byte-level PDF/A-preflightscanner. Vanaf elke pagina telt de tocht kleur getekend door:
- de contentstreams van de pagina, en elke Form XObject die ze met
Doaanroepen, geneste forms inbegrepen - een pattern geselecteerd met
scnofSCN, gelezen met de eigenResourcesvan het pattern - de
CharProcsvan een Type 3-font geselecteerd metTf - image XObjects en inline afbeeldingen, naar de kleurruimte die hun eigen dictionary noemt
- appearance streams van annotaties, bovenop de pagina getekend; wanneer de
/AP /Nvan een widget een state-dictionary is, telt elke state mee, want het omschakelen van het veld tekent degene die/ASniet selecteerde
De subtielere helft van bereikbaarheid is kleur die de content nooit benoemt. q 0 0 10 10 re f Q bevat geen kleuroperator. Het tekent toch. De initiële kleurruimte van de graphics state is DeviceGray (ISO 32000-1 Table 52), dus de vulling is DeviceGray-zwart, onder elk part ongecalibreerd tenzij er een PDF/A OutputIntent of DefaultGray bestaat. De scan houdt daarom bij of er al iets een kleur heeft gekozen: rg, k, g en hun stroking-vormen selecteren een device-ruimte, cs en CS selecteren wat ze benoemen, en een fill-, stroke- of tekendeoperator die vóór elke keuze wordt bereikt noteert DeviceGray. /CS0 cs 1 0 0 /P0 scn heeft al een ruimte gekozen, dus die scn is niet grijs
Inline afbeeldingen brengen hun kleurruimte en hun ruwe samples mee in de contentstream zelf, en een scanner moet allebei zorgvuldig lezen. De /CS kan een afkorting zijn (G, RGB, CMYK, I) of een resourcenaam zoals één die uitkomt op [/Indexed /DeviceRGB 255 13 0 R], waarvan de basis meetelt; en de bytes tussen ID en EI zijn willekeurige binaire data, dus EI beëindigt de afbeelding alleen tussen witruimte, anders wordt een rg in gecomprimeerde samples een spookoperator
% pagina 1: DefaultRGB in scope, en een XObject dat niets aanroept
4 0 obj << /Type /Page /Parent 2 0 R /Contents 5 0 R
/Resources << /ColorSpace << /DefaultRGB 9 0 R >>
/XObject << /Fm0 6 0 R >> >> >>
endobj
% pagina 2: dezelfde contentstream, geen ColorSpace-subdictionary
7 0 obj << /Type /Page /Parent 2 0 R /Contents 5 0 R /Resources << >> >>
endobj
5 0 obj << /Length 46 >> stream
1 0 0 rg 72 72 200 100 re f
q 0 0 10 10 re f Q
endstream
endobj
6 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 50 50] /Length 24 >> stream
0 0 0 1 k 0 0 50 50 re f
endstream
endobj
9 0 obj [/ICCBased 10 0 R]
endobj
Elk symptoom uit de opening valt uit dit fragment te verklaren. /Fm0 ontmoet nooit een Do, dus zijn k is irrelevant. De kale re f op beide pagina's is DeviceGray zonder iets dat hem calibreert. De rg op pagina 1 wordt gedekt door de DefaultRGB in de resources waarmee pagina 1 tekent; pagina 2 draait dezelfde stream tegen resources zonder die mapping, dus dezelfde bytes zijn daar ongecalibreerd. Verwacht bij een PDF/A-1b-claim: pvaiMissingOutputIntent met pvaiMissingIccProfile, aangedreven door de RGB van pagina 2 en het grijs van beide pagina's. De form levert niets; aangeroepen zou zijn CMYK bovenop het PDF/A-1-mixverbod stapelen
Default-kleurruimten horen bij de resourcedictionary die tekent
De Default-mappings worden opgezocht in het ColorSpace-subdictionary van de huidige resourcedictionary (ISO 32000-1 §8.6.5.6), wat ze precies zo lokaal maakt als de resources zelf; een document heeft geen globale default. Een image XObject heeft geen eigen Resources, dus een afbeelding waarvan het dictionary /ColorSpace /DeviceCMYK zegt wordt gecalibreerd door de DefaultCMYK van de pagina of form die hem toevallig tekent, en dezelfde afbeelding vanaf twee plekken getekend kan op de één gecalibreerd zijn en op de ander niet. Form XObjects, tiling patterns en Type 3-glyphprocedures dragen hun eigen Resources, dus de DefaultCMYK van een pagina reikt er niet naar binnen, terwijl een mapping in hun eigen dictionary dat wel doet. PDFium Component scherpt de mappings op dezelfde manier af. Het oordeel komt terug als record TPdfAValidationResult: de gedetecteerde Conformance plus een set Issues. Dat is genoeg om een map te triageren
uses
System.SysUtils, System.Classes, System.TypInfo, FPdfPdfa;
procedure ReportColorFindings(const FileName: string; Log: TStrings);
const
ColorRules: TPdfAValidationIssues = [pvaiMissingOutputIntent,
pvaiMissingIccProfile, pvaiMixedDeviceColorSpaces, pvaiBlendSpaceUndefined];
var
Source: TFileStream;
Res: TPdfAValidationResult;
Found: TPdfAValidationIssues;
Issue: TPdfAValidationIssue;
begin
Source := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Res := ValidatePdfACompliance(Source); // leest vanaf positie 0
finally
Source.Free;
end;
Log.Add(ExtractFileName(FileName) + ': ' +
GetEnumName(TypeInfo(TPdfAConformance), Ord(Res.Conformance)));
Found := Res.Issues * ColorRules;
for Issue in Found do
case Issue of
pvaiMissingOutputIntent:
Log.Add(' reachable uncalibrated device color, no PDF/A OutputIntent');
pvaiMissingIccProfile:
Log.Add(' no OutputIntent with a DestOutputProfile ICC stream');
pvaiMixedDeviceColorSpaces:
Log.Add(' RGB/CMYK use disagrees with the intent, or PDF/A-1 paints both');
pvaiBlendSpaceUndefined:
Log.Add(' transparent page without a blending color space');
end;
if Found = [] then
Log.Add(' device color and blending rules satisfied');
end;
pvaiMissingOutputIntent en pvaiMissingIccProfile verschijnen samen wanneer de tocht ongecalibreerde devicekleur bereikt en er geen PDF/A OutputIntent bestaat. pvaiMissingIccProfile op zichzelf betekent dat er een intent is maar zonder profiel, wat 6.2.2 niet als PDF/A-intent accepteert. pvaiMixedDeviceColorSpaces dekt zowel het PDF/A-1-mixverbod als een componentmismatch: ongecalibreerde DeviceRGB onder een intent met vier componenten, of DeviceCMYK onder een met drie. De set benoemt de regel in plaats van de pagina, dus in een lang of samengevoegd document vergelijkt u welke pagina's Default-entries opgeven en welke niet
Wanneer heeft een transparante pagina zijn eigen blending-ruimte nodig?
Een transparante pagina heeft alleen dan een eigen blending-kleurruimte nodig wanneer het document geen PDF/A OutputIntent heeft. ISO 19005-2 6.2.10 (6.2.9 in PDF/A-4) maakt de intent de default blending-kleurruimte in de zin van ISO 32000-1 §11.3.4; zonder intent moet elke pagina die transparantie bevat een Group dragen waarvan het attributen-dictionary (ISO 32000-1 Table 147) een CS bevat. Die CS wordt ook afgerekend op 6.2.4, dus een paginagroep met /DeviceCMYK onder een sRGB-intent wordt gemeld alsof hij ontbreekt, en PDFium Component geeft pvaiBlendSpaceUndefined voor allebei; CalRGB of een ICCBased-groepsruimte heeft die afhankelijkheid niet. PDF/A-1 komt bij deze vraag niet, omdat ISO 19005-1 6.4 transparantie volledig uitsluit
Het lastige is de formulering bevat transparantie. Bijlage A van ISO 19005-2 is normatief en toetst vanuit de pagina naar buiten; een telling door het hele bestand van /SMask-sleutels of /ca-waarden beantwoordt een andere vraag. Zoektochten op bytes botsen ook elders op transparantiesyntax: /S /Trans, de verboden transitie-actie, gaat aan elke /S /Transparency-groep vooraf, en /Screen is zowel een verboden annotatiesubtype als een standaard blend mode, dus een naam zegt niets totdat hij met zijn sleutel is gepaard. Volgend Bijlage A behandelt PDFium Component een pagina als transparant wanneer een van deze ervan bereikt wordt:
- een ExtGState die de content met
gsselecteert en die een soft mask-dictionary heeft, eencaofCAonder 1, of een blend mode anders danNormal; één die alleen gedeclareerd en nooit geselecteerd wordt telt niet mee - een Form XObject aangeroepen met
Dowaarvan/Groupop/S /Transparencystaat, of waarvan de eigen content aan een van deze voorwaarden voldoet; een tiling pattern wordt als form beoordeeld - een image XObject met een
SMask-stream of eenSMaskInData-waarde boven 0 - een glyph-beschrijving van een Type 3-font waarmee de pagina tekst toont, beoordeeld als een form
- een annotatie-appearancestream, elke widgetstate inbegrepen, en een blend mode op het annotatiedictionary zelf
Groepen voeden ook terug in de deviceregel voor kleur, en hier corrigeerde het corpus ons. De veraPDF-suite voor 6.2.4.3 bevat PDF/A-4-bestanden zonder enige OutputIntent die device-RGB tekenen en naar verwachting slagen, omdat de /Group van elke pagina een gecalibreerde CS benoemt. Wij gingen ervan uit dat alleen geïsoleerde groepen konden calibreren, omdat een niet-geïsoleerde groep in zijn achtergrond componeert, en dat was fout voor paginagroepen: Table 147 merkt op dat een pagina die direct op het uitvoermedium wordt afgedrukt effectief geïsoleerd is, ongeacht I, dus zijn CS wordt gerespecteerd. Op een Form XObject of annotatie-appearance beslist de vlag wel; de suite heeft een slaag- en een zakbestand die alleen in /I true verschillen. DeviceGray haalt geen calibratie uit een groep, want 6.2.4.3 vraagt om DefaultGray of een intent, en een groep waarvan de CS een device-ruimte is moet zelf gecalibreerd worden. PDFium Component laat daarom een paginagroep calibreren wat zijn /I ook zegt, laat een form- of appearancegroep alleen calibreren wanneer geïsoleerd, houdt grijs buiten groepscalibratie en toetst toch een device-ruimte die een groep benoemt
Eén OutputIntent in plaats van een groep op elke pagina
Schrijft uw eigen code het archief, begin dan met een OutputIntent op documentniveau. Eén catalogentry calibreert DeviceGray overal, dekt de overeenkomende device-ruimte op elke pagina en is de default blending-ruimte voor elke transparante pagina. Paginagroepen en Default-entries gelden elk voor één resourcedictionary, en de pagina die een latere merge zonder hen toevoegt is degene die zakt. PDF 2.0 voegt OutputIntents toe aan het paginaobject (ISO 32000-2 §7.7.3.3 en §14.11.5); PDFium Component accepteert die intent op paginaniveau voor PDF/A-4 wanneer de catalog geen heeft, terwijl parts 1 tot 3, gebouwd op PDF 1.4 tot 1.7, alleen naar de catalog kijken. Voor RGB-content voegt SaveAsPdfAToStream een catalogintent toe gebouwd op het ingebedde sRGB ICC-profiel van de PDF/A-writer, en het valideren van de uitvoer laat zien of de content werkelijk alleen RGB was
uses
System.SysUtils, System.Classes, PDFium, FPdfPdfa;
function ArchiveWithSrgbIntent(const InFile, OutFile: string;
out Remaining: TPdfAValidationIssues): Boolean;
var
Pdf: TPdf;
Opts: TPdfASaveOptions;
Output: TMemoryStream;
Check: TPdfAValidationResult;
begin
Result := False;
Remaining := [];
Pdf := TPdf.Create(nil);
Output := TMemoryStream.Create;
try
Pdf.FileName := InFile;
Pdf.Active := True;
if not Pdf.Active then
Exit; // het bestand kon niet worden geopend
Opts := TPdfASaveOptions.Default;
Opts.Conformance := pac2b; // PDF/A-1 zou de transparantie ronduit verbieden
// IccProfileData blijft leeg: het ingebouwde sRGB IEC61966-2.1-profiel wordt gebruikt
if not Pdf.SaveAsPdfAToStream(Output, Opts) then
Exit;
Check := ValidatePdfACompliance(Output);
Remaining := Check.Issues;
// Verwacht bij content met alleen RGB: pvaiMissingOutputIntent en
// pvaiBlendSpaceUndefined zijn verdwenen. pvaiMixedDeviceColorSpaces betekent
// nu dat een bereikbaar pad DeviceCMYK tekent dat geen DefaultCMYK calibreert.
if Check.IsCompliant then
begin
Output.SaveToFile(OutFile);
Result := True;
end;
finally
Output.Free;
Pdf.Free;
end;
end;
Een pvaiMixedDeviceColorSpaces die de sRGB-intent overleeft is de tocht die DeviceCMYK meldt op een bereikbaar pad, en dat document heeft een DefaultCMYK-mapping nodig op de pagina's die hem tekenen, of een CMYK-outputprofiel, voordat PDFium Component hem als PDF/A-2b accepteert