veraPDF segnala ISO 19005-1 6.2.3.3 su un file che non disegna mai RGB, chiama non calibrato un re f nudo, o boccia la pagina 2 mentre una pagina 1 identica passa. Il PDF/A giudica quelle regole da ciò che ogni pagina dipinge, così il validatore PDF/A di PDFium Component per Delphi traccia ogni pagina dentro form, pattern, glifi e annotazioni prima di pronunciarsi su colore e trasparenza
Che cosa richiedono davvero 6.2.3.3 e 6.2.4.3
ISO 19005-1 6.2.3.3 impacchetta tre regole indipendenti in un solo paragrafo. Un file conforme può usare DeviceRGB o DeviceCMYK ma non deve usare entrambi; se viene usato qualsiasi spazio di colore non calibrato, il file deve contenere un OutputIntent PDF/A-1; e DeviceRGB è permesso solo con un intent il cui profilo è RGB, DeviceCMYK solo con uno CMYK. DeviceGray resta fuori da quella lista perché la clausola prosegue spiegando la conversione del grigio sotto entrambi gli intent. L'intent in sé è opzionale: 6.2.2 dice che un file può specificarne uno, e conta solo una voce OutputIntents con /S /GTS_PDFA1 e uno stream di profilo ICC valido in /DestOutputProfile. Così un controllo che esige un intent da ogni file boccia documenti conformi che non dipingono mai colore device. La Parte 1 non menziona DefaultRGB o DefaultCMYK, eppure un colore passato attraverso di loro viene disegnato in uno spazio basato su CIE (ISO 32000-1 §8.6.5.6), il che soddisfa la richiesta di indipendenza dal device di 6.2.3.1; la suite di test veraPDF per 6.2.3.3 lo tratta come calibrato, e PDFium Component legge la clausola allo stesso modo. Il divieto di miscelazione sta a parte: un file PDF/A-1 che dipinge sia RGB sia CMYK fallisce anche quando voci Default calibrano entrambi. ISO 19005-2 6.2.4.3 lascia cadere quel divieto e calibra ogni spazio per conto suo, come mostra la colonna di destra qui sotto, così PDFium Component esegue una scansione per ogni parte e applica il controllo di miscelazione alle sole dichiarazioni PDF/A-1
| Spazio device dipinto | PDF/A-1 (ISO 19005-1 6.2.3.3) | PDF/A-2 e successivi (ISO 19005-2 6.2.4.3) |
|---|---|---|
| DeviceRGB | DefaultRGB in ambito o un intent RGB; non insieme a DeviceCMYK | DefaultRGB in ambito, o un OutputIntent RGB |
| DeviceCMYK | DefaultCMYK in ambito o un intent CMYK; non insieme a DeviceRGB | DefaultCMYK in ambito, o un OutputIntent CMYK |
| DeviceGray | DefaultGray in ambito, o qualsiasi OutputIntent PDF/A-1 | DefaultGray in ambito, o qualsiasi OutputIntent PDF/A |
Che cosa conta come usare uno spazio di colore?
Usare uno spazio di colore significa dipingere con esso su un percorso che un lettore disegnerà. Dichiararlo non basta. La suite veraPDF lo dimostra con un file di pass per 6.2.3.3: un Form XObject nominato imposta CMYK con K e k, sta nel dizionario delle risorse della pagina, non viene mai referenziato dal contenuto di pagina, e l'OutputIntent del file è RGB. Una ricerca su tutto il file dei nomi di colore device boccia quel file, e non vede uno che dipinge solo DeviceRGB sotto un intent CMYK, dove nessun paio di nomi va in conflitto. PDFium Component attraversa invece il grafo di disegno, costruito sul suo scanner di preflight PDF/A a livello di byte. Da ogni pagina, la scansione conta il colore dipinto da:
- gli stream di contenuto di pagina, e ogni Form XObject che invocano con
Do, form annidate incluse - un pattern selezionato con
scnoSCN, letto con leResourcesproprie del pattern - i
CharProcsdi un font Type 3 selezionato conTf - image XObject e immagini inline, per lo spazio di colore che il loro dizionario nomina
- gli appearance stream delle annotazioni, dipinti sopra la pagina; quando
/AP /Ndi un widget è un dizionario di stati, ogni stato conta, perché commutare il campo dipinge quello che/ASnon aveva selezionato
La metà più sottile della raggiungibilità è il colore che il contenuto non nomina mai. q 0 0 10 10 re f Q non contiene alcun operatore di colore. Dipinge comunque. Lo spazio di colore iniziale dello stato grafico è DeviceGray (ISO 32000-1 Table 52), così il riempimento è nero DeviceGray, non calibrato sotto ogni parte a meno che esista un OutputIntent PDF/A o un DefaultGray. La scansione quindi tiene traccia di se qualcosa abbia già scelto un colore: rg, k, g e le loro forme di stroke selezionano uno spazio device, cs e CS selezionano ciò che nominano, e un operatore di riempimento, stroke o testo raggiunto prima di qualsiasi scelta registra DeviceGray. /CS0 cs 1 0 0 /P0 scn ha già scelto uno spazio, così quello scn non è grigio
Le immagini inline portano il loro spazio di colore e i loro campioni grezzi dentro lo stream di contenuto stesso, e uno scanner deve leggere entrambi con attenzione. La /CS può essere un'abbreviazione (G, RGB, CMYK, I) o un nome di risorsa come uno che risolve a [/Indexed /DeviceRGB 255 13 0 R], la cui base conta; e i byte tra ID ed EI sono binari arbitrari, così EI chiude l'immagine solo tra spazi bianchi, oppure un rg dentro campioni compressi diventa un operatore fantasma
% pagina 1: DefaultRGB in ambito, e un XObject che nessuno invoca
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: lo stesso content stream, nessun sottodizionario ColorSpace
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
Ogni sintomo dell'apertura cade fuori da questo frammento. /Fm0 non incontra mai un Do, così il suo k è irrilevante. Il re f nudo su entrambe le pagine è DeviceGray senza nulla che lo calibri. Il rg della pagina 1 è coperto dal DefaultRGB nelle risorse con cui la pagina 1 dipinge; la pagina 2 esegue lo stream identico contro risorse che non hanno la mappatura, così gli stessi byte sono lì non calibrati. Atteso per una dichiarazione PDF/A-1b: pvaiMissingOutputIntent con pvaiMissingIccProfile, guidati dal RGB della pagina 2 e dal grigio di entrambe le pagine. La form non contribuisce nulla; invocata, il suo CMYK aggiungerebbe sopra il divieto di miscelazione PDF/A-1
Gli spazi di colore Default appartengono al dizionario delle risorse che dipinge
Le mappature Default vengono cercate nel sottodizionario ColorSpace del dizionario delle risorse corrente (ISO 32000-1 §8.6.5.6), il che le rende esattamente locali quanto le risorse stesse; un documento non ha alcun default globale. Un image XObject non ha Resources proprie, così un'immagine il cui dizionario dice /ColorSpace /DeviceCMYK viene calibrata dal DefaultCMYK della pagina o della form che la disegna, e la stessa immagine disegnata da due posti può essere calibrata in uno e nell'altro no. Form XObject, pattern di tiling e procedure di glifi Type 3 portano le proprie Resources, così il DefaultCMYK di una pagina non arriva dentro di loro, mentre una mappatura nel loro dizionario sì. PDFium Component delimita le mappature allo stesso modo. Il verdetto torna come record TPdfAValidationResult: la Conformance rilevata più un insieme Issues. Basta per fare triage su una cartella
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); // legge dalla posizione 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 e pvaiMissingIccProfile appaiono insieme quando la scansione raggiunge colore device non calibrato e non esiste alcun OutputIntent PDF/A. pvaiMissingIccProfile da solo significa che un intent esiste ma non porta profilo, cosa che 6.2.2 non accetta come intent PDF/A. pvaiMixedDeviceColorSpaces copre sia il divieto di miscelazione PDF/A-1 sia una discrepanza di componenti: DeviceRGB non calibrato sotto un intent a quattro componenti, o DeviceCMYK sotto uno a tre componenti. L'insieme nomina la regola e non la pagina, così in un documento lungo o unito confrontate quali pagine dichiarano voci Default e quali no
Quando una pagina trasparente ha bisogno del suo spazio di fusione?
Una pagina trasparente ha bisogno del suo spazio di colore di fusione solo quando il documento non ha un OutputIntent PDF/A. ISO 19005-2 6.2.10 (6.2.9 in PDF/A-4) fa dell'intent lo spazio di colore di fusione predefinito nel senso di ISO 32000-1 §11.3.4; senza intent, ogni pagina che contiene trasparenza deve portare un Group il cui dizionario di attributi (ISO 32000-1 Table 147) includa CS. Quella CS è vincolata anche a 6.2.4, così un gruppo di pagina /DeviceCMYK sotto un intent sRGB viene riferito come uno mancante, e PDFium Component solleva pvaiBlendSpaceUndefined per entrambi; CalRGB o uno spazio di gruppo ICCBased non hanno questa dipendenza. Il PDF/A-1 non arriva a questa domanda, perché ISO 19005-1 6.4 esclude del tutto la trasparenza
La parte difficile è la frase contiene trasparenza. L'Allegato A di ISO 19005-2 è normativo e prova dalla pagina verso fuori; un conteggio su tutto il file delle chiavi /SMask o dei valori /ca risponde a un'altra domanda. Le ricerche di byte collidono anche con la sintassi di trasparenza altrove: /S /Trans, l'azione di transizione vietata, fa da prefisso a ogni gruppo /S /Transparency, e /Screen è sia un sottotipo di annotazione vietato sia una modalità di fusione standard, così un nome non significa nulla finché non è abbinato alla sua chiave. Seguendo l'Allegato A, PDFium Component tratta una pagina come trasparente quando una di queste viene raggiunta da essa:
- un ExtGState che il contenuto seleziona con
gsche ha un dizionario di soft mask, unacaoCAsotto 1, o una modalità di fusione diversa daNormal; uno dichiarato ma mai selezionato non conta - un Form XObject invocato con
Doil cui/Groupha/S /Transparency, o il cui contenuto proprio soddisfa una di queste condizioni; un pattern di tiling viene giudicato come una form - un image XObject con uno stream
SMasko un valoreSMaskInDatasopra 0 - una descrizione di glifo di un font Type 3 con cui la pagina mostra testo, giudicata come una form
- un appearance stream di annotazione, ogni stato di widget incluso, e una modalità di fusione sul dizionario di annotazione stesso
I gruppi rientrano anche nella regola del colore device, e qui il corpus ci ha corretti. La suite veraPDF per 6.2.4.3 contiene file PDF/A-4 senza alcun OutputIntent che dipingono RGB device e sono attesi in pass, perché il /Group di ogni pagina nomina una CS calibrata. Assumevamo che solo i gruppi isolati potessero calibrare, dato che un gruppo non isolato si compone nel suo sfondo, e per i gruppi di pagina era sbagliato: Table 147 nota che una pagina imposta direttamente sul supporto di output è di fatto isolata a prescindere da I, così la sua CS viene rispettata. Su un appearance di Form XObject o di annotazione il flag lo decide davvero; la suite ha un file di pass e uno di fail che differiscono solo per /I true. DeviceGray non prende alcuna calibrazione da un gruppo, perché 6.2.4.3 chiede DefaultGray o un intent, e un gruppo la cui CS è uno spazio device ha bisogno di essere calibrato a sua volta. PDFium Component quindi lascia che un gruppo di pagina calibri a prescindere da ciò che dice il suo /I, lascia che un gruppo di form o di appearance calibri solo quando isolato, tiene il grigio fuori dalla calibrazione dei gruppi, e controlla comunque uno spazio device che un gruppo nomina
Un OutputIntent invece di un gruppo su ogni pagina
Se il vostro codice scrive l'archivio, partite con un OutputIntent PDF/A a livello di documento. Una voce di catalogo calibra DeviceGray ovunque, copre lo spazio device corrispondente su ogni pagina, ed è lo spazio di fusione predefinito per ogni pagina trasparente. I gruppi di pagina e le voci Default hanno l'ambito di un dizionario di risorse ciascuno, e la pagina che una fusione successiva aggiunge senza di loro è quella che fallisce. PDF 2.0 aggiunge OutputIntents all'oggetto pagina (ISO 32000-2 §7.7.3.3 e §14.11.5); PDFium Component accetta quell'intent a livello di pagina per PDF/A-4 quando il catalogo non ne ha, mentre le parti 1 a 3, costruite su PDF 1.4 a 1.7, guardano solo il catalogo. Per contenuto RGB, SaveAsPdfAToStream aggiunge un intent di catalogo costruito sul profilo ICC sRGB incorporato dello scrittore PDF/A, e validare l'output mostra se il contenuto era davvero solo RGB
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; // il file non poteva essere aperto
Opts := TPdfASaveOptions.Default;
Opts.Conformance := pac2b; // PDF/A-1 vieterebbe la trasparenza del tutto
// IccProfileData resta vuoto: viene usato il profilo sRGB IEC61966-2.1 interno
if not Pdf.SaveAsPdfAToStream(Output, Opts) then
Exit;
Check := ValidatePdfACompliance(Output);
Remaining := Check.Issues;
// Atteso per contenuto solo RGB: pvaiMissingOutputIntent e
// pvaiBlendSpaceUndefined sono spariti. pvaiMixedDeviceColorSpaces ora indica
// che un percorso raggiungibile dipinge DeviceCMYK che nessun DefaultCMYK calibra.
if Check.IsCompliant then
begin
Output.SaveToFile(OutFile);
Result := True;
end;
finally
Output.Free;
Pdf.Free;
end;
end;
Una pvaiMixedDeviceColorSpaces che sopravvive all'intent sRGB è la scansione che riferisce DeviceCMYK su un percorso raggiungibile, e quel documento ha bisogno di una mappatura DefaultCMYK sulle pagine che lo dipingono, o di un profilo di output CMYK, prima che PDFium Component lo accetti come PDF/A-2b