Module optionnel · pdftoolkit/pdf-codecs 0.1.0

English

Jpeg2000\Jpeg2000Decoder décode une image JP2/JPX ou un codestream JPEG 2000 brut à partir des octets fournis. Il renvoie les plans de composantes et leurs métadonnées couleur. Il n’ouvre aucun fichier, ne récupère aucun fragment externe, ne lance aucun processus et n’effectue ni gestion couleur ni rendu PDF. PhpDecoder lui transmet les requêtes Codec::Jpeg2000.

use PDFToolkit\Codecs\Codec;
use PDFToolkit\Codecs\DecodeLimits;
use PDFToolkit\Codecs\DecodeRequest;
use PDFToolkit\Codecs\Jpeg2000\Jpeg2000Decoder;

$decoder = new Jpeg2000Decoder(new DecodeLimits(
    maxInputBytes: 8 * 1024 * 1024,
    maxOutputBytes: 16 * 1024 * 1024,
    maxPixels: 4_000_000,
    maxWork: 40_000_000,
));
$image = $decoder->decode(new DecodeRequest(Codec::Jpeg2000, $encodedBytes));
$premierEchantillon = $image->components[0]->sample(0, 0);

Chaque appel possède ses en-têtes, ses contextes, ses compteurs et l’état de ses tuiles. Le décodeur est réutilisable. Les entiers PHP 64 bits sont nécessaires ; aucune extension, bibliothèque native ou commande externe n’intervient en production.

Valeurs natives et métadonnées

Chaque ComponentPlane conserve ses dimensions, son origine, ses séparations horizontale/verticale, son signe et sa précision de 1 à 38 bits. Les lignes sont stockées MSB d’abord et complétées à l’octet ; les valeurs signées utilisent le complément à deux sur la précision déclarée. sample() renvoie l’entier natif signé ou non signé. Il ne décale pas les valeurs signées et n’agrandit pas les composantes sous-échantillonnées. Les palettes et correspondances produisent les canaux de sortie déclarés, avec leur précision propre.

ColorInformation expose l’interprétation sélectionnée et toutes les ColorSpecification d’origine. Celles-ci conservent la méthode, la priorité signée, l’approximation, les octets exacts de la méthode et du profil ICC, l’espace énuméré et ses paramètres supplémentaires. Parmi les déclarations énumérées/ICC interprétables, la sélection retient la priorité la plus élevée, puis l’approximation la plus faible, puis l’ordre du fichier. Les méthodes propres aux fournisseurs restent dans les alternatives. La sélection d’un profil ICC ne signifie pas qu’un moteur couleur a accepté ce profil. Les en-têtes ICC mal formés sont refusés.

space désigne une famille, pas une conversion : RGB peut représenter sRGB, e-sRGB ou ROMM-RGB. Le consommateur doit examiner enumeratedSpace, le profil ICC et les paramètres avant d’interpréter les valeurs. La bibliothèque ne transforme pas les valeurs CMYK, YCbCr, Lab ou ICC en sRGB. Le Reader expose les octets et métadonnées ; le consommateur PDF (par exemple HTML) applique les priorités du ColorSpace PDF, le repli couleur et la politique SMaskInData.

ChannelDefinition conserve le numéro de canal d’origine, son type, son association et son outputChannel. Les canaux couleur suivent leurs associations déclarées ; chaque plan d’opacité conserve le caractère associé ou non associé de son alpha. Les associations multiples sont préservées. DecodedImage::chromaKey conserve les valeurs natives d’opct type2 sans appliquer de transparence ; PDF ignore cette déclaration JPX. Les constructeurs publics refusent les listes non typées, sélections incohérentes, indices invalides, déclarations alpha incompatibles et clés hors de la précision des plans.

Chemins de décodage implémentés

Domaine Comportement
Géométrie Part1 Origines image/tuile, tuiles rectangulaires, parties de tuile, grilles des composantes, précisions et signes mixtes
Ordre des paquets LRCP, RLCP, RPCL, PCRL et CPRL ; couches, precincts, changements POC jusque dans les parties de tuile suivantes
En-têtes Héritage COD/COC et QCD/QCC indépendant de l’ordre des marqueurs ; PPM/PPT, y compris marqueurs répartis ; SOP et EPH
Codage entropique MQ, bypass sélectif brut, remise à zéro des contextes, terminaison de chaque passe, contextes causaux verticaux, codage à terminaison prévisible et symboles de segmentation
Reconstruction Quantification absente, scalaire dérivée ou détaillée ; ondelettes inverses 5/3 entières et 9/7 flottantes ; transformations de trois composantes réversibles/irréversibles ; ROI max-shift jusqu’à255
Transformations JPX baseline Une étape/collection de décorrélation irréversible ; CBD ; tableaux MCT integer16/integer32/float32/float64 ; MCC/MCO ; non-linéarité gamma et table ; priorités par composante/tuile
Conteneurs JP2 et première couche/codestream JPX baseline ; boîtes et reader requirements bornés ; héritage des champs jpch/jplh ; palettes, cmap, cdef, opct, ICC/EnumCS/paramètres supplémentaires
Références internes Fragments ordonnés et contenus de boîtes référencés, résolus dans la chaîne d’octets fournie, métadonnées comprises

La première couche JPX utilise un seul codestream. Les couches suivantes et les instructions de composition/animation ne la remplacent pas. La registration identité est acceptée ; celle qui nécessite un moteur de composition/rééchantillonnage produit UnsupportedFeature. Les fragments externes sont refusés sans accès réseau ou disque. Les autres transformations Part2, transformations de composantes/ondelettes hors baseline, HTJ2K et compressions autres que JPEG 2000 ne sont pas revendiqués. Les capacités requises ou fonctions actives non prises en charge échouent explicitement. Les segments de marqueur inconnus sont ignorés selon leur longueur bornée, conformément à T.800 A.1.

Il s’agit d’un décodeur, pas d’un vérificateur exhaustif de conformité du codestream. Il contrôle le cadrage, les limites, la syntaxe prise en charge et les invariants de sortie ; il ne certifie pas tous les choix de terminaison de l’encodeur ni tous les champs de métadonnées inutilisés. Les flux à terminaison prévisible utilisent le même décodage MQ ; leur décodage réussi ne prouve pas toutes les contraintes des bits de remplissage. L’entrée codestream brut est une commodité de la bibliothèque ; les exigences de conteneur PDF relèvent du consommateur PDF.

Limites et erreurs

DecodeLimits borne les octets d’entrée/sortie, dimensions, pixels, composantes, opérations, estimations d’allocations cumulées, nombres de marqueurs/paquets, profondeur des boîtes/décompositions, métadonnées et tuiles. Les compteurs sont communs aux tuiles, tableaux intermédiaires, palettes, fragments et valeurs transformées. L’allocation est estimée de manière conservatrice et cumulée ; ce n’est pas la limite mémoire du processus PHP. Le budget par défaut peut refuser une grande image avant sa limite de pixels. Toute augmentation doit être explicite et adaptée à un traitement de confiance disposant de mémoire suffisante.

MalformedImage décrit une entrée tronquée/incohérente, UnsupportedFeature une capacité non prise en charge et ResourceLimit un budget épuisé. Aucune image partielle n’est renvoyée. Les sorties 5/3 entières sont comparées exactement. Les ondelettes irréversibles, matrices et transformations non linéaires utilisent les doubles PHP puis un arrondi/écrêtage dans la plage de chaque sortie ; les tolérances sont consignées par fixture, sans promettre le même arrondi pour toute implémentation externe.

Preuves et reproduction

tests/Fixtures/jpx/manifest.json contient les hashes des données codées et des plans attendus et précise la nature de chaque oracle. tools/validate_jpx.py régénère les fixtures, contrôle les hashes conservés et compare la géométrie et les valeurs natives PHP. L’oracle OpenJPEG2.5.4 est épinglé au commit 6c4a29b00211eb0430fa0e5e890f1ce5c80f409f et utilisé par son API C, afin que les conversions CLI ne changent pas silencieusement la précision.

python3 tools/build_jpx_oracle.py --output _build/openjpeg
python3 tools/validate_jpx.py --php php --oracle _build/openjpeg/jpx-oracle --output _build/jpx
vendor/bin/phpunit --filter Jpeg2000

Le constructeur d’oracle nécessite Git, CMake, un compilateur C et Make sous Linux. Les outils Python n’utilisent que la bibliothèque standard. OpenJPEG reste réservé aux tests. La CI exécute PHP8.3,8.4 et8.5. Le profil Gray ICC est une fixture originale LittleCMS D50/gamma2.2 ; sa provenance et son hash figurent dans le manifeste.

Les niveaux de preuve sont distingués :

  • OpenJPEG compare les valeurs natives 1/2/4/8/12/16/24/31bits, signées/non signées et mixtes, options de blocs, progressions, grilles, reconstructions réversibles/irréversibles et quantification scalaire dérivée. L’égalité entre l’entrée de l’encodeur indépendant et son résultat décodé est contrôlée séparément lorsqu’elle est prise en charge.
  • OpenJPEG ne décode pas indépendamment tous les shifts ROI255 testés ; ce vecteur est encodé indépendamment puis comparé aux valeurs initiales.
  • Les précisions32–38 utilisent des vecteurs entiers normatifs dérivés des équations T.800 E-1/E-2/E-8 et du décalage DC, à partir de coefficients encodés indépendamment. Ce ne sont pas des tests de décodage OpenJPEG32–38bits.
  • Les matrices/non-linéarités Part2 utilisent des équations Python distinctes issues de T.801 et de ses corrigenda. Le décodeur OpenJPEG refuse la sortie de son propre encodeur matriciel testée : elle n’est pas comptée comme oracle matriciel réussi.
  • Les en-têtes déplacés, priorités, palettes/alpha/couleurs et références internes reposent sur des transformations d’octets et sorties natives attendues spécifiées séparément. Les vecteurs MQ vérifient la parité avec l’implémentation attribuée, sans être présentés comme oracle indépendant. Les véritables codestreams OpenJPEG exercent MQ indépendamment.

Le nombre de fixtures est un inventaire de régressions, pas une preuve de couverture de tous les codestreams légaux.

Sources normatives et d’implémentation

  • ITU-T T.800 (06/2019) : annexes A/B pour les en-têtes, géométrie et paquets ; C/D pour le codage arithmétique/des blocs ; E/F pour quantification/ondelettes ; G pour les transformations ; H pour ROI ; I pour JP2.
  • ITU-T T.801 (08/2002) : A.3.6–10, J.3.1.1.1, annexeK, M.9.2 et M.11 ; avec Corrigendum3 et Corrigendum4. Le texte2023 n’a pas été revu. Cor4 régit l’équation gamma, l’identité des remplacements MCT et l’indice MCC zéro.
  • ISO32000-2:2020 EC3 §7.4.9 définit la frontière PDF, dont les précisions1–38, restrictions JPX baseline et politiques d’opacité/couleur.
  • MQ et l’organisation des scans des blocs sont adaptés de Mozilla PDF.js, Apache2. Voir NOTICE et resources/jpeg2000/NOTICE et resources/arithmetic/NOTICE. Les coefficients natifs, limites, ROI, bypass, transformations et états de conteneur sont implémentés par des objets PHP propres à chaque requête.

Source de ce guide au commit documenté ↗