10 #include <netinet/in.h>
13 #define LGR_ENTETE_A_LIRE 256 // on ne lit plus que le debut
16 //FIXME: this looks dirty to me...
17 #define str2num(str, typeNum) *((typeNum *)(str))
21 * \brief La seule maniere sure que l'on aie pour determiner
22 * si on est en LITTLE_ENDIAN, BIG-ENDIAN,
23 * BAD-LITTLE-ENDIAN, BAD-BIG-ENDIAN
24 * est de trouver l'element qui donne la longueur d'un 'GROUP'
25 * (on sait que la longueur de cet element vaut 0x00000004)
26 * et de regarder comment cette longueur est codee en memoire
28 * Le probleme vient de ce que parfois, il n'y en a pas ...
30 * On fait alors le pari qu'on a a faire a du LITTLE_ENDIAN propre.
31 * (Ce qui est la norme -pas respectee- depuis ACR-NEMA)
32 * Si ce n'est pas le cas, on ne peut rien faire.
34 * (il faudrait avoir des fonctions auxquelles
35 * on passe le code Swap en parametre, pour faire des essais 'manuels')
37 void gdcmHeader::CheckSwap()
40 guint32 x=4; // x : pour ntohs
41 bool net2host; // true when HostByteOrder is the same as NetworkByteOrder
45 char deb[LGR_ENTETE_A_LIRE];
47 // On teste le processeur
54 // On commence par verifier si c'est du DICOM 'actuel'
56 lgrLue = fread(deb,1,LGR_ENTETE_A_LIRE, fp);
59 if(memcmp(entCur, "DICM", (size_t)4) == 0) {
61 if (DEBUG) printf ("_IdDcmCheckSwap : C est du DICOM actuel \n");
64 if (DEBUG) printf ("_IdDcmCheckSwap : Ce n'est PAS du DICOM actuel\n");
67 if(filetype == TrueDicom) {
68 // on saute le File Preamble (souvent a ZERO) : 128 Octets
69 // + le DICM (4), et le (0002, 0000) soit 4 (136 = 128 + 4 + 4)
71 if(memcmp(entCur, "UL", (size_t)2) == 0) {
72 // les 2 premiers octets de la lgr peuvent valoir UL --> Explicit VR
73 filetype = ExplicitVR;
74 if (DEBUG) printf ("_IdDcmCheckSwap : Explicit VR\n");
76 filetype = ImplicitVR;
77 if (DEBUG) printf ("_IdDcmCheckSwap : PAS Explicit VR\n");
80 if (net2host) { // HostByteOrder is different from NetworkByteOrder
81 sw = 0; // on est sur PC ou DEC --> LITTLE-ENDIAN -> Rien a faire
82 if (DEBUG) printf("HostByteOrder = NetworkByteOrder\n");
83 } else { /* on est sur une Sun ou une SGI */
85 if (DEBUG) printf("HostByteOrder != NetworkByteOrder\n");
89 fseek (fp, 132L, SEEK_SET); //On se positionne sur le debut des info
93 // Pas du TrueDicom : permiere hypothese c'est de l'ACR 'propre', auquel
94 // cas la lgr du premier element du groupe est FORCEMENT 4
96 s=str2num(entCur,int);
100 sw=3412; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
104 sw=4321; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
108 sw=2143; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
112 sw=0; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
117 if (DEBUG) printf (" Pas trouve l info de Swap; On va parier\n");
120 rewind(fp); // les info commencent au debut
125 // Deuxieme hypothese : c'est de l'ACR 'pas propre' i.e. il manque
128 // On n'a pas trouve l'info de swap.
129 // Si c'est du VRAI ACR NEMA et
130 // * si on est sur une DEC ou un PC alors swap=0,
131 // * si on est sur SUN ou SGI, alors swap=4321
132 // Si c'est du RAW, ca degagera + tard
133 if (DEBUG) printf("On force la chance \n");
135 if (x!=ntohs(x)) // HostByteOrder is different from NetworkByteOrder
136 // on est sur PC ou DEC --> LITTLE-ENDIAN -> Rien a faire
139 // on est sur Sun ou SGI
141 rewind(fp); // les info commencent au debut
147 * \ingroup gdcmHeader
148 * \brief Pour les fichiers non TrueDicom, si le recognition
149 * code (0008,0010) s'avere etre "ACR_LIBIDO", alors
150 * valide la reconnaissance du fichier en positionnant
153 void gdcmHeader::setAcrLibido() {
156 if ( filetype != TrueDicom) {
157 printf("_setAcrLibido expects a presumably ACR file\n");
158 // Recognition Code --> n'existe plus en DICOM V3 ...
159 RecCode = GetPubElValByNumber(0x0008, 0x0010);
161 if (RecCode == "ACRNEMA_LIBIDO" ||
162 RecCode == "CANRME_AILIBOD" )
163 filetype = ACR_LIBIDO;
171 * \ingroup gdcmHeader
172 * \brief recupere la longueur d'un champ DICOM.
174 * 1/ le fichier doit deja avoir ete ouvert,
175 * 2/ CheckSwap() doit avoir ete appele
176 * 3/ la partie 'group' ainsi que la partie 'elem'
177 * de l'acr_element doivent avoir ete lues.
179 * ACR-NEMA : we allways get
180 * GroupNumber (2 Octets)
181 * ElementNumber (2 Octets)
182 * ElementSize (4 Octets)
183 * DICOM en implicit Value Representation :
184 * GroupNumber (2 Octets)
185 * ElementNumber (2 Octets)
186 * ElementSize (4 Octets)
188 * DICOM en explicit Value Representation :
189 * GroupNumber (2 Octets)
190 * ElementNumber (2 Octets)
191 * ValueRepresentation (2 Octets)
192 * ElementSize (2 Octets)
194 * ATTENTION : dans le cas ou ValueRepresentation = OB, OW, SQ, UN
195 * GroupNumber (2 Octets)
196 * ElementNumber (2 Octets)
197 * ValueRepresentation (2 Octets)
198 * zone reservee (2 Octets)
199 * ElementSize (4 Octets)
201 * @param sw code swap
202 * @param skippedLength pointeur sur nombre d'octets que l'on a saute qd
203 * la lecture est finie
204 * @param longueurLue pointeur sur longueur (en nombre d'octets)
206 * @return longueur retenue pour le champ
209 // FIXME sw n'est plus un argument necessaire
210 long int gdcmHeader::RecupLgr(
211 _ID_DCM_ELEM *pleCourant, int sw, int *skippedLength, int *longueurLue)
214 unsigned short int l_gr_2;
220 // ATTENTION : nbCode correspond au nombre d'elements dans la table
221 // de type DICOM_VR. A nettoyer.
225 if (filetype == ExplicitVR) {
226 lgrLue=fread (&VR, (size_t)2,(size_t)1, fp);
230 // Ce n'est pas parce qu'on a trouve UL la premiere fois qu'on respecte
231 // Explicit VR tout le temps (cf e=film ...)
233 for(i=0,trouve=0;i<nbCode;i++) {
234 if(memcmp(_ID_dicom_vr[i].dicom_VR,VR,(size_t)2)==0) {
235 (pleCourant)->VR=_ID_dicom_vr[i].dicom_VR;
243 // On est mal : implicit VR repere
244 // mais ce n'est pas un code connu ...
245 // On reconstitue la longueur
248 printf("IdDcmRecupLgr : Explicit VR, mais pas de code connu\n");
249 memcpy(&l_gr, VR,(size_t)2);
251 lgrLue=fread ( ((char*)&l_gr)+2, (size_t)2, (size_t)1, fp);
253 l_gr = SWAP_LONG((guint32)l_gr);
256 printf("IdDcmRecupLgr : lgr deduite : %08x , %d\n",l_gr,l_gr);
259 if ( (int)l_gr == -1)
264 printf(" 1 : lgr %08x (%d )skippedLength %d\n",
265 l_gr,l_gr, *skippedLength);
269 // On repart dans la sequence 'sensee'
272 printf("VR : [%01x , %01x] (%c%c) en position %d du tableau\n",
273 VR[0],VR[1],VR[0],VR[1],i);
275 if ( (!memcmp( VR,"OB",(size_t)2 )) ||
276 (!memcmp( VR,"OW",(size_t)2 )) ||
277 (!memcmp( VR,"SQ",(size_t)2 )) ||
278 (!memcmp( VR,"UN",(size_t)2 )) ) {
280 // les 2 octets suivants sont reserves: on les saute
282 printf("IdDcmRecupLgr : les 2 octets suivants sont reserves\n");
283 fseek(fp, 2L,SEEK_CUR);
285 //on lit la lgr sur QUATRE octets
286 lgrLue=fread (&l_gr, (size_t)4,(size_t)1, fp);
287 l_gr = SWAP_LONG((guint32)l_gr);
291 //on lit la lgr sur DEUX octets
292 lgrLue=fread (&l_gr_2, (size_t)2,(size_t)1, fp);
294 if(sw) l_gr_2 = _IdDcmSWAP_SHORT((unsigned short)l_gr_2,sw);
299 if ( l_gr_2 == 0xffff) {
308 //on lit la lgr sur QUATRE octets
310 lgrLue=fread (&l_gr, (size_t)4,(size_t)1, fp);
312 l_gr= SWAP_LONG((long)l_gr);
318 // Traitement des curiosites sur la longueur
320 if ( (int)l_gr == 0xffffffff)
323 if(!memcmp( VR,"SQ",(size_t)2 )) { // ca annonce une SEQUENCE d'items ?!
324 l_gr=0; // on lira donc les items de la sequence
325 if (DEBUG) printf(" SQ trouve : lgr %d \n",l_gr);
329 printf(" 2 : lgr %08x (%d) skippedLength %d\n",l_gr,l_gr, *skippedLength);
334 * \ingroup gdcmHeader
335 * \brief remet les octets dans un ordre compatible avec celui du processeur
337 * @return longueur retenue pour le champ
340 guint32 gdcmHeader::SWAP_LONG(guint32 a) {
341 // FIXME: il pourrait y avoir un pb pour les entiers negatifs ...
344 a=( ((a<<24) & 0xff000000) | ((a<<8) & 0x00ff0000) |
345 ((a>>8) & 0x0000ff00) | ((a>>24) & 0x000000ff) );
349 a=( ((a<<16) & 0xffff0000) | ((a>>16) & 0x0000ffff) );
353 a=( ((a<<8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) );
356 printf("\n\n\n *******\n erreur code swap ?!?\n\n\n");