]> Creatis software - gdcm.git/blob - src/gdcmFile.cxx
Ajout fonctions
[gdcm.git] / src / gdcmFile.cxx
1 // gdcmFile.cxx
2
3 #include "gdcm.h"
4
5 #define DEBUG 1
6
7 static void _Swap(void* im, int swap, int lgr, int nb);
8
9 /////////////////////////////////////////////////////////////////
10 /**
11  * \ingroup   gdcmFile
12  * \brief Constructor dedicated to writing a new DICOMV3 part10 compliant
13  * \file (see SetFileName, SetDcmTag and Write)
14  * \Opens (in read only and when possible) an existing file and checks
15  * \for DICOM compliance. Returns NULL on failure.
16  * \Note: the in-memory representation of all available tags found in
17  * \the DICOM header is post-poned to first header information access.
18  * \This avoid a double parsing of public part of the header when
19  * \one sets an a posteriori shadow dictionary (efficiency can be
20  * \seen as a side effect).   
21  *
22  * @param 
23  *
24  * @return      
25  */
26  
27 gdcmFile::gdcmFile(string & filename) 
28         :gdcmHeader(filename.c_str())   
29 {
30 }
31
32
33 /////////////////////////////////////////////////////////////////
34 /**
35  * \ingroup   gdcmFile
36  * \brief     Renvoie la longueur A ALLOUER pour recevoir les pixels de l'image
37  * \            ou DES images dans le cas d'un multiframe
38  * \            ATTENTION : il ne s'agit PAS de la longueur du groupe des Pixels        
39  * \            (dans le cas d'images compressees, elle n'a pas de sens).
40  *
41  * @param void  Rien en entree
42  *
43  * @return      longueur a allouer 
44  */
45
46 size_t gdcmFile::GetImageDataSize(void) {
47         int nbLignes, nbCol, nbFrames, nb;
48         string str_nbFrames, str_nb;
49         // Nombre de Lignes     
50         nbLignes=atoi(gdcmHeader::GetPubElValByNumber(0x0028,0x0010).c_str());
51         // Nombre de Colonnes   
52         nbCol   =atoi(gdcmHeader::GetPubElValByNumber(0x0028,0x0011).c_str());
53
54         // Nombre de Frames     
55         str_nbFrames=gdcmHeader::GetPubElValByNumber(0x0028,0x0008);
56         
57         if (str_nbFrames == "gdcm::Unfound" ) {
58                 nbFrames = 1;
59         } else {
60                 nbFrames = atoi(str_nbFrames.c_str() );
61         }
62         
63         // Nombre de Bits Alloues pour le stockage d'un Pixel   
64         str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
65
66         if (str_nb == "gdcm::Unfound" ) {
67                 nb = 16;
68         } else {
69                 nb = atoi(str_nb.c_str() );
70         }
71
72         size_t lgrTotale = nbFrames*nbLignes*nbCol*(nb/8);
73         return (lgrTotale);
74
75 }
76
77 /////////////////////////////////////////////////////////////////
78 /**
79  * \ingroup   gdcmFile
80  * \brief amene en mémoire les Pixels d'une image NON COMPRESSEE
81  * \Aucun test n'est fait pour le moment sur le caractere compresse ou non de l'image
82  *
83  * @param rien
84  *
85  * @return      Pointeur sur la zone mémoire contenant les Pixels lus
86  */
87
88 void * gdcmFile::GetImageData (void) {
89         
90         char* _Pixels;
91
92         int  nb, nbu, highBit, signe;
93         string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe;
94         
95         unsigned short int mask = 0xffff;
96
97         // Nombre de Bits Alloues pour le stockage d'un Pixel   
98         str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
99
100         if (str_nb == "gdcm::Unfound" ) {
101                 nb = 16;
102         } else {
103                 nb = atoi(str_nb.c_str() );
104         }
105                         
106         // Nombre de Bits Utilises      
107         str_nbu=GetPubElValByNumber(0x0028,0x0101);
108
109         if (str_nbu == "gdcm::Unfound" ) {
110                 nbu = nb;
111         } else {
112                 nbu = atoi(str_nbu.c_str() );
113         }       
114         
115         // Position du Bit de Poids Fort        
116         str_highBit=GetPubElValByNumber(0x0028,0x0102);
117
118         if (str_highBit == "gdcm::Unfound" ) {
119                 highBit = nb - 1;
120         } else {
121                 highBit = atoi(str_highBit.c_str() );
122         }
123                 
124         // Signe des Pixels 0 : Unsigned
125         str_signe=GetPubElValByNumber(0x0028,0x0103);
126
127         if (str_signe == "gdcm::Unfound" ) {
128                 signe = 1;
129         } else {
130                 signe = atoi(str_signe.c_str() );
131         }
132         
133         // Longueur en Octets des Pixels a lire
134         size_t _lgrTotale = GetImageDataSize();
135         
136         //Pixels = (char *) g_malloc(_lgrTotale);
137         _Pixels = (char *) malloc(_lgrTotale);
138         
139         GetPixels(lgrTotale, _Pixels);
140
141         // On remet les Octets dans le bon ordre si besoin est
142         if (nb != 8) {
143                 int _sw = GetSwapCode();
144
145                 _Swap (_Pixels, _sw, _lgrTotale, nb);
146         }
147         
148         // On remet les Bits des Octets dans le bon ordre si besoin est
149         //
150         // ATTENTION :  Jamais confronté a des pixels stockes sur 32 bits 
151         //                      avec moins de 32 bits utilises
152         //                      et dont le bit de poids fort ne serait pas la ou on l'attend ...
153         //                      --> ne marchera pas dans ce cas 
154         if (nbu!=nb){
155                 mask = mask >> (nb-nbu);
156                 int l=(int)_lgrTotale/(nb/8);
157                 unsigned short *deb = (unsigned short *)_Pixels;
158                 for(int i=0;i<l;i++) {
159                                 *deb = (*deb >> (nbu-highBit-1)) & mask;
160                                 deb ++;
161                 }
162         }
163                 
164         printf ("on est sorti\n");
165         
166         // On l'affecte à un champ du dcmFile
167         
168         Pixels = _Pixels;
169         lgrTotale = _lgrTotale;
170         
171         // et on le retourne
172         // ca fait double emploi, il faudra nettoyer ça
173         
174         return (_Pixels);               
175 }
176
177
178 /////////////////////////////////////////////////////////////////
179 /**
180  * \ingroup   gdcmFile
181  * \brief amene en mémoire dans une zone précisee par l'utilisateur
182  * \les Pixels d'une image NON COMPRESSEE
183  * \Aucun test n'est fait pour le moment sur le caractere compresse ou non de l'image
184  *
185  * @param 
186  *
187  * @return      
188  */
189
190 int gdcmFile::PutImageDataHere (void* destination, size_t MaxSize) {
191
192 // Question :
193 //      dans quel cas la Maxize sert-elle a quelque chose?
194 //      que fait-on si la taille de l'image est + gde    que Maxize?
195 //      que fait-on si la taille de l'image est + petite que Maxize?
196
197         
198         void * Pixels = destination;  // pour garder le code identique avec GetImageData
199
200         int nb, nbu, highBit, signe;
201         string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe;
202         
203         unsigned short int mask = 0xffff;
204         
205         // Longueur en Octets des Pixels a lire
206         size_t _lgrTotale = GetImageDataSize(); // ne faudrait-il pas la stocker?
207         
208         // si lgrTotale < MaxSize ==> Gros pb . A VOIR
209         
210         lgrTotale = MaxSize;                                    // pour garder le code identique avec GetImageData
211         //Pixels = (char *) malloc(lgrTotale);  // pour garder le code identique avec GetImageData
212         
213         GetPixels(lgrTotale, Pixels);
214                 
215                 
216         // Nombre de Bits Alloues pour le stockage d'un Pixel   
217         str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
218
219         if (str_nb == "gdcm::Unfound" ) {
220                 nb = 16;
221         } else {
222                 nb = atoi(str_nb.c_str() );
223         }
224         
225         // Nombre de Bits Utilises      
226         str_nbu=GetPubElValByNumber(0x0028,0x0101);
227
228         if (str_nbu == "gdcm::Unfound" ) {
229                 nbu = nb;
230         } else {
231                 nbu = atoi(str_nbu.c_str() );
232         }       
233         
234         // Position du Bit de Poids Fort        
235         str_highBit=GetPubElValByNumber(0x0028,0x0102);
236
237         if (str_highBit == "gdcm::Unfound" ) {
238                 highBit = nb - 1;
239         } else {
240                 highBit = atoi(str_highBit.c_str() );
241         }
242                 
243         // Signe des Pixels 
244         str_signe=GetPubElValByNumber(0x0028,0x0103);
245
246         if (str_signe == "gdcm::Unfound" ) {
247                 signe = 1;
248         } else {
249                 signe = atoi(str_signe.c_str() );
250         }
251
252
253         // On remet les Octets dans le bon ordre si besoin est
254         if (nb != 8) {
255                 int _sw = GetSwapCode();
256
257                 _Swap (Pixels, _sw, lgrTotale, nb);
258         }
259         
260         // On remet les Bits des Octets dans le bon ordre si besoin est
261         //
262         // ATTENTION :  Jamais confronté a des pixels stockes sur 32 bits 
263         //                      avec moins de 32 bits utilises
264         //                      et dont le bit de poids fort ne serait pas la ou on l'attend ...
265         //                      --> ne marchera pas dans ce cas 
266         if (nbu!=nb){
267                 mask = mask >> (nb-nbu);
268                 int l=(int)lgrTotale/(nb/8);
269                 unsigned short *deb = (unsigned short *)Pixels;
270                 for(int i=0;i<l;i++) {
271                                 *deb = (*deb >> (nbu-highBit-1)) & mask;
272                                 deb ++;
273                 }
274         }
275                         
276         // VOIR s'il ne faudrait pas l'affecter à un champ du dcmHeader
277         
278         //return (Pixels);                              // pour garder le code identique avec GetImageData      
279         return 1; 
280 }
281
282 //
283 // Je laisse le code integral, au cas ça puisse etre reutilise ailleurs
284 //
285
286 static void _Swap(void* im, int swap, int lgr, int nb) {                     
287 guint32 s32;
288 guint16 fort,faible;
289 int i;
290
291 if(nb == 16)
292     
293         switch(swap) {
294                 case 0:
295                 case 12:
296                 case 1234:
297                         break;
298                 
299                 case 21:
300                 case 3412:
301                 case 2143:
302                 case 4321:
303
304                         for(i=0;i<lgr;i++)
305                                 ((unsigned short int*)im)[i]= ((((unsigned short int*)im)[i])>>8)
306                                                 | ((((unsigned short int*)im)[i])<<8);
307                         break;
308                         
309                 default:
310                         printf("valeur de SWAP (16 bits) non autorisee : %d\n", swap);
311         } 
312  
313 if( nb == 32 )
314
315         switch (swap) {
316                 case 0:
317                 case 1234:
318                          break;
319
320                 case 4321:
321                          for(i=0;i<lgr;i++) {
322                                 faible=  ((unsigned long int*)im)[i]&0x0000ffff;    /* 4321 */
323                                 fort  =((unsigned long int*)im)[i]>>16;
324                                 fort=  (fort>>8)   | (fort<<8);
325                                 faible=(faible>>8) | (faible<<8);
326                                 s32=faible;
327                                 ((unsigned long int*)im)[i]=(s32<<16)|fort;
328                         }
329                         break;
330
331                 case 2143:
332                         for(i=0;i<lgr;i++) {
333                                 faible=  ((unsigned long int*)im)[i]&0x0000ffff;    /* 2143 */
334                                 fort=((unsigned long int*)im)[i]>>16;
335                                 fort=  (fort>>8)   | (fort<<8);
336                                 faible=(faible>>8) | (faible<<8);
337                                 s32=fort; 
338                                 ((unsigned long int*)im)[i]=(s32<<16)|faible;
339                         }
340                         break;
341   
342                 case 3412:
343                         for(i=0;i<lgr;i++) {
344                                 faible=  ((unsigned long int*)im)[i]&0x0000ffff;    /* 3412 */
345                                 fort=((unsigned long int*)im)[i]>>16;                  
346                                 s32=faible; 
347                                 ((unsigned long int*)im)[i]=(s32<<16)|fort;
348                         }                 
349                         break; 
350                                 
351                 default:
352                         printf("valeur de SWAP (32 bits) non autorisee : %d\n", swap);
353         } 
354 return;
355 }
356
357 /////////////////////////////////////////////////////////////////
358 /**
359  * \ingroup   gdcmFile
360  * \brief Ecrit sur disque les pixels d'UNE image
361  * \Aucun test n'est fait sur l'"Endiannerie" du processeur.
362  * \Ca sera à l'utilisateur d'appeler son Reader correctement
363  * \ Equivalent a IdImaWriteRawFile) 
364  *
365  * @param 
366  *
367  * @return      
368  */
369
370 int gdcmFile::WriteRawData (string nomFichier) {
371
372         FILE * fp1;
373         fp1 = fopen(nomFichier.c_str(),"wb");
374         if (fp1 == NULL) {
375                 printf("Echec ouverture (ecriture) Fichier [%s] \n",nomFichier.c_str());
376                 return (0);
377         } 
378         
379         fwrite (Pixels,lgrTotale, 1, fp1);
380         fclose (fp1);
381         return(1);
382 }
383
384
385
386 /////////////////////////////////////////////////////////////////
387 /**
388  * \ingroup   gdcmFile
389  * \brief Ecrit sur disque UNE image Dicom
390  * \Aucun test n'est fait sur l'"Endiannerie" du processeur.
391  * \Ca sera à l'utilisateur d'appeler son Reader correctement.
392  * \ (Equivalent a IdDcmWrite) 
393  *
394  * @param 
395  *
396  * @return      
397  */
398
399 int gdcmFile::WriteDcm (string nomFichier) {
400
401
402 // ATTENTION : fonction non terminée (commitée a titre de precaution)
403
404         FILE * fp1;
405         char* filePreamble;
406         fp1 = fopen(nomFichier.c_str(),"wb");
407         if (fp1 == NULL) {
408                 printf("Echec ouverture (ecriture) Fichier [%s] \n",nomFichier.c_str());
409                 return (0);
410         } 
411         
412         //      Ecriture Dicom File Preamble
413         filePreamble=(char*)calloc(128,1);
414         fwrite(filePreamble,128,1,fp1);
415         fwrite("DICM",4,1,fp1);
416         if(DEBUG) printf("Ecriture File Preamble\n");
417
418         // un accesseur de + est obligatoire ???
419         
420         GetPubElVals().Write(fp1);
421
422         fclose (fp1);
423         return(1);
424 }
425         
426