veraPDF signale ISO 19005-1 6.2.3.3 sur un fichier qui ne dessine jamais de RGB, qualifie de non calibré un re f nu, ou fait échouer la page 2 alors qu'une page 1 identique passe. Le PDF/A juge ces règles à ce que chaque page peint, si bien que le validateur PDF/A de PDFium Component pour Delphi remonte chaque page jusqu'aux formulaires, motifs, glyphes et annotations avant de statuer sur la couleur et la transparence
Ce qu'exigent réellement 6.2.3.3 et 6.2.4.3
ISO 19005-1 6.2.3.3 range trois règles indépendantes dans un seul paragraphe. Un fichier conforme peut utiliser DeviceRGB ou DeviceCMYK mais ne doit pas utiliser les deux ; si un espace de couleurs non calibré quelconque est utilisé, le fichier doit contenir un OutputIntent PDF/A-1 ; et DeviceRGB n'est admis qu'avec une intention dont le profil est RGB, DeviceCMYK qu'avec une CMYK. DeviceGray est laissé hors de cette liste parce que la clause enchaîne sur la conversion du gris sous l'une ou l'autre intention. L'intention elle-même est optionnelle : 6.2.2 dit qu'un fichier peut en spécifier une, et ne compte qu'une entrée OutputIntents avec /S /GTS_PDFA1 et un flux de profil ICC valide dans /DestOutputProfile. Aussi un vérificateur qui exige une intention de chaque fichier rejette des documents conformes qui ne peignent jamais de couleur device. La Partie 1 ne mentionne ni DefaultRGB ni DefaultCMYK, pourtant une couleur remappée au travers d'eux est rendue dans un espace à base CIE (ISO 32000-1 §8.6.5.6), ce qui satisfait l'exigence d'indépendance device de 6.2.3.1 ; la suite de tests veraPDF pour 6.2.3.3 la traite comme calibrée, et PDFium Component lit la clause de la même façon. L'interdiction de mélange se tient à part : un fichier PDF/A-1 qui peint à la fois du RGB et du CMYK échoue même quand des entrées Default calibrent les deux. ISO 19005-2 6.2.4.3 lève cette interdiction et calibre chaque espace à ses propres conditions, comme le montre la colonne de droite ci-dessous, si bien que PDFium Component exécute un scan pour chaque partie et n'applique la vérification de mélange qu'aux seules déclarations PDF/A-1
| Espace device peint | PDF/A-1 (ISO 19005-1 6.2.3.3) | PDF/A-2 et ultérieurs (ISO 19005-2 6.2.4.3) |
|---|---|---|
| DeviceRGB | DefaultRGB dans la portée ou une intention RGB ; pas à côté de DeviceCMYK | DefaultRGB dans la portée, ou un OutputIntent RGB |
| DeviceCMYK | DefaultCMYK dans la portée ou une intention CMYK ; pas à côté de DeviceRGB | DefaultCMYK dans la portée, ou un OutputIntent CMYK |
| DeviceGray | DefaultGray dans la portée, ou n'importe quel OutputIntent PDF/A-1 | DefaultGray dans la portée, ou n'importe quel OutputIntent PDF/A |
Qu'est-ce qui compte comme utilisation d'un espace de couleurs ?
Utiliser un espace de couleurs signifie peindre avec lui sur un tracé qu'un lecteur rendra. Le déclarer ne suffit pas. La suite veraPDF fait la démonstration avec un fichier qui passe 6.2.3.3 : un Form XObject nommé pose du CMYK avec K et k, se trouve dans le dictionnaire de ressources de la page, n'est jamais référencé depuis le contenu de page, et l'OutputIntent du fichier est RGB. Une recherche des noms de couleurs device sur tout le fichier fait échouer ce fichier, et rate un autre qui ne peint que du DeviceRGB sous une intention CMYK, où aucun couple de noms n'entre en conflit. PDFium Component parcourt le graphe de dessin à la place, sur la base de son scanner PDF/A de préflight au niveau octet. Depuis chaque page, la marche compte la couleur peinte par :
- les flux de contenu de page, et chaque Form XObject qu'ils invoquent avec
Do, formulaires imbriqués compris - un motif sélectionné avec
scnouSCN, lu avec lesResourcesdu motif lui-même - les
CharProcsd'une police Type 3 sélectionnée avecTf - les image XObjects et les images en ligne, d'après l'espace de couleurs que leur propre dictionnaire nomme
- les flux d'apparence d'annotations, peints par-dessus la page ; quand le
/AP /Nd'un widget est un dictionnaire d'états, chaque état compte, car basculer le champ peint celui que le/ASn'avait pas sélectionné
La moitié la plus subtile de l'accessibilité est la couleur que le contenu ne nomme jamais. q 0 0 10 10 re f Q ne contient aucun opérateur de couleur. Il peint quand même. L'espace de couleurs initial de l'état graphique est DeviceGray (ISO 32000-1 Table 52), si bien que le remplissage est du noir DeviceGray, non calibré sous chaque partie tant qu'il n'existe ni OutputIntent PDF/A ni DefaultGray. Le scan suit donc si quelque chose a déjà choisi une couleur : rg, k, g et leurs formes de tracé sélectionnent un espace device, cs et CS sélectionnent ce qu'ils nomment, et un opérateur de remplissage, de tracé ou de texte atteint avant tout choix enregistre DeviceGray. /CS0 cs 1 0 0 /P0 scn a déjà choisi un espace, si bien que ce scn n'est pas du gris
Les images en ligne amènent leur espace de couleurs et leurs échantillons bruts dans le flux de contenu lui-même, et un scanner doit lire les deux avec soin. Le /CS peut être une abréviation (G, RGB, CMYK, I) ou un nom de ressource tel qu'un qui se résout en [/Indexed /DeviceRGB 255 13 0 R], dont la base compte ; et les octets entre ID et EI sont du binaire arbitraire, si bien que EI ne termine l'image qu'entre des blancs, sinon un rg à l'intérieur d'échantillons compressés devient un opérateur fantôme
% page 1 : DefaultRGB dans la portée, et un XObject jamais invoqué
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
% page 2 : le même flux de contenu, pas de sous-dictionnaire 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
Chaque symptôme de l'ouverture découle de ce fragment. /Fm0 ne rencontre jamais de Do, si bien que son k est sans importance. Le re f nu sur les deux pages est du DeviceGray sans rien pour le calibrer. Le rg de la page 1 est couvert par le DefaultRGB des ressources avec lesquelles la page 1 peint ; la page 2 exécute le flux identique contre des ressources qui n'ont pas la correspondance, si bien que les mêmes octets sont non calibrés là. Attendu pour une déclaration PDF/A-1b : pvaiMissingOutputIntent avec pvaiMissingIccProfile, poussés par le RGB de la page 2 et le gris des deux pages. Le formulaire ne contribue rien ; invoqué, son CMYK ajouterait par-dessus l'interdiction de mélange PDF/A-1
Les espaces de couleurs Default appartiennent au dictionnaire de ressources qui peint
Les correspondances Default sont recherchées dans le sous-dictionnaire ColorSpace du dictionnaire de ressources courant (ISO 32000-1 §8.6.5.6), ce qui les rend exactement aussi locales que les ressources elles-mêmes ; un document n'a pas de défaut global. Un image XObject n'a pas de Resources propre, si bien qu'une image dont le dictionnaire dit /ColorSpace /DeviceCMYK est calibrée par le DefaultCMYK de la page ou du formulaire qui la dessine, et la même image dessinée depuis deux endroits peut être calibrée en un et pas en l'autre. Les Form XObjects, les motifs de pavage et les procédures de glyphes Type 3 portent leurs propres Resources, si bien que le DefaultCMYK d'une page ne pénètre pas à l'intérieur d'eux, tandis qu'une correspondance dans leur propre dictionnaire oui. PDFium Component délimite la portée des correspondances de la même façon. Le verdict revient sous la forme d'un enregistrement TPdfAValidationResult : la Conformance détectée plus un ensemble Issues. C'est assez pour trier un dossier
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); // lit depuis la position 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 et pvaiMissingIccProfile apparaissent ensemble quand la marche atteint de la couleur device non calibrée et qu'aucun OutputIntent PDF/A n'existe. pvaiMissingIccProfile seul signifie qu'une intention existe mais ne porte aucun profil, ce que 6.2.2 n'accepte pas comme intention PDF/A. pvaiMixedDeviceColorSpaces couvre à la fois l'interdiction de mélange PDF/A-1 et un décalage de composantes : du DeviceRGB non calibré sous une intention à quatre composantes, ou du DeviceCMYK sous une à trois. L'ensemble nomme la règle plutôt que la page, si bien que dans un document long ou fusionné, comparez quelles pages déclarent des entrées Default et lesquelles ne le font pas
Quand une page transparente demande-t-elle son propre espace de fusion ?
Une page transparente ne demande son propre espace de couleurs de fusion que quand le document n'a aucun OutputIntent PDF/A. ISO 19005-2 6.2.10 (6.2.9 en PDF/A-4) fait de l'intention l'espace de couleurs de fusion par défaut au sens de ISO 32000-1 §11.3.4 ; sans intention, chaque page contenant de la transparence doit porter un Group dont le dictionnaire d'attributs (ISO 32000-1 Table 147) inclut un CS. Ce CS est aussi tenu à 6.2.4, si bien qu'un groupe de page /DeviceCMYK sous une intention sRGB est rapporté comme un manquant, et PDFium Component lève pvaiBlendSpaceUndefined pour les deux ; un espace de groupe CalRGB ou ICCBased n'a pas cette dépendance. Le PDF/A-1 n'atteint pas cette question, parce que ISO 19005-1 6.4 écarte la transparence entièrement
La partie dure est l'expression contient de la transparence. L'annexe A de ISO 19005-2 est normative et teste depuis la page vers l'extérieur ; un comptage des clés /SMask ou des valeurs /ca sur tout le fichier répond à une autre question. Les recherches d'octets butent aussi sur la syntaxe de transparence ailleurs : /S /Trans, l'action de transition interdite, préfixe chaque groupe /S /Transparency, et /Screen est à la fois un sous-type d'annotation interdit et un mode de fusion standard, si bien qu'un nom ne signifie rien tant qu'il n'est pas apparié à sa clé. En suivant l'annexe A, PDFium Component traite une page comme transparente quand l'un de ceux-ci est atteint depuis elle :
- un ExtGState que le contenu sélectionne avec
gsqui porte un dictionnaire de soft mask, uncaouCAsous 1, ou un mode de fusion autre queNormal; un ExtGState déclaré mais jamais sélectionné ne compte pas - un Form XObject invoqué avec
Dodont le/Groupporte/S /Transparency, ou dont le contenu propre remplit une de ces conditions ; un motif de pavage est jugé comme un formulaire - un image XObject avec un flux
SMaskou une valeurSMaskInDataau-dessus de 0 - une description de glyphe d'une police Type 3 avec laquelle la page affiche du texte, jugée comme un formulaire
- un flux d'apparence d'annotation, chaque état de widget compris, et un mode de fusion sur le dictionnaire d'annotation lui-même
Les groupes nourrissent aussi la règle de la couleur device en retour, et ici le corpus nous a corrigés. La suite veraPDF pour 6.2.4.3 contient des fichiers PDF/A-4 sans aucun OutputIntent qui peignent du RGB device et qui doivent passer, parce que le /Group de chaque page nomme un CS calibré. Nous supposions que seuls les groupes isolés pouvaient calibrer, puisqu'un groupe non isolé se compose dans son arrière-plan, et c'était faux pour les groupes de page : la Table 147 note qu'une page imposée directement sur le support de sortie est effectivement isolée quel que soit I, si bien que son CS est honoré. Sur un Form XObject ou une apparence d'annotation le drapeau décide bien ; la suite a un fichier passant et un fichier échouant qui ne diffèrent que par /I true. DeviceGray ne prend aucune calibration d'un groupe, parce que 6.2.4.3 demande DefaultGray ou une intention, et un groupe dont le CS est un espace device a besoin d'être calibré lui-même. PDFium Component laisse donc un groupe de page calibrer quel que soit ce que dit son /I, laisse un groupe de formulaire ou d'apparence calibrer seulement quand il est isolé, tient le gris hors de la calibration par groupe, et vérifie quand même un espace device qu'un groupe nomme
Un OutputIntent au lieu d'un groupe sur chaque page
Si votre propre code écrit l'archive, commencez par un OutputIntent PDF/A au niveau du document. Une entrée de catalog calibre DeviceGray partout, couvre l'espace device correspondant sur chaque page, et est l'espace de fusion par défaut de chaque page transparente. Les groupes de page et les entrées Default ont chacun une portée d'un dictionnaire de ressources, et la page qu'une fusion ultérieure ajoute sans eux est celle qui échoue. PDF 2.0 ajoute OutputIntents à l'objet page (ISO 32000-2 §7.7.3.3 et §14.11.5) ; PDFium Component accepte cette intention au niveau page pour le PDF/A-4 quand le catalog n'en a pas, tandis que les parties 1 à 3, bâties sur PDF 1.4 à 1.7, ne regardent que le catalog. Pour du contenu RGB, SaveAsPdfAToStream ajoute une intention de catalog bâtie sur le profil ICC sRGB embarqué de l'écrivain PDF/A, et la validation de la sortie montre si le contenu était vraiment RGB seulement
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; // le fichier n'a pas pu être ouvert
Opts := TPdfASaveOptions.Default;
Opts.Conformance := pac2b; // le PDF/A-1 interdirait la transparence carrément
// IccProfileData reste vide : le profil sRGB IEC61966-2.1 intégré est utilisé
if not Pdf.SaveAsPdfAToStream(Output, Opts) then
Exit;
Check := ValidatePdfACompliance(Output);
Remaining := Check.Issues;
// Attendu pour un contenu RGB seul : pvaiMissingOutputIntent et
// pvaiBlendSpaceUndefined ont disparu. pvaiMixedDeviceColorSpaces signifie
// désormais qu'un chemin accessible peint du DeviceCMYK qu'aucun DefaultCMYK ne calibre.
if Check.IsCompliant then
begin
Output.SaveToFile(OutFile);
Result := True;
end;
finally
Output.Free;
Pdf.Free;
end;
end;
Un pvaiMixedDeviceColorSpaces qui survit à l'intention sRGB est la marche qui signale du DeviceCMYK sur un chemin accessible, et ce document demande une correspondance DefaultCMYK sur les pages qui le peignent, ou un profil de sortie CMYK, avant que PDFium Component ne l'accepte comme PDF/A-2b