Le but de cette page est de vous apporter suffisamment de connaissances pour pouvoir décoder un fichier PNG et en récupérer les informations des pixels sans avoir à transformer ce fichier dans un autre format. Attention, cette documentation ne couvre pas tous les encodages possibles du format PNG.
Toutes les informations de cette page proviennent de la documentation de référence du format PNG sur le site du W3C (English).
Un fichier PNG commence par une signature de 8 octets représenté par les valeurs décimales suivantes:
137 80 78 71 13 10 26 10 (ou 89 50 4E 47 0D 0A 10 0A en hexadécimal).
La suite du fichier est décomposé en plusieurs parties appelées chunk (gros morceaux).
Un fichier peut contenir plusieurs chunks de données IDAT + un chunk PLTE pour la palette à utiliser s'il s'agit d'une image dont les couleurs sont indéxées + d'autre chunks secondaires.
Il existe 18 chunks officiels, dont 4 principaux et 14 secondaires.
Nom | Description | Contient | Importance | Occurence |
---|---|---|---|---|
IHDR | En-tête du fichier |
|
Obligatoire | Après la signature PNG |
PLTE | Palette de l'image | Table des couleurs | Facultatif | Entre IHDR et le 1er IDAT |
IDAT | Bloc de données | Données de l'image | Obligatoire | Entre IHDR ou PLTE et IEND |
IEND | Fin du fichier | néant | Obligatoire | Dernier chunk |
tIME | Timestamp | Facultatif | N'importe où | |
iTXt | Info textuelle internationale (peut-être compressée zlib) | Facultatif | N'importe où | |
tEXt | Info textuelle non-compressée | Facultatif | N'importe où | |
zTXt | Info textuelle compressée (zlib) | Facultatif | N'importe où |
Un chunk se décompose en 4 parties:
LENGTH | TYPE | DATAS | CRC |
---|---|---|---|
Longueur des données | Type de chunk | Données dont la longueur en octets est spécifiée dans LENGTH | Contrôle |
4 octets | 4 octets | n octets | 4 octets |
Extraire les "LENGTH octets" se trouvant après le champ TYPE, puis les décompresser avec la méthode INFLATE.
Pour chaque chunk IDAT, extraire les "LENGTH octets" se trouvant après leur champ TYPE, et les concaténer dans l'ordre d'apparition dans le fichier.
Ensuite décomprésser cette concaténation avec la méthode INFLATE.
A la suite de la décompréssion, on obtient une suite de SCANLINES.
Une SCANLINE est une représentation "filtrée" d'une ligne de l'image. Le nombre de SCANLINES est égal à la hauteur de l'image en pixels pour une image qui n'est pas entrelacée.
Le premier octet de chaque SCANLINE indique le type de filtre appliqué aux octets de cette SCANLINE. La longueur d'une SCANLINE est donc toujours supérieure d'un octet à la représentation d'une ligne d'une image.
Les SCANLINES obtenues sont filtrées. Pour pouvoir lire l'information de couleur de chaque pixel, il va falloir "reconstituer" les octets SCANLINE par SCANLINE. Il existe cinq types de filtres codés par 0, 1, 2, 3 ou 4 dans le premier octet de chaque SCANLINE.
Le filtrage s'effectue sur les octets et non sur les pixels.
Les pixels peuvent êtres représentés par 1 bit ou plusieurs octets suivant l'encodage utilisé. Pour cette opération de filtrage il faut repérer 4 octets:
c | b |
---|---|
l'octet précédent b représentant le même composant que b (l'octet représentant le rouge du pixel précédent b) | l'octet se trouvant au même rang que x dans la ligne précédente (l'octet représentant le rouge du pixel se trouvant juste au dessus du pixel de x) |
a | x |
l'octet précédent x représentant le même composant que x (dans l'exemple, c'est l'octet rouge du pixel précédent) | l'octet devant être filtré (par exemple l'octet représentant le rouge si 1 pixel est codé sur trois octets) |