Une base de palette PNG avec IDAT qui a BTYPE = 00 pour aucune compression, maintenant avec le code Adler32

Je travaille sur un code qui construit des fichiers PNG simples à base de palette sans libpng. À ce stade, le fichier de sortie ne contient que des fragments IHDR, PLTE, IDAT (x3) et IEND. La seule chose qui est peut-être un peu différente en ce que les valeurs d’index de pixels dans le bloc IDAT ne sont pas compressées, c’est-à-dire que les différents octets d’en-tête zlib / block sont les suivants.

  • CMF = 0x78.
  • FLG = 0x9C (ayez aussi quelques autres valeurs ici mais toujours avec le bit 5 vide).
  • Octet d’en-tête de bloc = 0x01 (BFINAL = 1, BTYPE = 00).

D’après ce que je peux voir, le code construit le fichier correctement, mais certains visualiseurs d’images refusent d’afficher l’image complètement, voire pas du tout.

  • MS Paint est heureux.
  • GIMP est heureux.
  • LibreOffice Draw est heureux.
  • Ristretto >> Erreur fatale lors de la lecture du fichier image PNG: pas assez de données compressées.
  • ImageMagick >> identifier: données d’image insuffisantes `20160317_PNG_064.png ‘@ error / png.c / MagickPNGErrorHandler / 1645.
  • Eye of Gnome >> pas assez de données d’image.

J’ai mis le fichier dans quelques outils différents, avec encore des résultats mitigés.

  • optipng >> pas assez de données d’image.
  • pngchunks ne rapporte aucune erreur.
  • pngcheck ne rapporte aucune erreur.

Voici la vue hexadécimale du fichier 20160317_PNG_064.png

L’image générée est cette petite image de 8×8 pixels .

Je suis donc un peu dans l’impasse sur ce qu’il faut essayer ensuite. Toute aide est appréciée.

EDIT_000 Après avoir limité le problème au calcul Adler32, voici, comme l’a demandé @Mark Adler, le code que j’utilise pour calculer la valeur Adler32 avec les données de test de la fonction principale. Au fait, ce n’est pas compliqué et je code très verbeux.

#include  #define DEBUG static const unsigned long GC_ADLER32_BASE = 0xFFF1; // Largest prime smaller than 65536 is 65521. unsigned long Adler32_Update ( unsigned long Adler32, unsigned char *Buffer, unsigned int BufferLength ) { unsigned long ulW0; unsigned long ulW1; unsigned int uiW0; #ifdef DEBUG printf("\n"); printf(" Incoming Adler32 value.................0x%.8X\n", Adler32); #endif ulW0 = Adler32 & 0xFFFF; ulW1 = (Adler32 >> 0x0010) & 0xFFFF; #ifdef DEBUG printf(" Inital sum values are..................0x%.8X, 0x%.8X\n", ulW0, ulW1); #endif for (uiW0 = 0x0000; uiW0 < BufferLength; uiW0 = uiW0 + 0x0001) { ulW0 = (ulW0 + Buffer[uiW0]) % GC_ADLER32_BASE; ulW1 = (ulW1 + ulW0) % GC_ADLER32_BASE; } #ifdef DEBUG printf(" Final sum values are...................0x%.8X, 0x%.8X\n", ulW0, ulW1); #endif Adler32 = (ulW1 << 0x0010) | ulW0; #ifdef DEBUG printf(" Outgoing Adler32 value.................0x%.8X\n", Adler32); #endif return (Adler32); } unsigned long Adler32_Get ( unsigned char *Buffer, unsigned int BufferLength ) { unsigned long Adler32; Adler32 = 0x00000001L; Adler32 = Adler32_Update(Adler32, Buffer, BufferLength); return (Adler32); } int main ( unsigned int argc, unsigned char *arg[] ) { unsigned long Adler32; unsigned char data[272] = { 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02 }; Adler32 = Adler32_Get(data, sizeof(data)); printf("\n"); printf("The Adler32 value is ..........................0x%.8X\n", Adler32); return(0x00); } 

Quel que soit le calcul effectué, la valeur d’Adler-32 est incorrecte. La valeur correcte pour Adler-32 pour les données est 0x10080061 , qui doit être stockée dans le stream sous le nom 10 08 00 61 . Si je résous ce problème dans le fichier lié et crée un nouveau CRC pour ce bloc, tout va bien.

L’image fixe est:

fixé

En tant que co-auteur de la spécification PNG, je pense que ce fichier est entièrement conforme. La spécification PNG diffère la définition de “deflate” dans RFC 1951, et que RFC autorise explicitement les sections BTYPE = 0. Vous souhaiterez peut-être contacter les auteurs de ces programmes qui rencontrent des problèmes et signaler un bogue en joignant votre fichier comme exemple d’entrée.