Compression avec zlib

Compression avec zlib - C - Programmation

Marsh Posté le 02-06-2006 à 11:18:50    

Bonjour,
 
je suis sur un projet qui demande d'enregistrer / charger des images cérébrales 3D au format NIfTI. Ce format est constitué d'un fichier contenant un header puis, toujours à partir de l'offset 352 (taille du header), les niveaux de gris de l'image.
 
 L'enregistrement et le chargement fonctionnent parfaitement sous ce format et j'ai donc décidé de pouvoir utiliser la compression / décompression de fichiers avec zlib. Et c'est là que rien ne va plus.
 
En effet, après sauvegarde et compression, lorsque l'on recharge le fichier, l'image se trouve légèrement décalée. Cela n'est pas du au chargement puisque les fichiers externes dont je me sers pour tester le programme s'ouvrent correctement.
 
Les informations du header me semblent bien enregistrées étant donné qu'elles sont toutes récupérées au chargement. Il s'agit très certainement d'un problème à l'enregistrement des niveaux de gris de l'image.
 
Voici comment je les enregistre (après avoir enregistré le header) :
 

Code :
  1. if(!write_raw(fich, image, 352)){
  2.   remove(fich);
  3.   PUT_ERROR("Erreur lors de la sauvegarde des donnees MRI de l'image" );
  4.   return 0;
  5.  }


 
Ceci est l'appel de la fonction d'enregistrement des données avec comme argument le nom du fichier, la structure contenant les données à enregistrer ("image" ) et la position d'enregistrement (l'offset).
 
 
Voilà le code de cette fonction, d'où vient certainement le bug :
 

Code :
  1. int write_raw(const char *file_img, grphic3d *graphic, int offset)
  2. {
  3. gzFile f_img;
  4. int i=0,j=0,k=0;
  5.     char *buffchar;
  6.     short *buffshort;
  7.     long *bufflong;
  8.     void *buffer;
  9. int data_size,num_items;
  10. f_img=gzopen(file_img, "a+" );
  11. if(f_img==NULL || (long)gzseek(f_img, offset, SEEK_SET)==-1)
  12.     {
  13.    char tmp[256];
  14.    sprintf(tmp,"pas possible ecrire fichier %s\n",file_img);
  15.        PUT_ERROR(tmp);
  16.        return 0;
  17.     } 
  18. //---------------------IMG Section
  19. data_size = graphic->bitppixel/8;
  20. num_items = graphic->width*graphic->depth;
  21.     switch(data_size)
  22.     {
  23.     case sizeof(char):
  24. buffchar = CALLOC(num_items,char);
  25. if(buffchar == NULL) {
  26.     PUT_ERROR(
  27.          "[save_mri_ipb_3d] memory allocation error (2)!\n" );
  28.     gzclose(f_img);
  29.  FREE(buffchar);
  30.     return 0;
  31. }
  32. buffer = buffchar;
  33. for(j=0; j<graphic->height; j++)
  34. {
  35.     buffchar = buffer;
  36.  for(k=0; k<graphic->depth; k++)
  37.  for(i=0; i<graphic->width; i++)
  38.      *buffchar ++ = graphic->mri[i][graphic->height-j-1][graphic->depth-k-1];
  39.     if(gzwrite(f_img,(void *)buffer, data_size * num_items) / data_size != num_items) {
  40.  PUT_ERROR(
  41.             "[save_mri_ipb_3d] error writing data (2)!\n" );
  42.  gzclose(f_img);
  43.  FREE(buffchar);
  44.  return 0;
  45.     }
  46. }
  47. gzflush(f_img, Z_SYNC_FLUSH);
  48. break;
  49.     case sizeof(short):
  50. buffshort = CALLOC(num_items,short);
  51. if(buffshort == NULL) {
  52.     PUT_ERROR(
  53.             "[save_mri_ipb_3d] memory allocation error (4)!\n" );
  54.     gzclose(f_img);
  55.  FREE(buffshort);
  56.     return 0;
  57. }
  58. buffer = buffshort;
  59. for(j=0; j<graphic->height; j++)
  60. {
  61.     buffshort = buffer;
  62.  for(k=0; k<graphic->depth; k++)
  63.  for(i=0; i<graphic->width; i++)
  64.      if (!_is_bigEndian) *buffshort ++ = graphic->mri[i][graphic->height-j-1][graphic->depth-k-1];
  65.   else *buffshort ++ = shEndianConversion(graphic->mri[i][graphic->height-j-1][graphic->depth-k-1]);
  66.     if(gzwrite(f_img, (void *)buffer, data_size * num_items) / data_size != num_items) {
  67.  PUT_ERROR(
  68.             "[save_mri_ipb_3d] error writing data (4)!\n" );
  69.  gzclose(f_img);
  70.  FREE(buffshort);
  71.  return 0;
  72.     }
  73. }
  74. gzflush(f_img, Z_SYNC_FLUSH);
  75. break;
  76.     case sizeof(long):
  77. bufflong = CALLOC(num_items*2,long);
  78. if(bufflong == NULL) {
  79.     PUT_ERROR(
  80.         "[save_mri_ipb_3d] memory allocation error (6)!\n" );
  81.     gzclose(f_img);
  82.  FREE(bufflong);
  83.     return 0;
  84. }
  85. buffer = bufflong;
  86. for(j=0; j<graphic->height; j++)
  87. {
  88.     bufflong = buffer;
  89.  for(k=0; k<graphic->depth; k++)
  90.  for(i=0; i<graphic->width; i++)
  91.      if (!_is_bigEndian) *bufflong ++ = graphic->mri[i][graphic->height-j-1][graphic->depth-k-1];
  92.   else *bufflong ++ = longEndianConversion(graphic->mri[i][graphic->height-j-1][graphic->depth-k-1]);
  93.     if(gzwrite(f_img, (void *)buffer, data_size * num_items) / data_size != num_items) {
  94.  PUT_ERROR(
  95.            "[save_mri_ipb_3d] error writing data (6)!\n" );
  96.  gzclose(f_img);
  97.  FREE(bufflong);
  98.  return 0;
  99.     }
  100. }
  101. gzflush(f_img, Z_SYNC_FLUSH);
  102. break;
  103.     default:
  104. PUT_ERROR(
  105.          "[save_mri_ipb_3d] invalid data size\n" );
  106. return 0;
  107.     }
  108.     FREE(buffer);
  109.     return 1;
  110. }


 
Le paramètre graphic est la structure contenant les données importantes sur l'image comme les dimensions (width, height, depth) ainsi que le nombre de bits par pixel (bitppixel) que l'on divise par 8 pour connaître le type de données et enregistrer les niveaux de gris (champ mri) en conséquence.
 
Ce même code enregistre sans aucun problème les données en utilisant les primitives fopen, fwrite, etc...
 
Merci à qui me répondra  :)


Message édité par atharendil le 06-06-2006 à 10:29:32
Reply

Marsh Posté le 02-06-2006 à 11:18:50   

Reply

Marsh Posté le 06-06-2006 à 10:29:50    

up !

Reply

Marsh Posté le 08-06-2006 à 16:45:40    

kk c'est bien compliqué tout ça...
 
En gros, tu ne devrai pas avoir de problème à passer d'un fread/fwrite à un fichier compressé avec zLib.
 
Vérifie d'abord que tu utilise les bonnes fonctions de la librarie, car il y a tout un tas de trucs pas forcément necessaire dans zLib, comme le flush à mon avis.
 
Ensuite, à vue de nez, il est certainement possible que ce décalage soit dû au header de ton image. Vérifie que les fonctions load() et write() lisent et écrivent exactement le même header, avec les mêmes champs, le même nombre d'octets, etc... et que tes appels de fonctions zLib n'interfèrent pas (vire les trucs inutiles).

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed