]> Creatis software - gdcm.git/blob - src/gdcmHeader.cxx
79aa0139dc2654de387de3a8094183e96dd9b559
[gdcm.git] / src / gdcmHeader.cxx
1 #include "gdcmlib.h"
2
3 /* =======================================================================
4
5    _IdDcmCheckSwap
6       La seule maniere sure que l'on aie pour determiner 
7       si on est en   LITTLE_ENDIAN,       BIG-ENDIAN, 
8                   BAD-LITTLE-ENDIAN, BAD-BIG-ENDIAN
9       est de trouver l'element qui donne la longueur d'un 'GROUP'
10       (on sait que la longueur de cet element vaut 0x00000004)
11       et de regarder comment cette longueur est codee en memoire  
12
13       Le probleme vient de ce que parfois, il n'y en a pas ...
14
15       On fait alors le pari qu'on a a faire a du LITTLE_ENDIAN propre.
16       (Ce qui est la norme -pas respectee- depuis ACR-NEMA)
17       Si ce n'est pas le cas, on ne peut rien faire.
18
19       (il faudrait avoir des fonctions auxquelles 
20        on passe le code Swap en parametre, pour faire des essais 'manuels')
21
22    ======================================================================= */
23
24 EndianType gdcmHeader::gdcmHeader()
25 {
26         //guint32  s;
27         guint32  x=4;  // x : pour ntohs
28         bool net2host; // true when HostByteOrder is the same as NetworkByteOrder
29
30         int sw;
31         int lgrLue;
32         char * entCur;
33         char deb[LGR_ENTETE_A_LIRE];
34
35         // On teste le processeur
36         if (x==ntohs(x)) {
37       net2host = true;
38    } else {
39       net2host = false;
40    }
41
42         // On commence par verifier si c'est du DICOM 'actuel'
43         //                                      -------------
44
45    lgrLue = fread(deb,1,LGR_ENTETE_A_LIRE,e->fp);
46
47    entCur = deb+128;
48    if(memcmp(entCur, "DICM", (size_t)4) == 0) {
49       filetype = TrueDicom;
50       if (DEBUG) printf ("_IdDcmCheckSwap : C est du DICOM actuel \n");
51    } else {
52       filetype = Unknown;
53       if (DEBUG) printf ("_IdDcmCheckSwap : Ce n'est PAS du DICOM actuel\n");
54    }
55
56    if(filetype == TrueDicom) {
57            // on saute le File Preamble (souvent a ZERO) : 128 Octets
58       // + le DICM (4), et le (0002, 0000) soit 4 (136 = 128 + 4 + 4)
59       entCur = deb+136;
60       if(memcmp(entCur, "UL", (size_t)2) == 0) {
61          // les 2 premiers octets de la lgr peuvent valoir UL --> Explicit VR
62          filetype = ExplicitVR;
63          if (DEBUG)  printf ("_IdDcmCheckSwap : Explicit VR\n");
64       } else {
65          filetype = ImplicitVR;
66          if (DEBUG)  printf ("_IdDcmCheckSwap : PAS Explicit VR\n");
67       }
68
69       if (net2host) { // HostByteOrder is different from NetworkByteOrder
70          sw = 0;    // on est sur PC ou DEC --> LITTLE-ENDIAN -> Rien a faire
71          if (DEBUG) printf("HostByteOrder = NetworkByteOrder\n");
72
73       } else {    /* on est sur une Sun ou une SGI */
74          sw = 4321;
75          if (DEBUG) printf("HostByteOrder != NetworkByteOrder\n");
76       }
77
78       rewind(e->fp);
79       fseek (e->fp, 132L, SEEK_SET); //On se positionne sur le debut des info
80       e->offsetCourant=132;
81       return sw;
82
83    } /* fin TrueDicom */
84
85         // Pas du TrueDicom : permiere hypothese c'est de l'ACR 'propre', auquel
86         // cas la lgr du premier element du groupe est FORCEMENT 4
87
88    entCur=deb + 4;
89    s=str2num(entCur,int);
90
91    switch (s) {
92       case 0x00040000 :
93          sw=3412; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
94                         filetype = ACR;
95          break;
96       case 0x04000000 :
97          sw=4321; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
98                         filetype = ACR;
99          break;
100       case 0x00000400 :
101          sw=2143; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
102                         filetype = ACR;
103          break;
104       case 0x00000004 :
105          sw=0;    if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
106                         filetype = ACR;
107          break;
108       default :
109          sw = -1;
110          if (DEBUG) printf (" Pas trouve l info de Swap; On va parier\n");
111         }
112
113         // Deuxieme hypothese : c'est de l'ACR 'pas propre' i.e. il manque
114         // la lgr du groupe
115
116         if(sw==-1) {
117       /* On n'a pas trouve l'info de swap    28/11/2000 JPR                */
118       // Si c'est du VRAI ACR NEMA  si on est sur une DEC ou un PC swap=0,
119            // SUN ou SGI SWAP=4321
120       /* si c'est du RAW, ca degagera + tard                      */
121
122       if (DEBUG) printf("On force la chance \n");
123
124       if (x!=ntohs(x)) // HostByteOrder is different from NetworkByteOrder
125          sw = 0;    // on est sur PC ou DEC --> LITTLE-ENDIAN -> Rien a faire
126       else
127          sw = 4321; // on est sur Sun ou SGI
128         }
129
130    rewind(e->fp);    // les info commencent au debut
131    e->offsetCourant=0;
132    return (sw);
133 }
134
135 void  gdcmHeader::_setAcrLibido() {
136
137    _ID_DCM_ELEM * ple;
138    PLIST_ELEMENT plelem;
139    PLIST pl;
140
141    // Positionnement ACR_LIBIDO
142    if(DEBUG) printf("Entree ds _setAcrLibido\n");
143
144    filetype = ACR_LIBIDO = 0;
145    if ( filetype != TrueDicom) {
146       // Recognition Code  --> n'existe plus en DICOM V3 ...
147
148       pl = e->plist;
149       plelem = IdLstFirst(pl);
150       while (plelem) {
151          ple= IdLstPtrObj(plelem);
152          if(DEBUG) printf("gr %04x Num %04x\n", ple->Gr, ple->Num);
153          if(ple->Gr >  0x0008) break;     // On a depasse
154          if(ple->Gr == 0x0008) {
155             if(ple->Num >  0x0010) break; // On a depasse
156             if(ple->Num == 0x0010) {
157                if (  (memcmp(ple->valeurElem,"ACRNEMA_LIBIDO",14)==0)
158                   // si c'est egal
159                   || (memcmp(ple->valeurElem,"CANRME_AILIBOD",14)==0)) {
160                   // en cas d'objet ACRLibido fait sr 1 autre machine) 
161                   e->ACR_LIBIDO =1;
162                }  // fin if memcmp
163                break;
164             } // fin if ple->Num==0x0010
165          } // fin ple->Gr==0x0008
166          plelem = IdLstNext(plelem);
167       } // fin while 
168    } // fin if TrueDicom
169
170    return;
171 }
172
173 /* ======================================================================= 
174 *       _IdDcmRecupLgr
175 *
176 *       ACR-NEMA :      On a toujours 
177 *                               GroupNumber   (2 Octets) 
178 *                               ElementNumber (2 Octets) 
179 *                               ElementSize   (4 Octets)
180 *
181 *
182 *       DICOM :         On peut avoir (implicit Value Representation)
183 *                               GroupNumber   (2 Octets) 
184 *                               ElementNumber (2 Octets) 
185 *                               ElementSize   (4 Octets)
186 *
187 *                       On peut avoir (explicit Value Representation)
188 *                               GroupNumber         (2 Octets) 
189 *                               ElementNumber       (2 Octets) 
190 *                               ValueRepresentation (2 Octets) 
191 *                               ElementSize         (2 Octets)
192 *
193 *                       ATTENTION : dans le cas ou ValueRepresentation = OB, OW, SQ, UN
194 *                               GroupNumber         (2 Octets) 
195 *                               ElementNumber       (2 Octets) 
196 *                               ValueRepresentation (2 Octets)
197 *                               zone reservee       (2 Octets) 
198 *                               ElementSize         (4 Octets)
199 *
200 *
201 *   ======================================================================= */
202 /**
203  * \ingroup       dcm
204  * \brief         recupere la longueur d'un champ DICOM.
205  *                      (le fichier doit deja avoir ete ouvert,
206  *                       _IdAcrCheckSwap(ID_DCM_HDR *e) avoir ete appele)
207  *                      et la  partie 'group'  ainsi que la  partie 'elem' 
208  *                      de l'acr_element doivent avoir ete lues.
209  * @param sw                            code swap
210  * @param skippedLength     pointeur sur nombre d'octets que l'on a saute qd la lecture est finie
211  * @param longueurLue       pointeur sur longueur (en nombre d'octets) effectivement lue
212
213  * @return                              longueur retenue pour le champ 
214  */
215
216 static guint32 _IdDcmRecupLgr(ID_DCM_HDR *e, int sw, int *skippedLength, int *longueurLue) {
217 guint32 l_gr; 
218 unsigned short int l_gr_2;
219 int i, trouve;
220 char VR[5];
221 int lgrLue;
222
223 /*
224  *   ATTENTION :
225 */
226
227 int nbCode=26; // nombre d'elements dans la table de type DICOM_VR definie dans dicom.c
228
229 /* ================ */
230
231 // ID_DCM_HDR *e sert uniquement de passe-plat pour  __ExplicitVR
232
233
234 if (e->__ExplicitVR == 1) {
235         lgrLue=fread (&VR, (size_t)2,(size_t)1, e->fp);
236         VR[2]=0;
237
238         // ATTENTION :
239         // Ce n'est pas parce qu'on a trouve UL la premiere fois qu'on respecte 
240         // Explicit VR tout le temps
241         // (cf e=film ...)
242
243         for(i=0,trouve=0;i<nbCode;i++) {
244                 if(memcmp(_ID_dicom_vr[i].dicom_VR,VR,(size_t)2)==0) {
245                         (e->pleCourant)->VR=_ID_dicom_vr[i].dicom_VR;
246                         trouve=1;       
247                         break;
248                 }
249         }
250
251         if ( trouve == 0) {
252
253                 // On est mal : implicit VR repere
254                 // mais ce n'est pas un code connu ...
255                 // On reconstitue la longueur
256                 
257                 if(DEBUG) printf("IdDcmRecupLgr : Explicit VR, mais pas trouve de code connu\n");
258                 memcpy(&l_gr, VR,(size_t)2);
259
260                 lgrLue=fread ( ((char*)&l_gr)+2, (size_t)2, (size_t)1, e->fp);
261
262                 if(sw) l_gr = _IdDcmSWAP_LONG(((guint32)l_gr),sw);
263                 
264                 if(DEBUG) printf("IdDcmRecupLgr : lgr deduite : %08x , %d\n",l_gr,l_gr);
265                 
266                 *longueurLue=l_gr;
267                 if ( (int)l_gr == -1) { 
268                         l_gr=0;
269                 }
270                 *skippedLength = 4; 
271                 if (DEBUG) printf(" 1 : lgr %08x (%d )skippedLength %d\n",l_gr,l_gr, *skippedLength);
272                 return(l_gr);
273         }
274
275         // On repart dans la sequence 'sensee'
276
277         if(DEBUG) printf("VR : [%01x , %01x] (%c%c) en position %d du tableau\n", VR[0],VR[1],VR[0],VR[1],i);
278         //printf(" %d , %s\n", i,_ID_dicom_vr[i].dicom_VR);
279         
280         if (    
281            (!memcmp( VR,"OB",(size_t)2 )) || 
282            (!memcmp( VR,"OW",(size_t)2 )) || 
283            (!memcmp( VR,"SQ",(size_t)2 )) ||
284            (!memcmp( VR,"UN",(size_t)2 )) ) {
285
286         // les 2 octets suivants sont reserves
287
288                 if(DEBUG) printf("IdDcmRecupLgr : les 2 octets suivants sont reserves\n");
289                                         //on les saute          
290                 fseek(e->fp, 2L,SEEK_CUR);
291                 
292                                         //on lit la lgr sur QUATRE octets
293
294                 lgrLue=fread (&l_gr, (size_t)4,(size_t)1, e->fp);
295
296                 if(sw) l_gr = _IdDcmSWAP_LONG(((guint32)l_gr),sw);
297                 *skippedLength = 8;
298
299         } else {
300                                         //on lit la lgr sur DEUX octets
301
302                 lgrLue=fread (&l_gr_2, (size_t)2,(size_t)1, e->fp);
303
304                 if(sw) l_gr_2 = _IdDcmSWAP_SHORT((unsigned short)l_gr_2,sw);
305                 
306                 *longueurLue=l_gr_2;
307
308                 
309                 if ( l_gr_2 == 0xffff) {
310                         l_gr = 0;       
311                 } else {
312                         l_gr = l_gr_2;
313                 }
314                 *skippedLength = 4;
315         }       
316   } else {      // Explicit VR = 0      
317
318                                 //on lit la lgr sur QUATRE octets
319
320         lgrLue=fread (&l_gr, (size_t)4,(size_t)1, e->fp);
321
322         if(sw)l_gr=_IdDcmSWAP_LONG(((long)l_gr),sw);
323         *skippedLength = 4;
324   }
325   
326   *longueurLue=l_gr;
327   
328   // Traitement des curiosites sur la longueur
329   
330   if ( (int)l_gr == 0xffffffff)
331         l_gr=0; 
332         
333   if(!memcmp( VR,"SQ",(size_t)2 )) {    // ca annonce une SEQUENCE d'items ?!
334         l_gr=0;                                                 // on lira donc les items de la sequence 
335         if (DEBUG) printf(" SQ trouve : lgr %d \n",l_gr);
336   }
337         
338 if (DEBUG) printf(" 2 : lgr %08x (%d) skippedLength %d\n",l_gr,l_gr, *skippedLength);
339   return(l_gr);
340 }