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