Module optionnel · pdftoolkit/pdf-codecs 0.1.0

English | Français

PDFToolkit\Codecs\Jbig2\Jbig2Decoder implémente Decoder pour une image monochrome. Il accepte les segments embarqués PDF, des segments globaux facultatifs déjà décodés, ainsi que les fichiers T.88 d'une seule page en organisation séquentielle ou à accès aléatoire. Le résultat contient un composant Gray non signé de 1 bit, bit fort en premier, avec des lignes alignées sur un octet : 0 est noir, 1 est blanc. Les bits inutilisés du dernier octet de chaque ligne valent zéro. La polarité interne T.88 est inversée uniquement à la sortie publique.

use PDFToolkit\Codecs\Codec;
use PDFToolkit\Codecs\DecodeLimits;
use PDFToolkit\Codecs\DecodeRequest;
use PDFToolkit\Codecs\Jbig2\Jbig2Decoder;

$image = (new Jbig2Decoder(new DecodeLimits(maxPixels: 4_000_000)))
    ->decode(new DecodeRequest(Codec::Jbig2, $encoded, globals: $decodedGlobals));

L'appelant fournit les octets. Le package ne résout pas les références PDF, ne déchiffre pas les flux, n'applique pas leurs filtres précédents, n'ouvre aucun fichier et n'exécute aucun processus. Ces responsabilités appartiennent à l'adaptateur Reader. Un numéro de page supérieur à un peut désigner la seule page extraite d'un fichier autonome ; l'accepter ne certifie pas la règle plus stricte d'association de page du format embarqué PDF 2.0.

Matrice d'implémentation et de preuves

Référence : ITU-T T.88 (08/2018), ISO/IEC 14492:2019, PDF officiel. Les pages physiques comptent toutes les pages depuis un ; les pages imprimées sont inférieures de 12. Les tests sont dans tests/Jbig2 et le manifeste conserve les empreintes des sources et des échantillons, les mécanismes exercés et la preuve exigée. Cette matrice décrit les mécanismes implémentés ; elle ne constitue pas une certification universelle de tout flux possible.

Mécanisme Clauses / pages physiques Objets Preuves
Organisations séquentielle, aléatoire et embarquée ; références globales/pages, rétention, profondeur, nombres courts/longs de références 7.2–7.3, 60–67 ; annexe D SegmentReader, Segment, Jbig2Session Pages/globaux de l'annexe H ; régressions d'organisation, références et cadrage invalide
Bitmaps génériques arithmétiques, modèles 0–3, coordonnées adaptatives et prédiction de ligne 6.2.5, 27–31 GenericBitmapDecoder, ArithmeticContext Quatre modèles avec/sans prédiction, AT déplacés/superposés ; comparaisons indépendantes jbig2enc → libjbig2dec
Modèle étendu à 12 pixels adaptatifs Figure 3b, 28 ; 7.4.6.2–3, 85–86 GenericBitmapDecoder, Jbig2Session Vecteur normatif encodé par MQ indépendant et revue croisée des positions fixes/nominales ; limite d'oracle décrite ci-dessous
MMR générique, collectif et motifs ; délimitation des plans de gris 6.2.6, 32 ; annexe C MmrBitmapDecoder, MmrRowReader, MmrCodes Bitmaps MMR/motifs/tramés de l'annexe H, tailles connues/inconnues et EOFB
Raffinement générique, modèles 0/1, décalages de référence, prédiction typique, références intermédiaires/tampon de page 6.3, 33–36 ; 7.4.7, 87–89 GenericBitmapDecoder, RegionBitmap Encodeur MQ indépendant ; libjbig2dec sur tampon de page, Poppler sur régions intermédiaires ; vecteurs normatifs transport/prédiction
Texte arithmétique/Huffman, bandes, quatre coins, transposition, OR/AND/XOR/XNOR, raffinement 6.4, 37–45 ; 7.4.3, 71–80 TextRegionDecoder, TextParameters 32 combinaisons coins/transposition/opérateurs, annexe H, raffinement Huffman vérifié par Poppler
Symboles directs arithmétiques, collectifs Huffman bruts/MMR, raffinement simple et agrégation de plusieurs instances 6.5, 45–52 ; 7.4.2, 67–71 SymbolDictionaryDecoder Annexe H, collectif brut/table personnalisée, agrégation et raffinement arithmétiques/Huffman
Conservation des contextes bitmap GB/GR avec nouveaux contextes entiers 7.4.2.2, 70 ; E.3.7–8 ArithmeticStates, ArithmeticContext, SymbolDictionary Encodeur redémarré avec statistiques conservées ; deux branches copient le même dictionnaire ; revue normative croisée
Tramés/motifs arithmétiques/MMR, modèles 0–3, plans Gray-vers-binaire, masques de saut, origine signée, cinq opérateurs et deux pixels par défaut 6.6–6.7, 53–59 ; 7.4.4–5, 81–84 ; annexe C HalftoneDecoder, PatternDictionary, Bitmap 80 combinaisons modèle/saut/opérateur/défaut et annexe H ; oracle libjbig2dec sur défaut 0, comparaisons normatives explicites sur défaut 1
Tables Huffman B.1–B.15, tables canoniques personnalisées, tables d'identifiants, compatibilité OOB 7.4.13, 92 ; annexe B StandardTables, HuffmanTable, HuffmanSelection Hauteur personnalisée, agrégats Huffman, rejet de préfixes dupliqués/OOB incohérent/tables inutilisées
Défauts/combinaison de page, bandes et hauteurs inconnues, régions génériques de longueur inconnue, métadonnées/extensions facultatives 7.4.8–14, 89–93 Jbig2Session, SegmentReader Bandes, longueurs inconnues arithmétiques/MMR, budget cumulé des métadonnées, rejet des extensions nécessaires inconnues

Le §7.4.6.3 indique «32-byte» dans sa prose, mais sa figure 50 et ses champs explicites énumèrent les octets 0 à 23, soit douze paires. L'implémentation utilise ces 24 octets. L'identité des bits du contexte reste liée au modèle nominal lorsque les pixels adaptatifs bougent ou se superposent, conformément au §6.2.5.7.

Le §6.2.6 interdit expressément les codes d'extension T.6, dont le mode non comprimé, dans le profil MMR de T.88. Le filtre CCITT séparé du Reader peut accepter ce mode ; JBIG2 le rejette. Le remplissage d'alignement MMR est ignoré comme prescrit. EOFB est obligatoire pour les plans de tramés et le chemin MMR de longueur inconnue, facultatif lorsque le nombre d'octets comprimés donne la frontière.

Périmètre explicite et bornes

Les extensions/palettes colorées T.88, les requêtes contenant plusieurs pages et les extensions nécessaires inconnues lèvent UnsupportedFeature. Elles ne sont pas transformées silencieusement en noir et blanc. Les extensions facultatives et déclarations de profils n'altèrent pas les pixels ; leurs octets partagent un budget cumulé de métadonnées. Les champs réservés/incohérents, références invalides, contextes conservés incompatibles, codes/tables incorrects et cadrages tronqués lèvent MalformedImage. Un dépassement de ressources lève ResourceLimit.

Un nouveau DecodeBudget couvre les octets encodés globaux compris, les dimensions/pixels, les octets de sortie, les allocations cumulées, segments/références, profondeur et travail. Dictionnaires globaux, page, régions intermédiaires, raffinements et copies de contextes partagent ces bornes. Les bitmaps sont compactés ; un glyphe intermédiaire peut être vide, mais l'image rendue possède des dimensions positives. Cette comptabilité n'est pas une limite mémoire du processus PHP ; l'application peut aussi imposer mémoire et durée au processus.

Le décodeur reconstruit l'image encodée. Il ne peut pas détecter qu'un encodeur JBIG2 avec perte a remplacé un glyphe avant de produire ces octets.

Validation et limites des oracles indépendants

php vendor/bin/phpunit tests/Jbig2
python tools/validate_jbig2.py --php php --report _build/jbig2-validation.json

L'oracle nécessite Python avec pypdf et Pillow, libjbig2dec.so.0 version 0.20, et Poppler pdfimages (--pdfimages accepte un exécutable explicite). Poppler 22.12 et 26.10 ont été contrôlés. Le chemin du rapport est libre ; les PDF/PNG adjacents conservent les octets des régions transmis à Poppler. Seuls les contrôles de transport fin-de-page/fin-de-fichier sont retirés lors de leur inclusion dans une image PDF.

Le manifeste comporte 145 vecteurs : 92 exigent la sortie exacte de libjbig2dec, 8 celle de Poppler, et 45 sont explicitement des vecteurs normatifs, pas des confirmations par décodeur indépendant. PHP doit reproduire chaque dimension et chaque empreinte des échantillons. Les résultats des deux moteurs restent visibles, même quand une limite connue ne constitue pas la preuve exigée. independentCoverageComplete reste donc faux.

Limites constatées :

  • libjbig2dec 0.20 rejette les régions génériques intermédiaires et contextes conservés, décode incorrectement des raffinements/agrégations Huffman que Poppler reproduit exactement, et ignore le bit 4 du modèle étendu de 2018.
  • Pour HDEFPIXEL=1, libjbig2dec 0.20 remplit le bitmap de tramé avec l'octet 0x01 (jbig2_halftone.c), alors que chaque pixel doit valoir 1 (0xff). Les variantes correspondantes avec défaut 0 sont comparées indépendamment ; celles avec défaut 1 ont aussi une revue normative du remplissage, du découpage et des cinq opérateurs.
  • Poppler diverge sur la prédiction du raffinement et les contextes conservés. Les vecteurs de prédiction équivalents utilisant le tampon de page concordent avec libjbig2dec. Aucune tolérance de pixels n'est élargie pour masquer ces différences.
  • Les petits fichiers TT2–TT7 du ZIP officiel 2018 comportent des références absentes, des séries d'export incohérentes ou du MMR endommagé, confirmés séparément par libjbig2dec. Ils ne sont pas installés comme références valides. Les grands TT9/TT10 concordaient exactement avec leurs BMP officiels et libjbig2dec pendant le développement ; la séquence compacte durable provient directement de l'annexe H.

Les vecteurs synthétiques se reconstruisent avec l'encodeur arithmétique indépendant jbig2enc, Apache-2.0, révision exacte indiquée ci-dessous. Cet encodeur sert uniquement aux tests ; il n'est pas lié au package PHP.

# jbig2enc 4553595aa094cad7d55c4efc9657ea31db23c742
c++ -O2 -I /chemin/jbig2enc/src tools/jbig2_encoder.cpp -o /chemin/jbig2-encoder
python tools/generate_jbig2.py --encoder /chemin/jbig2-encoder

Le générateur définit les dispositions et pixels attendus indépendamment du PHP. L'encodeur MQ produit les octets comprimés ; libjbig2dec/Poppler fournissent les comparaisons de décodage séparées. La provenance exacte figure dans tests/Jbig2/Fixtures/README.md et provenance.json.

Source de ce guide au commit documenté ↗