PB avec libpng : png en niveau de gris sur 16 bits

ReDcRoWn Messages postés 2 Date d'inscription jeudi 1 mars 2007 Statut Membre Dernière intervention 5 mars 2007 - 5 mars 2007 à 19:53
cs_jguy Messages postés 13 Date d'inscription mardi 28 mars 2006 Statut Membre Dernière intervention 26 novembre 2007 - 19 nov. 2007 à 20:04
Bonjour à tous,

A l'aide de la libpng je cherche à écrire des images au format PNG en niveau de gris sur 16 bits (pas de transparence).

1/ Je voudrais tout d'abord savoir si cela est bien supporté par la librairie (il me semble que oui)

2/ Voici le code que j'utilise :
<!-- BEGIN TEMPLATE: bbcode_code -->

int ecrirePNG(constchar *nomFichier, short tab[DIM_Y][DIM_X]){/* --- declarations --- */int x, y, n = 0;
FILE *fic = NULL;
png_structp png_ptr;
png_infop info_ptr;
png_byte buffer[2*DIM_X];
int i,j;
/* --- fin declarations --- */
 
memset(buffer,0,sizeof(buffer));
 
fic = fopen(nomFichier,"wb");
if(fic == NULL){return(EXIT_FAILURE);
}/* on cree une png read struct */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(!png_ptr){
fclose(fic);
return(EXIT_FAILURE);
}/* on cree une png info struct */
info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr){
fclose(fic);
png_destroy_write_struct(&png_ptr, NULL);
return(EXIT_FAILURE);
}
 
/* on ecrit dans un fichier */
png_init_io(png_ptr,fic);
 
/* choix du type de compression */
png_set_compression_level(png_ptr, Z_NO_COMPRESSION);

/* infos sur l'image */
png_set_IHDR( png_ptr,
info_ptr,
DIM_X, /* largeur image */
DIM_Y, /* hauteur image */16, /* profondeur de couleur */
PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
 
png_write_info(png_ptr, info_ptr);
 
/* on ecrit l'image ligne par ligne */for(y = 0; y < DIM_Y; y++){
n = 0;
for(x 0; x < DIM_X; x++){/*buffer[n] round( ((double)tab[y][x] - min) / LSB );
buffer[n+1] = 0;*/
buffer[n] = tab[y][x]; /* LSB */
buffer[n+1] = tab[y][x] >> 8; /* MSB semble non pris en compte */
n += 2;
}
 
png_write_row(png_ptr, buffer);
}
 
/* fin ecriture PNG */
png_write_end(png_ptr, info_ptr);
 
/* liberation */
png_destroy_write_struct(&png_ptr, &info_ptr);
 
fclose(fic);
 
return(EXIT_SUCCESS);
}
 

<!-- END TEMPLATE: bbcode_code -->Quelques explications sur le code :
- la fonction "png_write_row" ne prend en second argument que des unsigned char (8 bits) donc il me semble que
le principe pour écrire des unsigned short (16 bits) c'est de passer l'octet LSB du mot 16 bits puis l'octet MSB (cela a pour conséquence de doubler la taille du buffer)
- le code en commentaire dans la double boucle me permet de passer mes images sur 8 bits et dans ce cas c'est OK
(car le MSB est à 0) donc le principe du § précédent me paraît cohérent.

Le problème c'est que le MSB ne semble pas pris en compte, du coup je n'ai pas les résultats voulu.
Toute aide sera la bienvenue, merci d'avance

2 réponses

ReDcRoWn Messages postés 2 Date d'inscription jeudi 1 mars 2007 Statut Membre Dernière intervention 5 mars 2007
5 mars 2007 à 19:58
Je la refais vu que je me suis bien planté dans mon copier coller du code source, désolé...

Bonjour à tous,

A l'aide de la libpng je cherche à écrire des images au format PNG en niveau de gris sur 16 bits (pas de transparence).

1/ Je voudrais tout d'abord savoir si cela est bien supporté par la librairie (il me semble que oui)

2/ Voici le code que j'utilise :

int ecrirePNG(const char *nomFichier, short tab[DIM_Y][DIM_X])
{
 /* --- declarations --- */
 int x, y, n = 0;
 FILE *fic = NULL;
 png_structp png_ptr;
 png_infop info_ptr;
 png_time  modtime; 
 png_text text[4];
 png_byte buffer[2*DIM_X];
 double LSB;
 short min, max;
 int i,j;
 /* --- fin declarations --- */


 memset(buffer,0,sizeof(buffer));


 fic = fopen(nomFichier,"wb");
 if (fic == NULL)
 {
  return (EXIT_FAILURE);
 }
 /* on cree une png read struct */
 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 if(!png_ptr)
 {
  fclose(fic);
  return(EXIT_FAILURE);
 }
 /* on cree une png info struct */
 info_ptr = png_create_info_struct(png_ptr);
 if(!info_ptr)
 {
  fclose(fic);
  png_destroy_write_struct(&amp;png_ptr, NULL);
  return(EXIT_FAILURE);
 }


 /* on ecrit dans un fichier */
 png_init_io(png_ptr,fic);


 /* type de compression */
 png_set_compression_level(png_ptr, Z_NO_COMPRESSION); /* Z_BEST_SPEED / Z_BEST_COMPRESSION / Z_NO_COMPRESSION */
      
    /* infos de l'image */
 png_set_IHDR( png_ptr, 
     info_ptr, 
     DIM_X,  
     DIM_Y, 
     16,  
     PNG_COLOR_TYPE_GRAY, 
     PNG_INTERLACE_NONE,
     PNG_COMPRESSION_TYPE_DEFAULT, 
     PNG_FILTER_TYPE_DEFAULT);


 png_write_info(png_ptr, info_ptr);


 /* ecrit l'image ligne par ligne */
 for (y = 0; y < DIM_Y; y++) 
 {
  n = 0;
  for (x = 0; x < DIM_X; x++)
  {
   /*buffer[n] = round( ((double)tab[y][x] - min) / LSB );
   buffer[n+1] = 0;*/
   buffer[n] = tab[y][x];
   buffer[n+1] = tab[y][x] >> 8; /* non pris en compte */
   n += 2;
  }


  png_write_row(png_ptr, buffer);
 }


 /* fin ecriture PNG */
 png_write_end(png_ptr, info_ptr); 


 /* liberation */
 png_destroy_write_struct(&amp;png_ptr, &amp;info_ptr);


 fclose(fic);


 return (EXIT_SUCCESS);
}


Quelques explications sur le code :
- la fonction "png_write_row" ne prend en second argument que des unsigned char (8 bits) donc il me semble que
le principe pour écrire des unsigned short (16 bits) c'est de passer l'octet LSB du mot 16 bits puis l'octet MSB (cela a pour conséquence de doubler la taille du buffer)
- le code en commentaire dans la double boucle me permet de passer mes images sur 8 bits et dans ce cas c'est OK
(car le MSB est à 0) donc le principe du § précédent me paraît cohérent.

Le problème c'est que le MSB ne semble pas pris en compte, du coup je n'ai pas les résultats voulu.
Toute aide sera la bienvenue, merci d'avance
0
cs_jguy Messages postés 13 Date d'inscription mardi 28 mars 2006 Statut Membre Dernière intervention 26 novembre 2007
19 nov. 2007 à 20:04
Salut!

Je voudrais savoir si tu avais résolu ton problème.
Je suis un peu dans la même situation, je n'arrive pas à lire mes PNG.

Je crois que ça se passe au niveau de la fonction "png_set_gray_to_rgb" située dans "pngwriter.cc" (ligne 1103).
Toutes les fonctions aux alentours cherchent à nous mettre dans le cas ideal d'une image RGB classique (colortype_=2).
Or, une image en niveaux de gris sans gamma a son "colortype_=0"
Cette fonction (
"png_set_gray_to_rgb") devrait donc retourner
"colortype_=2" pour pouvoir continuer le processus.

Ce n'est pas mon cas...
Je ne sais pas si une bibliothèque n'est pas inclue,  si le programme, intrinsèquement ne peut pas lire mes images (j'en doute).
Je n'arrive de toute façon pas à localiser cette transformation. Donc si toi ou quelque autre spécialiste des PNG sauraient m'aider...
0
Rejoignez-nous