QOI (format d'image)QOI Quite OK Image
Le QOI (Quite OK Image) est un format de compression d'images sans perte de 24 bits (8 bits par couleur RVB) ou 32 bits (8 bits par couleur avec le canal alpha de 8 bits RGBA), inventé par Dominic Szablewski et annoncé pour la première fois le 24 novembre 2021. DescriptionL'objectif visé était de créer une méthode de compression d'image sans perte open source, plus rapide et plus facile à mettre en œuvre que PNG. Une vidéo YouTube tierce en anglais explique comment la compression PNG et QOI est effectuée[1]. Les chiffres spécifiés dans l'annonce et la vidéo revendiquent un encodage 20 à 50 fois plus rapide et une vitesse de décodage 3 à 4 fois plus rapide par rapport au PNG, avec des tailles compressées à peine plus lourdes que celles de PNG[2]. Le format appartient au domaine public (CC0). Support logiciel et langageQOI est pris en charge nativement par ImageMagick[3], IrfanView (à partir de la version 4.60)[4], et FFmpeg (à partir de la version 5.1)[5]. Des plugins créés par la communauté sont disponibles dans GIMP, Paint. NET et XnViewMP[6]. Il existe également des implémentations pour divers langages tels que Rust, Python, Java, C++, C# et bien d'autres[7]. Une liste complète peut être trouvée sur le référentiel GitHub du projet. Format de fichierEntêteUn fichier QOI se compose d'un en-tête de 14 octets, suivi d'un nombre quelconque de "morceaux" de données et d'un marqueur de fin de 8 octets. qoi_header {
char magic[4] ; // octets de magie "qoif".
uint32_t width ; // largeur de l'image en pixels (BE)
uint32_t height ; // hauteur de l'image en pixels (BE)
uint8_t channels ; // 3 = RGB, 4 = RGBA
uint8_t colorspace ; // 0 = sRGB avec alpha linéaire
// 1 = tous les canaux sont linéaires
} ;
Les champs espace colorimétrique et canal sont purement informatifs. Ils ne changent pas la façon dont les blocs de données sont encodés. EncodageLes images sont encodées ligne par ligne, de gauche à droite, de haut en bas. Le décodeur et l'encodeur commencent par
Les canaux de couleur sont supposés ne pas être prémultipliés avec le canal alpha (« alpha non prémultiplié »). Un
Dans l'encodeur, si la valeur de pixel à l'index correspond au pixel actuel, cette position d'index est écrite dans le flux sous la forme index_position = (r * 3 + g * 5 + b * 7 + a * 11) % 64
Chaque bloc commence par une balise de 2 ou 8 bits, suivie d'un certain nombre de bits de données. La longueur en bits des morceaux est divisible par 8 - c'est-à-dire que tous les morceaux sont alignés sur les octets. Toutes les valeurs codées dans ces bits de données ont le bit le plus significatif à gauche. Les balises 8 bits ont priorité sur les balises 2 bits. Un décodeur doit d'abord vérifier la présence d'une étiquette de 8 bits. La fin du flux d'octets est marquée par 7 octets ┌─ QOI_OP_RGB ────┬─────────┬─────────┬─────────┐
│ Byte[0] │ Byte[1] │ Byte[2] │ Byte[3] │
│ 7 6 5 4 3 2 1 0 │ 7 .. 0 │ 7 .. 0 │ 7 .. 0 │
├─────────────────┼─────────┼─────────┼─────────┤
│ 1 1 1 1 1 1 1 0 │ red │ green │ blue │
└─────────────────┴─────────┴─────────┴─────────┘
8-bit tag b11111110 (254)
Valeur du canal rouge 8 bits
Valeur du canal vert 8 bits
Valeur du canal bleu 8 bits
La valeur alpha reste inchangée par rapport au pixel précédent. ┌─ QOI_OP_RGBA ───┬─────────┬─────────┬─────────┬─────────┐
│ Byte[0] │ Byte[1] │ Byte[2] │ Byte[3] │ Byte[4] │
│ 7 6 5 4 3 2 1 0 │ 7 .. 0 │ 7 .. 0 │ 7 .. 0 │ 7 .. 0 │
├─────────────────┼─────────┼─────────┼─────────┼─────────┤
│ 1 1 1 1 1 1 1 1 │ red │ green │ blue │ alpha │
└─────────────────┴─────────┴─────────┴─────────┴─────────┘
8-bit tag b11111111 (255)
Valeur du canal rouge 8 bits
Valeur du canal vert 8 bits
Valeur du canal bleu 8 bits
Valeur du canal alpha 8 bits
┌─ QOI_OP_INDEX ──┐
│ Byte[0] │
│ 7 6 5 4 3 2 1 0 │
├────┬────────────┤
│0 0 │ index │ (Range: 0..63)
└────┴────────────┘
2-bit tag b00Balise 2 bits b00
Index 6 bits dans le tableau d'indexation des couleurs : 0..63
Un encodeur valide ne doit pas émettre 2 blocs ┌─ QOI_OP_DIFF ───┐
│ Byte[0] │
│ 7 6 5 4 3 2 1 0 │
├────┬───┬───┬────┤
│ 0 1│dr │dg │ db │ (Range: 64 .. 127)
└────┴───┴───┴────┘
2-bit tag b01
2-bit red channel difference from the previous pixel -2..1
2-bit green channel difference from the previous pixel -2..1
2-bit blue channel difference from the previous pixel -2..1
La différence avec les valeurs de canal actuelles utilise une opération de bouclage, donc ┌─ QOI_OP_LUMA ───┬─────────────────┐
│ Byte[0] │ Byte[1] │
│ 7 6 5 4 3 2 1 0 │ 7 6 5 4 3 2 1 0 │
├────┬────────────┼────────┬────────┤
│1 0 │ diff green │dr - dg │db - dg │ (Byte[0] Range: 128 .. 191)
└────┴────────────┴────────┴────────┘
2-bit tag b10
6-bit green channel difference from the previous pixel -32..31
4-bit red channel difference minus green channel difference -8..7
4-bit blue channel difference minus green channel difference -8..7
Le canal vert est utilisé pour indiquer le sens général du changement et est codé sur 6 bits. Les canaux rouge et bleu (dr et db) fondent leurs diffs sur la différence du canal vert. C'est-à-dire : dr_dg = (cur_px.r - prev_px.r) - (cur_px.g - prev_px.g)
db_dg = (cur_px.b - prev_px.b) - (cur_px.g - prev_px.g)
La différence avec les valeurs de canal actuelles utilise une opération de bouclage, donc ┌─ QOI_OP_RUN ────┐
│ Byte[0] │
│ 7 6 5 4 3 2 1 0 │
├────┬────────────┤
│1 1 │ run │ (Range: 192 .. 253)
└────┴────────────┘
2-bit tag b11
6-bit run-length repeating the previous pixel: 1..62 111101 32 16 8 4 1
La longueur d'exécution est stockée avec un biais de − 1. Notez que les longueurs d'exécution 63 et 64 ( Références
Voir aussiLiens externes |