Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals

dcmutil.c

Go to the documentation of this file.
00001 /************************************************************************* 00002 * $Id: dcmutil.c,v 1.4 2005/09/26 10:20:08 bellet Exp $ 00003 ************************************************************************** 00004 This software is governed by the CeCILL license under French law and 00005 abiding by the rules of distribution of free software. You can use, 00006 modify and/ or redistribute the software under the terms of the CeCILL 00007 license as circulated by CEA, CNRS and INRIA at the following URL 00008 "http://www.cecill.info". 00009 00010 As a counterpart to the access to the source code and rights to copy, 00011 modify and redistribute granted by the license, users are provided only 00012 with a limited warranty and the software's author, the holder of the 00013 economic rights, and the successive licensors have only limited 00014 liability. 00015 00016 In this respect, the user's attention is drawn to the risks associated 00017 with loading, using, modifying and/or developing or reproducing the 00018 software by the user in light of its specific status of free software, 00019 that may mean that it is complicated to manipulate, and that also 00020 therefore means that it is reserved for developers and experienced 00021 professionals having in-depth computer knowledge. Users are therefore 00022 encouraged to load and test the software's suitability as regards their 00023 requirements in conditions enabling the security of their systems and/or 00024 data to be ensured and, more generally, to use and operate it in the 00025 same conditions as regards security. 00026 00027 The fact that you are presently reading this means that you have had 00028 knowledge of the CeCILL license and that you accept its terms. 00029 00030 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de 00031 l'Image). All rights reserved. See License.txt for details. 00032 00033 Version 1.0 05/09/2005 00034 *************************************************************************/ 00035 00036 #include "idio.h" 00037 #include "iddicom.h" 00038 #include "iddcm-restricted.h" 00039 #include "iderr.h" 00040 #include <string.h> 00041 #include <stdlib.h> 00042 00043 #ifdef _MSC_VER 00044 #include <winsock.h> // Pour ntohs - BigEndianeries - 00045 #else 00046 #include <netinet/in.h> // Pour ntohs - BigEndianeries - 00047 #endif 00048 00049 #include "idliste.h" 00050 00051 char * _IdStrShowTransfertSyntax (char * codeTransfSynt); 00052 00053 #define LGR_ENTETE_A_LIRE 256 // on ne lit plus que le debut 00054 00055 #define DEBUG 0 00056 00057 00058 // ON NE DECORTIQUE PLUS LES SQ (trop long, trop dangereux, inutile) 00059 00060 static char * var_itoa(void * , int ); 00061 static char * _cleanString(char *); 00062 00063 static uint32_t _IdDcmRecupLgr(ID_DCM_HDR *, int, int*, int *); 00064 static int _IdDcmCheckSwap(ID_DCM_HDR *); 00065 static int _IdDcmLireEtStockerElement(ID_DCM_HDR *, char **, int, 00066 int, char *, int); 00067 char ** _IdDcmInquireImageInfoXXX (ID_DCM_HDR *, char **); 00068 00069 static void _setAcrLibido(ID_DCM_HDR *); 00070 00071 // ----------------------------------------------------------------- 00072 00079 ID_DCM_HDR * IdDcmHdrAlloc () { 00080 ID_DCM_HDR *e = (ID_DCM_HDR *) calloc (1, sizeof(ID_DCM_HDR)); 00081 if (!e) return e; 00082 00083 e->deb = (char *) malloc(LGR_ENTETE_A_LIRE); 00084 if (!e->deb) { 00085 free(e); 00086 printf("Echec alloc ID_DCM_HDR\n"); 00087 } 00088 00089 e->plist = IdLstAlloc(); 00090 00091 if (!e->plist) { 00092 free(e->deb); 00093 free(e); 00094 printf("Echec alloc ID_DCM_HDR->deb\n"); 00095 return (ID_DCM_HDR *)NULL; 00096 } 00097 return(e); 00098 } 00099 00100 // ------------------------------------------------------------------ 00108 void IdDcmHdrFree (ID_DCM_HDR * e) { 00109 00110 if (e) { 00111 if (e->deb) free(e->deb); 00112 if (e->plist) IdLstFree(e->plist); // LIBERER LES ELEMENTS DE LA LISTE AVANT 00113 free(e); 00114 } 00115 } 00116 00117 /* ======================================================================= 00118 * _IdDcmSWAP_SHORT 00119 * remet les octets dans un ordre compatible avec celui du processeur 00120 * ======================================================================= */ 00121 00122 short int _IdDcmSWAP_SHORT(short int a,int sw) { 00123 if ( (sw==4321) || (sw==2143) ) 00124 a =(((a<<8) & 0x0ff00) | ((a>>8)&0x00ff)); 00125 return (a); 00126 } 00127 00128 /* ======================================================================= 00129 * _IdDcmSWAP_LONG 00130 * remet les octets dans un ordre compatible avec celui du processeur 00131 * ======================================================================= */ 00132 00133 uint32_t _IdDcmSWAP_LONG(uint32_t a, int sw) { 00134 /* ATTENTION: il pourrait y avoir un pb pour les entiers negatifs ... 00135 * 00136 */ 00137 switch (sw) { 00138 case 4321 : 00139 a=( ((a<<24) & 0xff000000) | ((a<<8) & 0x00ff0000) | 00140 ((a>>8) & 0x0000ff00) | ((a>>24) & 0x000000ff) ); 00141 break; 00142 00143 case 3412 : 00144 a=( ((a<<16) & 0xffff0000) | ((a>>16) & 0x0000ffff) ); 00145 break; 00146 00147 case 2143 : 00148 a=( ((a<<8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) ); 00149 break; 00150 default : 00151 printf("\n\n\n *******\n erreur code swap ?!?\n\n\n"); 00152 a=0; 00153 } 00154 return(a); 00155 } 00156 00157 00158 #define DEBUG 0 00159 00160 // ----------------------------------------------------------------------------------- 00168 ID_DCM_HDR * IdDcmGetHeader(char *filename) { 00169 00170 ID_DCM_HDR *e=NULL; 00171 _ID_DCM_ELEM * ple; 00172 PLIST_ELEMENT plist_elem; 00173 unsigned int g, n, samplesPerPixel, raws, columns, bitsAllocated; 00174 char icone, icone_Trouvee; 00175 00176 00177 e = IdDcmHdrAlloc(); 00178 if(!e) { 00179 printf("echec alloc HDR \n"); 00180 return(NULL); 00181 } 00182 00183 if((e->fp=fopen(filename,ID_RFILE_BIN))==0) { // OK 00184 // IdDcmHdrAFree(e); 00185 printf ("echec ouverture %s\n",filename); 00186 return (NULL); 00187 } 00188 00189 e->filename = strdup(filename); 00190 00191 fseek(e->fp, 0L, SEEK_END); 00192 /* 00193 * obtains the current value of the file-position 00194 * indicator for the stream pointed to by stream 00195 */ 00196 e->taille_fich = ftell(e->fp); 00197 00198 if(DEBUG) printf("IdDcmGetHeader : lgr fich %f\n",(float)e->taille_fich); // FORMAT IMPRESSION long int ??? 00199 00200 rewind(e->fp); 00201 00202 e->sw= _IdDcmCheckSwap(e); 00203 00204 if(e->sw == -1) { // On est assure que c'est NON DICOM, NON ACR 00205 IdDcmHdrFree(e); 00206 return (NULL); 00207 } 00208 00209 e->__NumeroGroupePrecedent = 0; // Pour etre sur que le premier sera + grand 00210 e->grPixelTrouve = 0; 00211 e->PixelsTrouves = 0; 00212 00213 while ( (ple=_IdDcmReadNextElement(e,e->sw)) ) { 00214 IdLstAddLast(e->plist, ple); 00215 // --> 00216 // --> Pour tester 00217 //if(e->PixelsTrouves) break; 00218 } 00219 00220 // une fois le DCM-Header charge en memoire, 00221 // on recherche les caracteristiques eventuelle 00222 // d'une 'icone' 00223 00224 icone=0; 00225 00226 plist_elem = IdLstFirst(e->plist); 00227 while ( plist_elem != NULL) { 00228 ple = IdLstPtrObj(plist_elem); 00229 g= ple->Gr; 00230 n=ple->Num; 00231 if (g > 0x0008 && n > 0x2112 ) break; // depasse : pas d'icone 00232 00233 if (g == 0x0008 && n == 0x2112) { // Source Image Sequence : 00234 icone=1; 00235 break; 00236 } 00237 plist_elem=IdLstNext(plist_elem); 00238 } 00239 00240 icone_Trouvee=0; 00241 if (icone == 1 ) { 00242 00243 printf ("rech iconeTrouvee\n"); 00244 00245 while ( plist_elem != NULL) { 00246 ple = IdLstPtrObj(plist_elem); 00247 g= ple->Gr; 00248 n= ple->Num; 00249 00250 if (g != 0xfffe && (g > 0x0088 && n > 0x0200)) break; // du soucis a se faire si on sort par ici 00251 if (g == 0x0088 && n == 0x0200) { // Icone Image Sequence 00252 icone_Trouvee=1; 00253 break; 00254 } 00255 plist_elem=IdLstNext(plist_elem); 00256 } 00257 } 00258 00259 if (icone_Trouvee == 1 ) { 00260 00261 printf ("rech valeurs\n"); 00262 00263 while ( plist_elem != NULL) { 00264 ple = IdLstPtrObj(plist_elem); 00265 g= ple->Gr; 00266 if ( g != 0xfffe && g > 0x0088) break; // on a du tous les trouver 00267 n=ple->Num; 00268 // on est dans la SQ, group vaut 0008 ... 00269 if (n == 0x0002) samplesPerPixel = str2num(ple->valeurElem,unsigned short int); 00270 else if (n == 0x0010) raws = str2num(ple->valeurElem,unsigned short int); 00271 else if (n == 0x0011) columns = str2num(ple->valeurElem,unsigned short int); 00272 else if (n == 0x0100) bitsAllocated = str2num(ple->valeurElem,unsigned short int); 00273 00274 plist_elem = IdLstNext(plist_elem); 00275 } 00276 } 00277 00278 // on ajuste PixelPosition, pour 'sauter' l'icone. 00279 if (icone_Trouvee) { 00280 00281 // PAS SUFFISANT : il y a des Koshon'ries apres les pixels imagette ! 00282 00283 printf ("samplesPerPixel %d raws %d columns %d bitsAllocated %d\n", 00284 samplesPerPixel, raws, columns, bitsAllocated); 00285 printf("pixelPosition %d x(%x) \n", 00286 e->PixelPosition,e->PixelPosition); 00287 e->PixelPosition += samplesPerPixel * raws * columns * bitsAllocated / 8; 00288 printf("pixelPosition %d x(%x)\n",e->PixelPosition, e->PixelPosition); 00289 } 00290 00291 // Positionnement ACR_LIBIDO 00292 00293 _setAcrLibido(e); 00294 00295 fclose(e->fp); 00296 return (e); 00297 } 00298 00299 static void _setAcrLibido(ID_DCM_HDR *e) { 00300 00301 _ID_DCM_ELEM * ple; 00302 PLIST_ELEMENT plelem; 00303 PLIST pl; 00304 00305 // Positionnement ACR_LIBIDO 00306 if(DEBUG) printf("Entree ds _setAcrLibido\n"); 00307 00308 e->ACR_LIBIDO = 0; 00309 if ( e->__TrueDicom == 0) { 00310 // Recognition Code --> n'existe plus en DICOM V3 ... 00311 00312 pl = e->plist; 00313 plelem = IdLstFirst(pl); 00314 while (plelem) { 00315 ple= IdLstPtrObj(plelem); 00316 if(DEBUG) printf("gr %04x Num %04x\n", ple->Gr, ple->Num); 00317 if(ple->Gr > 0x0008) break; // On a depasse 00318 if(ple->Gr == 0x0008) { 00319 if(ple->Num > 0x0010) break; // On a depasse 00320 if(ple->Num == 0x0010) { 00321 if ( (memcmp(ple->valeurElem,"ACRNEMA_LIBIDO",14)==0) 00322 // si c'est egal 00323 || (memcmp(ple->valeurElem,"CANRME_AILIBOD",14)==0)) { 00324 // en cas d'objet ACRLibido fait sr 1 autre machine) 00325 e->ACR_LIBIDO =1; 00326 } // fin if memcmp 00327 break; 00328 } // fin if ple->Num==0x0010 00329 } // fin ple->Gr==0x0008 00330 plelem = IdLstNext(plelem); 00331 } // fin while 00332 } // fin if TrueDicom 00333 00334 if(DEBUG) printf("ACR_LIBIDO = %d\n", e->ACR_LIBIDO); 00335 return; 00336 } 00337 /* ======================================================================= 00338 * _IdDcmRecupLgr 00339 * 00340 * ACR-NEMA : On a toujours 00341 * GroupNumber (2 Octets) 00342 * ElementNumber (2 Octets) 00343 * ElementSize (4 Octets) 00344 * 00345 * 00346 * DICOM : On peut avoir (implicit Value Representation) 00347 * GroupNumber (2 Octets) 00348 * ElementNumber (2 Octets) 00349 * ElementSize (4 Octets) 00350 * 00351 * On peut avoir (explicit Value Representation) 00352 * GroupNumber (2 Octets) 00353 * ElementNumber (2 Octets) 00354 * ValueRepresentation (2 Octets) 00355 * ElementSize (2 Octets) 00356 * 00357 * ATTENTION : dans le cas ou ValueRepresentation = OB, OW, SQ, UN 00358 * GroupNumber (2 Octets) 00359 * ElementNumber (2 Octets) 00360 * ValueRepresentation (2 Octets) 00361 * zone reservee (2 Octets) 00362 * ElementSize (4 Octets) 00363 * 00364 * 00365 * ======================================================================= */ 00380 static uint32_t _IdDcmRecupLgr(ID_DCM_HDR *e, int sw, int *skippedLength, int *longueurLue) { 00381 uint32_t l_gr; 00382 unsigned short int l_gr_2; 00383 int i, trouve; 00384 char VR[5]; 00385 int lgrLue; 00386 00387 // ID_DCM_HDR *e sert uniquement de passe-plat pour __ExplicitVR 00388 00389 00390 if (e->__ExplicitVR == 1) { 00391 lgrLue=fread (&VR, (size_t)2,(size_t)1, e->fp); 00392 VR[2]=0; 00393 00394 // ATTENTION : 00395 // Ce n'est pas parce qu'on a trouve UL la premiere fois qu'on respecte 00396 // Explicit VR tout le temps 00397 // (cf e=film ...) 00398 00399 //for(i=0,trouve=0;i<nbCode;i++) { 00400 00401 for(i=0,trouve=0;_ID_dicom_vr[i].dicom_VR != NULL ;i++) { 00402 if(memcmp(_ID_dicom_vr[i].dicom_VR,VR,(size_t)2)==0) { 00403 (e->pleCourant)->VR=_ID_dicom_vr[i].dicom_VR; 00404 trouve=1; 00405 break; 00406 } 00407 } 00408 00409 if ( trouve == 0) { 00410 00411 // On est mal : implicit VR repere 00412 // mais ce n'est pas un code connu ... 00413 // On reconstitue la longueur 00414 00415 if(DEBUG) printf("IdDcmRecupLgr : Explicit VR, mais pas trouve de code connu\n"); 00416 memcpy(&l_gr, VR,(size_t)2); 00417 00418 lgrLue=fread ( ((char*)&l_gr)+2, (size_t)2, (size_t)1, e->fp); 00419 00420 if(sw) l_gr = _IdDcmSWAP_LONG(((uint32_t)l_gr),sw); 00421 00422 if(DEBUG) printf("IdDcmRecupLgr : lgr deduite : %08x , %d\n",l_gr,l_gr); 00423 00424 *longueurLue=l_gr; 00425 if ( (int)l_gr == -1) { 00426 l_gr=0; 00427 } 00428 *skippedLength = 4; 00429 if (DEBUG) printf(" 1 : lgr %08x (%d )skippedLength %d\n",l_gr,l_gr, *skippedLength); 00430 return(l_gr); 00431 } 00432 00433 // On repart dans la sequence 'sensee' 00434 00435 if(DEBUG) printf("VR : [%01x , %01x] (%c%c) en position %d du tableau\n", VR[0],VR[1],VR[0],VR[1],i); 00436 //printf(" %d , %s\n", i,_ID_dicom_vr[i].dicom_VR); 00437 00438 if ( 00439 (!memcmp( VR,"OB",(size_t)2 )) || 00440 (!memcmp( VR,"OW",(size_t)2 )) || 00441 (!memcmp( VR,"SQ",(size_t)2 )) || 00442 (!memcmp( VR,"UN",(size_t)2 )) ) { 00443 00444 // les 2 octets suivants sont reserves 00445 00446 if(DEBUG) printf("IdDcmRecupLgr : les 2 octets suivants sont reserves\n"); 00447 //on les saute 00448 fseek(e->fp, 2L,SEEK_CUR); 00449 00450 //on lit la lgr sur QUATRE octets 00451 00452 lgrLue=fread (&l_gr, (size_t)4,(size_t)1, e->fp); 00453 00454 if(sw) l_gr = _IdDcmSWAP_LONG(((uint32_t)l_gr),sw); 00455 *skippedLength = 8; 00456 00457 } else { 00458 //on lit la lgr sur DEUX octets 00459 00460 lgrLue=fread (&l_gr_2, (size_t)2,(size_t)1, e->fp); 00461 00462 if(sw) l_gr_2 = _IdDcmSWAP_SHORT((unsigned short)l_gr_2,sw); 00463 00464 *longueurLue=l_gr_2; 00465 00466 if ( l_gr_2 == 0xffff) { 00467 l_gr = 0; 00468 } else { 00469 l_gr = l_gr_2; 00470 } 00471 *skippedLength = 4; 00472 } 00473 } else { // Explicit VR = 0 00474 00475 //on lit la lgr sur QUATRE octets 00476 00477 lgrLue=fread (&l_gr, (size_t)4,(size_t)1, e->fp); 00478 00479 if(sw)l_gr=_IdDcmSWAP_LONG(((long)l_gr),sw); 00480 *skippedLength = 4; 00481 } 00482 00483 *longueurLue=l_gr; 00484 00485 // Traitement des curiosites sur la longueur 00486 00487 if ( (int)l_gr == 0xffffffff) 00488 l_gr=0; 00489 00490 if(!memcmp( VR,"SQ",(size_t)2 )) { // ca annonce une SEQUENCE d'items ?! 00491 00492 //l_gr=0; // on lira donc les items de la sequence 00493 00494 // devrait permettre de SAUTER toures les SQ 00495 00496 if (DEBUG) printf(" SQ trouve : lgr %d \n",l_gr); 00497 } 00498 00499 if (DEBUG) printf(" 2 : lgr %08x (%d) skippedLength %d\n",l_gr,l_gr, *skippedLength); 00500 return(l_gr); 00501 } 00502 00503 /* ======================================================================= 00504 _IdDcmReadNextElement 00505 00506 lit l'acr_element courant 00507 le fichier doit deja avoir ete ouvert, 00508 00509 ======================================================================= */ 00510 00511 00525 _ID_DCM_ELEM * _IdDcmReadNextElement(ID_DCM_HDR * e, int sw) { 00526 unsigned short g; 00527 unsigned short n; 00528 uint32_t l; 00529 long int posFich; 00530 int skL; 00531 size_t lgrLue; 00532 _ID_DCM_ELEM *nouvDcmElem; 00533 00534 if (DEBUG) printf(" ===> entree ds _IdDcmReadNextElement\n"); 00535 00536 if(e->offsetCourant == e->taille_fich) { // On a atteint la fin du fichier 00537 if (DEBUG) printf(" On a atteint la fin du fichier\n"); 00538 return(NULL); 00539 } else { 00540 if (DEBUG) { 00541 posFich = ftell(e->fp); 00542 printf("lgrFich %f positionDsFich %f offset courant %f x(%x)\n", 00543 (float)e->taille_fich, 00544 (float)posFich, 00545 (float)e->offsetCourant, 00546 e->offsetCourant); 00547 } 00548 } 00549 00550 nouvDcmElem = (_ID_DCM_ELEM *)malloc(sizeof(_ID_DCM_ELEM)); 00551 if (!nouvDcmElem) { 00552 printf("Echec alloc _ID_DCM_ELEM *nouvDcmElem\n"); 00553 return(NULL); 00554 } 00555 00556 e->pleCourant = nouvDcmElem; 00557 00558 // ------------------------- Lecture Num group : g 00559 00560 lgrLue=fread (&g, (size_t)2,(size_t)1, e->fp); 00561 00562 if (feof(e->fp)) { 00563 if (DEBUG) printf("_IdDcmReadNextElement : eof trouve\n"); 00564 return (NULL); 00565 } 00566 if (ferror(e->fp)){ 00567 if (DEBUG) printf(" IdDcmReadNextElement : echec lecture NumGr\n"); 00568 return (NULL); 00569 } 00570 00571 if (DEBUG) printf("_IdDcmReadNextElement : " 00572 " gr %04x\n",g ); 00573 00574 if (sw) g=_IdDcmSWAP_SHORT(((short)g),sw); 00575 00576 nouvDcmElem->Gr=g; 00577 e->__NumeroGroupePrecedent =g; 00578 00579 // ------------------------- Lecture Num Elem : n 00580 00581 lgrLue=fread (&n, (size_t)2,(size_t)1, e->fp); 00582 00583 if (feof(e->fp)) { 00584 if (DEBUG) printf("_IdDcmReadNextElement : eof trouve\n"); 00585 return (NULL); 00586 } 00587 if (ferror(e->fp)){ 00588 if (DEBUG) printf(" IdDcmReadNextElement : echec lecture NumElem\n"); 00589 return (NULL); 00590 } 00591 00592 if (DEBUG) printf("_IdDcmReadNextElement : " 00593 " num %04x\n",n ); 00594 00595 if(sw)n=_IdDcmSWAP_SHORT(((short)n),sw); 00596 nouvDcmElem->Num=n; 00597 00598 // ------------------------- Lecture longueur element : l 00599 00600 l = _IdDcmRecupLgr(e, sw, &skL, &nouvDcmElem->LgrLueElem); 00601 00602 if(g==0xfffe) l=0; // pour sauter les indicateurs de 'SQ' 00603 00604 nouvDcmElem->LgrElem=l; 00605 00606 if (DEBUG) if (n!=0) printf("_IdDcmReadNextElement : " 00607 " gr %04x\tnum %04x\tlong %08x (%d)\n", 00608 g,n,l,l); 00609 00610 // ------------------------- Lecture Valeur element 00611 00612 nouvDcmElem->valeurElem = malloc(l+1); 00613 if(nouvDcmElem->valeurElem) { 00614 nouvDcmElem->valeurElem[l]= 0; 00615 } else { 00616 if (DEBUG) printf(" IdDcmReadNextElement : echec Alloc valeurElem lgr : %d\n",l); 00617 return (NULL); 00618 } 00619 00620 // ------------------------ On amene en mémoire y compris les Elem 'tres longs' 00621 00622 lgrLue=fread (nouvDcmElem->valeurElem, (size_t)l,(size_t)1, e->fp); 00623 00624 e->offsetCourant += 2 + 2 + skL; // gr + num + lgr 00625 nouvDcmElem->Offset = e->offsetCourant; 00626 e->offsetCourant += l; // debut elem suivant 00627 00628 00629 // ------------------------- Doit-on le Swapper ? 00630 00631 00632 if ((n==0) && sw) { // n=0 : lgr du groupe : uint32_t 00633 *(uint32_t *) nouvDcmElem->valeurElem = 00634 _IdDcmSWAP_LONG ((*(uint32_t *) nouvDcmElem->valeurElem),sw); 00635 nouvDcmElem->Swap = 1; 00636 } else { 00637 if(sw) { 00638 if ( (g/2)*2-g==0) { /* on ne teste pas les groupes impairs */ 00639 00640 if ((l==4)||(l==2)) { /*pour ne s'interroger que sur les elements 00641 de lgr =2 ou =4 */ 00642 00643 // On a deja trouve la VR lors de RecupLgr 00644 // On la reutilise 00645 00646 if ( (strcmp(nouvDcmElem->VR,"UL") ==0) 00647 || (strcmp(nouvDcmElem->VR,"US") ==0) 00648 || (strcmp(nouvDcmElem->VR,"SL") ==0) 00649 || (strcmp(nouvDcmElem->VR,"SS") ==0) 00650 || (g == 0x0028 && 00651 ( n == 0x0005 || n == 0x0200) ) ) { // seuls (28,5) de vr RET 00652 // et (28,200) sont des entiers 00653 // ... jusqu'a preuve du contraire 00654 nouvDcmElem->Swap = 1; 00655 00656 if(l==4) { 00657 *(uint32_t *) nouvDcmElem->valeurElem= 00658 _IdDcmSWAP_LONG ((*(uint32_t *) nouvDcmElem->valeurElem),sw); 00659 nouvDcmElem->valInt = 00660 _IdDcmSWAP_LONG ((*(uint32_t *) nouvDcmElem->valeurElem),sw); 00661 } else { 00662 if(l==2) 00663 *(unsigned short *) nouvDcmElem->valeurElem= 00664 _IdDcmSWAP_SHORT ((*(unsigned short *)nouvDcmElem->valeurElem),sw); 00665 00666 nouvDcmElem->valShort = 00667 _IdDcmSWAP_SHORT ((*(unsigned short *)nouvDcmElem->valeurElem),sw); 00668 } 00669 } 00670 } /* fin if l==2 ==4 */ 00671 } /* fin if g pair */ 00672 } /* fin sw */ 00673 } 00674 00675 // ------------------------- A-t-on trouve l'info donnant le 'num groupe' des Pixels ? 00676 00677 00678 if (!e->grPixelTrouve) { // on n a pas encore trouve les pixels 00679 00680 if ( (g == 0x0028 && n > 0x0200) || g > 0x0028 ) { // on a depasse (28,200) 00681 e->grPixel = 0x7FE0; 00682 e->numPixel = 0x0010; 00683 e->grPixelTrouve = 1; 00684 if (DEBUG) printf("-----------------par defaut, en %04x %04x :-------grPixel %04x numPixel %04x\n", 00685 g,n,e->grPixel,e->numPixel); 00686 } else { // on est sur (28,200) 00687 if (g == 0x0028) { 00688 if (n == 0x0200) { 00689 e->grPixelTrouve = 1; 00690 00691 *(unsigned short *)nouvDcmElem->valeurElem= 00692 _IdDcmSWAP_SHORT ((*(unsigned short *)nouvDcmElem->valeurElem),sw); 00693 00694 e->grPixel = str2num(nouvDcmElem->valeurElem, short int); 00695 00696 00697 if (e->grPixel == 0xE07F) { 00698 e->grPixel=0x7FE0; 00699 } 00700 00701 if (DEBUG) printf("-----------28 200 trouve-------------GrPixel %04x\n", 00702 e->grPixel); 00703 00704 if (e->grPixel != 0x7FE0) // Vieux pb Philips 00705 e->numPixel = 0x1010; // encore utile ?? 00706 else 00707 e->numPixel = 0x0010; 00708 if (DEBUG) printf("------------------------grPixel %04x numPixel %04x\n", 00709 e->grPixel,e->numPixel); 00710 } 00711 } 00712 } 00713 } else { // on vient de trouver les pixels 00714 if (g == e->grPixel) { 00715 if (n == e->numPixel) { 00716 e->PixelPosition = nouvDcmElem->Offset; 00717 e->PixelsTrouves = 1; 00718 if (DEBUG) printf(" \t===x=> Pixels Trouves en %d\n",e->PixelPosition); 00719 } 00720 } 00721 } 00722 e->nbElem ++; 00723 if (DEBUG) printf("nb Elem %d\n",e->nbElem); 00724 return(nouvDcmElem); 00725 } 00726 00727 00728 #define DEBUG 0 00729 00730 /* ============================================================================ 00731 00732 SPESHEUL FUNKSHEUNZ TO READ NAADIN ZOBOROMOK LEONARDO IMAGES 00733 00734 N.B. : LEONARDO, c'est la console Siemens . 00735 Pendant plusieurs mois, les entetes des images etaient verolees 00736 Des longueurs de Champs etaient fausses 00737 Ces deux fonctions ne servent qu'a pouvoir relire ces images 00738 (on ne les a pas conservées sous une autre forme :-( 00739 00740 ============================================================================= */ 00741 00742 00743 00744 /* ======================================================================= 00745 _IdDcmReadNextElementLeonardo 00746 00747 lit l'acr_element courant (Special images foirées Leonardo) 00748 le fichier doit deja avoir ete ouvert, 00749 00750 ======================================================================= */ 00751 00763 //_ID_DCM_ELEM * _IdDcmReadNextElement(ID_DCM_HDR * e, int sw) { 00764 00765 _ID_DCM_ELEM * _IdDcmReadNextElementLeonardo(ID_DCM_HDR * e, int sw) { 00766 unsigned short g; 00767 unsigned short n; 00768 uint32_t l; 00769 long int posFich; 00770 int skL; 00771 size_t lgrLue; 00772 int i; 00773 _ID_DCM_ELEM *nouvDcmElem; 00774 00775 if (DEBUG) printf(" ===> entree ds _IdDcmReadNextElement\n"); 00776 00777 if(e->offsetCourant == e->taille_fich) { // On a atteint la fin du fichier 00778 if (DEBUG) printf(" On a atteint la fin du fichier\n"); 00779 return(NULL); 00780 } else { 00781 if (DEBUG) { 00782 posFich = ftell(e->fp); 00783 printf("lgrFich %f positionDsFich %f offset courant %f\n", 00784 (float)e->taille_fich, 00785 (float)posFich, 00786 (float)e->offsetCourant); 00787 } 00788 } 00789 00790 nouvDcmElem = (_ID_DCM_ELEM *)malloc(sizeof(_ID_DCM_ELEM)); 00791 if (!nouvDcmElem) { 00792 printf("Echec alloc _ID_DCM_ELEM *nouvDcmElem\n"); 00793 return(NULL); 00794 } 00795 00796 e->pleCourant = nouvDcmElem; 00797 00798 // ------------------------- Lecture Num group : g 00799 00800 lgrLue=fread (&g, (size_t)2,(size_t)1, e->fp); 00801 00802 if (feof(e->fp)) { 00803 if (DEBUG) printf("_IdDcmReadNextElement : eof trouve\n"); 00804 return (NULL); 00805 } 00806 if (ferror(e->fp)){ 00807 if (DEBUG) printf(" IdDcmReadNextElement : echec lecture NumGr\n"); 00808 return (NULL); 00809 } 00810 00811 if (DEBUG) printf("_IdDcmReadNextElement : " 00812 " gr %04x\n",g ); 00813 00814 if (sw) g=_IdDcmSWAP_SHORT(((short)g),sw); 00815 00816 nouvDcmElem->Gr=g; 00817 e->__NumeroGroupePrecedent =g; 00818 00819 // ------------------------- Lecture Num Elem : n 00820 00821 lgrLue=fread (&n, (size_t)2,(size_t)1, e->fp); 00822 00823 if (feof(e->fp)) { 00824 if (DEBUG) printf("_IdDcmReadNextElement : eof trouve\n"); 00825 return (NULL); 00826 } 00827 if (ferror(e->fp)){ 00828 if (DEBUG) printf(" IdDcmReadNextElement : echec lecture NumElem\n"); 00829 return (NULL); 00830 } 00831 00832 if (DEBUG) printf("_IdDcmReadNextElement : " 00833 " num %04x\n",n ); 00834 00835 if(sw)n=_IdDcmSWAP_SHORT(((short)n),sw); 00836 nouvDcmElem->Num=n; 00837 00838 // ------------------------- Lecture longueur element : l 00839 00840 l = _IdDcmRecupLgr(e, sw, &skL, &nouvDcmElem->LgrLueElem); 00841 00842 00843 // ---------------- images delirantes LEONARDO 00844 00845 if( (nouvDcmElem->Gr == 0x0009) && ( (nouvDcmElem->Num == 0x1113) || (nouvDcmElem->Num == 0x1114) ) ) 00846 { 00847 00848 if (DEBUG) printf ("gr %04x num %04x LgrElem %d\n", 00849 nouvDcmElem->Gr, nouvDcmElem->Num, nouvDcmElem->LgrElem); 00850 l=4; 00851 nouvDcmElem->LgrElem =4; 00852 nouvDcmElem->LgrLueElem =4; 00853 } 00854 00855 // ---------------fin LEONARDO --------------------------------------------------- 00856 00857 if(g==0xfffe) l=0; // pour sauter les indicateurs de 'SQ' 00858 00859 nouvDcmElem->LgrElem=l; 00860 00861 if (DEBUG) if (n!=0) printf("_IdDcmReadNextElement : " 00862 " gr %04x\tnum %04x\tlong %08x (%d)\n", 00863 g,n,l,l); 00864 00865 // ------------------------- Lecture Valeur element 00866 00867 nouvDcmElem->valeurElem = malloc(l+1); 00868 if(nouvDcmElem->valeurElem) { 00869 nouvDcmElem->valeurElem[l]= 0; 00870 } else { 00871 if (DEBUG) printf(" IdDcmReadNextElement : echec Alloc valeurElem lgr : %d\n",l); 00872 return (NULL); 00873 } 00874 00875 // ------------------------ On amene en mémoire y compris les Elem 'tres longs' 00876 00877 lgrLue=fread (nouvDcmElem->valeurElem, (size_t)l,(size_t)1, e->fp); 00878 00879 e->offsetCourant += 2 + 2 + skL; // gr + num + lgr 00880 nouvDcmElem->Offset = e->offsetCourant; 00881 e->offsetCourant += l; // debut elem suivant 00882 00883 // ------------------------- Doit-on le Swapper ? 00884 00885 00886 if ((n==0) && sw) { // n=0 : lgr du groupe : uint32_t 00887 *(uint32_t *) nouvDcmElem->valeurElem = 00888 _IdDcmSWAP_LONG ((*(uint32_t *) nouvDcmElem->valeurElem),sw); 00889 nouvDcmElem->Swap = 1; 00890 } else { 00891 if(sw) { 00892 if ( (g/2)*2-g==0) { /* on ne teste pas les groupes impairs */ 00893 00894 if ((l==4)||(l==2)) { /*pour eviter de swapper les chaines 00895 de lgr 2 ou 4 */ 00896 00897 // On a deja trouve la VR lors de RecupLgr 00898 // On la reutilise 00899 00900 if ( (strcmp(nouvDcmElem->VR,"UL") ==0) 00901 || (strcmp(nouvDcmElem->VR,"US") ==0) 00902 || (strcmp(nouvDcmElem->VR,"SL") ==0) 00903 || (strcmp(nouvDcmElem->VR,"SS") ==0) 00904 || (g == 0x0028 && 00905 ( n == 0x0005 || n == 0x0200) ) ) { // seuls (28,5) de vr RET 00906 // et (28,200) sont des entiers 00907 // ... jusqu'a preuve du contraire 00908 nouvDcmElem->Swap = 1; 00909 00910 if(l==4) { 00911 *(uint32_t *) nouvDcmElem->valeurElem= 00912 _IdDcmSWAP_LONG ((*(uint32_t *) nouvDcmElem->valeurElem),sw); 00913 nouvDcmElem->valInt = 00914 _IdDcmSWAP_LONG ((*(uint32_t *) nouvDcmElem->valeurElem),sw); 00915 } else { 00916 if(l==2) 00917 *(unsigned short *) nouvDcmElem->valeurElem= 00918 _IdDcmSWAP_SHORT ((*(unsigned short *)nouvDcmElem->valeurElem),sw); 00919 nouvDcmElem->valShort = 00920 _IdDcmSWAP_SHORT ((*(unsigned short *)nouvDcmElem->valeurElem),sw); 00921 } 00922 } 00923 } /* fin if l==2 ==4 */ 00924 } /* fin if g pair */ 00925 } /* fin sw */ 00926 } 00927 00928 // ------------------------- A-t-on trouve l'info donnant le 'num groupe' des Pixels ? 00929 00930 if (!e->grPixelTrouve) { // on n a pas encore trouve les pixels 00931 if (g > 0x0028) { 00932 if (n > 0x0200 || g == 0x7FE0 ) { // on a depasse (28,200) 00933 e->grPixel = 0x7FE0; 00934 e->numPixel = 0x0010; 00935 e->grPixelTrouve = 1; 00936 if (DEBUG) printf("------------------------grPixel %04x numPixel %04x\n", 00937 e->grPixel,e->numPixel); 00938 } 00939 00940 } else { // on est sur (28,200) 00941 if (g == 0x0028) { 00942 if (n == 0x0200) { 00943 e->grPixelTrouve = 1; 00944 for(i=0;i<4;i++) 00945 *((char*)(&e->grPixel)+i) = *(nouvDcmElem->valeurElem+i); 00946 00947 00948 if (DEBUG) printf("------------------------GrPixel %04x\n", 00949 e->grPixel); 00950 00951 if (e->grPixel != 0x7FE0) // Vieux pb Philips 00952 e->numPixel = 0x1010; // encore utile ?? 00953 else 00954 e->numPixel = 0x0010; 00955 if (DEBUG) printf("------------------------grPixel %04x numPixel %04x\n", 00956 e->grPixel,e->numPixel); 00957 } 00958 } 00959 } 00960 } else { // on vient de trouver les pixels 00961 if (g == e->grPixel) { 00962 if (n == e->numPixel) { 00963 e->PixelPosition = nouvDcmElem->Offset; 00964 e->PixelsTrouves = 1; 00965 /*if (DEBUG)*/printf(" \t=$$$$$$$==> Pixels Trouves en %d\n",e->PixelPosition); 00966 } 00967 } 00968 } 00969 e->nbElem ++; 00970 return(nouvDcmElem); 00971 } 00972 00973 00974 // ----------------------------------------------------------------------------------- 00982 ID_DCM_HDR * IdDcmGetHeaderLeonardo(char *filename) { 00983 00984 ID_DCM_HDR *e=NULL; 00985 _ID_DCM_ELEM * ple; 00986 00987 e = IdDcmHdrAlloc(); 00988 if(!e) { 00989 printf("echec alloc HDR \n"); 00990 return(NULL); 00991 } 00992 00993 if((e->fp=fopen(filename,ID_RFILE_BIN))==0) { // OK 00994 // IdDcmHdrAFree(e); 00995 printf ("echec ouverture %s\n",filename); 00996 return (NULL); 00997 } 00998 00999 e->filename = strdup(filename); 01000 01001 fseek(e->fp, 0L, SEEK_END); 01002 /* 01003 * obtains the current value of the file-position 01004 * indicator for the stream pointed to by stream 01005 */ 01006 e->taille_fich = ftell(e->fp); 01007 01008 if(DEBUG) printf("IdDcmGetHeader : lgr fich %f\n",(float)e->taille_fich); // FORMAT IMPRESSION long int ??? 01009 01010 rewind(e->fp); 01011 01012 e->sw= _IdDcmCheckSwap(e); 01013 e->__NumeroGroupePrecedent = 0; // Pour etre sur que le premier sera + grand 01014 e->grPixelTrouve = 0; 01015 e->PixelsTrouves = 0; 01016 01017 01018 while ( (ple=_IdDcmReadNextElementLeonardo(e,e->sw)) ) { 01019 IdLstAddLast(e->plist, ple); 01020 } 01021 01022 // Positionnement ACR_LIBIDO 01023 01024 _setAcrLibido(e); 01025 01026 fclose(e->fp); 01027 return (e); 01028 } 01029 01030 01031 01032 /* ============================================================================ 01033 01034 END OF SPESHEUL FUNKSHEUNZ TO READ NAADIN ZOBOROMOK LEONARDO IMAGES 01035 01036 ============================================================================= */ 01037 01038 01039 01040 /* ======================================================================= 01041 01042 _IdDcmCheckSwap 01043 La seule maniere sure que l'on aie pour determiner 01044 si on est en LITTLE_ENDIAN, BIG-ENDIAN, 01045 BAD-LITTLE-ENDIAN, BAD-BIG-ENDIAN 01046 est de trouver l'element qui donne la longueur d'un 'GROUP' 01047 (on sait que la longueur de cet element vaut 0x00000004) 01048 et de regarder comment cette longueur est codee en memoire 01049 01050 Le probleme vient de ce que parfois, il n'y en a pas ... 01051 01052 On fait alors le pari qu'on a a faire a du LITTLE_ENDIAN propre. 01053 (Ce qui est la norme -pas respectee- depuis ACR-NEMA) 01054 Si ce n'est pas le cas, on ne peut rien faire. 01055 01056 (il faudrait avoir des fonctions auxquelles 01057 on passe le code Swap en parametre, pour faire des essais 'manuels') 01058 01059 ======================================================================= */ 01060 01061 static int 01062 _IdDcmCheckSwap(ID_DCM_HDR * e) { 01063 uint32_t s, x=4; // x : pour ntohs 01064 01065 int sw; 01066 int lgrLue; 01067 char * entCur; 01068 char deb[LGR_ENTETE_A_LIRE]; 01069 short int shortS; 01070 01071 01072 // On teste le processeur 01073 01074 if (x==(x)) { /* si le HostByteOrder est le meme que le NetworkByteOrder */ 01075 e->net2host = 1; 01076 } else { 01077 e->net2host = 0; 01078 } 01079 01080 //printf("\t\t\t\te->net2host %d \n",e->net2host); 01081 01082 /* On commence par verifier si c'est du DICOM 'actuel' */ 01083 /* ------------- */ 01084 01085 lgrLue = fread(deb,1,LGR_ENTETE_A_LIRE,e->fp); 01086 01087 entCur = deb+128; 01088 if(memcmp(entCur, "DICM", (size_t)4) == 0) { 01089 e->__TrueDicom=1; 01090 if (DEBUG) printf ("_IdDcmCheckSwap : C est du DICOM actuel \n"); 01091 } else { 01092 e->__TrueDicom=0; 01093 if (DEBUG) printf ("_IdDcmCheckSwap : Ce n'est PAS du DICOM actuel\n"); 01094 } 01095 01096 if(e->__TrueDicom) { 01097 entCur = deb+136; /* on saute le File Preamble (souvent a ZERO) : 128 Octets */ 01098 /* le DICM, et le 0002, 0000 ou le 0002, 0001 */ 01099 if( (memcmp(entCur, "UL", (size_t)2) == 0) || 01100 (memcmp(entCur, "OB", (size_t)2) == 0) ) 01101 { 01102 /* les 2 premiers octets de la lgr peuvent valoir UL --> Explicit VR */ 01103 e->__ExplicitVR = 1; 01104 if (DEBUG) printf ("_IdDcmCheckSwap : Explicit VR\n"); 01105 } else { 01106 e->__ExplicitVR = 0; 01107 if (DEBUG) printf ("_IdDcmCheckSwap : PAS Explicit VR\n"); 01108 } 01109 01110 if (e->net2host == 0) { /* si le HostByteOrder est different du NetworkByteOrder */ 01111 sw = 0; /* on est sur PC ou DEC --> LITTLE-ENDIAN -> Rien a faire */ 01112 if (DEBUG) printf("HostByteOrder = NetworkByteOrder\n"); 01113 01114 } else { /* on est sur une Sun ou une SGI */ 01115 sw = 4321; 01116 if (DEBUG) printf("HostByteOrder != NetworkByteOrder\n"); 01117 } 01118 01119 rewind(e->fp); 01120 fseek (e->fp, 132L, SEEK_SET); //On se positionne sur le debut des info 01121 e->offsetCourant=132; 01122 return sw; 01123 01124 } /* fin TrueDicom */ 01125 01126 /* ----- SINON ----- */ 01127 01128 /* Si c'est de l'ACR 'propre', la lgr du premier element du groupe est FORCEMENT 4 */ 01129 01130 entCur=deb + 4; 01131 s=str2num(entCur,int); 01132 01133 switch (s) { 01134 case 0x00040000 : 01135 sw=3412; if(DEBUG) printf("s : %08x sw : %d\n",s,sw); 01136 break; 01137 case 0x04000000 : 01138 sw=4321; if(DEBUG) printf("s : %08x sw : %d\n",s,sw); 01139 break; 01140 case 0x00000400 : 01141 sw=2143; if(DEBUG) printf("s : %08x sw : %d\n",s,sw); 01142 break; 01143 case 0x00000004 : 01144 sw=0; if(DEBUG) printf("s : %08x sw : %d\n",s,sw); 01145 break; 01146 default : 01147 sw = -1; 01148 if (DEBUG) printf (" Pas trouve l info de Swap; On va parier\n"); 01149 } 01150 01151 /* Si c'est de l'ACR 'pas propre', il manque la lgr du groupe */ 01152 01153 if(sw==-1) { 01154 /* On n'a pas trouve l'info de swap (lgr de l'elem (0008,0000) = 4) */ 01155 /* Si c'est du VRAI ACR NEMA on DOIT trouver le numero du premier groupe : 0008 */ 01156 /* Les seules possibilités sont (Good)BigEndian,(Good)LittleEndian 01157 */ 01158 01159 shortS=str2num(deb,short int); 01160 01161 switch (shortS) { 01162 case 0x0008 : 01163 sw=0; 01164 if(DEBUG) printf("shortS : %04x sw : %d\n",shortS,sw); 01165 break; 01166 case 0x0800 : 01167 sw=4321; 01168 if(DEBUG) printf("shortS : %08x sw : %d\n",shortS,sw); 01169 break; 01170 default : 01171 sw = -1; 01172 if (DEBUG) printf (" Meme pas trouve 0008 (premier groupe); c est du RAW\n"); 01173 } 01174 } 01175 rewind(e->fp); // les info commencent au debut 01176 e->offsetCourant=0; 01177 return (sw); 01178 } 01179 01180 01181 // 01182 /* ================================================================== */ 01183 // 01184 01200 /* Pour rajouter une entree ici, 01201 01202 penser a modifier le fichier dicom.c 01203 penser a modifier la fonction idacr.h 01204 01205 pour maintenir la coherence. 01206 */ 01207 01208 char ** 01209 IdDcmInquireImageInfoFromFile(char *filename) { 01210 01211 ID_DCM_HDR *e; 01212 char **imageInfo; 01213 01214 e = IdDcmGetHeader(filename); 01215 01216 if (!e) { 01217 printf("fichier %s : gros problème :\n", filename); 01218 IdErrno = IDERR_NON_ACR_FILE; 01219 return (0); 01220 } 01221 imageInfo = _IdDcmInquireImageInfoXXX(e, NULL); 01222 01223 // LIBERER LE HEADER 01224 01225 return (imageInfo); 01226 } 01227 01228 01229 // 01230 /* ================================================================== */ 01231 // 01232 01248 /* Pour rajouter une entree ici, 01249 01250 penser a modifier le fichier dicom.c 01251 penser a modifier la fonction idacr.h 01252 01253 pour maintenir la coherence. 01254 */ 01255 01256 char ** 01257 IdDcmInquireImageInfoFromDcmHdr(ID_DCM_HDR *e) 01258 { 01259 char **imageInfo; 01260 01261 if (!e) { 01262 printf("ID_DCM_HDR pas alloue\n"); 01263 IdErrno = IDERR_NON_ACR_FILE; 01264 return (0); 01265 } 01266 01267 imageInfo = _IdDcmInquireImageInfoXXX(e, NULL); 01268 01269 return (imageInfo); 01270 } 01271 01272 /* ----------------------------------------------------------------------- */ 01273 01274 char ** 01275 _IdDcmInquireImageInfoXXX(ID_DCM_HDR *e, char **imageInfo) 01276 { 01277 01278 int boolTrouveQqChose=0,trouv,k; 01279 01280 DICOM_INFO *t; 01281 t = _ID_dicom_info; 01282 01283 if (!imageInfo) 01284 imageInfo = 01285 (char **) calloc (1, _ID_Number_of_Items + 1); 01286 01287 for(k=0;k<_ID_Number_of_Items;k++) { 01288 trouv=_IdDcmLireEtStockerElement(e, imageInfo,t[k].dicom_group, t[k].dicom_elem, 01289 t[k].dicom_info_libelle, t[k].dicom_info_ind); 01290 if(trouv) boolTrouveQqChose=1; 01291 } 01292 01293 if(boolTrouveQqChose) 01294 return (imageInfo); 01295 else 01296 return(0); 01297 } 01298 01299 /* ----------------------------------------------------------------------- 01300 * ID_DCM_HDR *e : doit avoir ete cree dans l'appelant 01301 * char **TableauImageInfo : doit avoir ete alloue dans l'appelant; 01302 * ses elements sont alloues dans la fonction 01303 * int numGroupe : gr et el du Tag DICOM 01304 * int numElem 01305 * char *nomElem : libelle imprime si element pas trouve 01306 * int position : indice dans TableauImageInfo 01307 -----------------------------------------------------------------------*/ 01308 static int 01309 _IdDcmLireEtStockerElement(ID_DCM_HDR *e, char **TableauImageInfo, int numGroupe, 01310 int numElem, char *nomElem, int position) { 01311 int z; 01312 char *chaine; 01313 01314 /* 01315 * Lecture Element 01316 */ 01317 //if (!( chaine = _IdDcmReadElement(numGroupe, numElem, e) )) { 01318 if (!( chaine = _IdDcmReadElementNoSQ(numGroupe, numElem, e) )) { 01319 01320 if (DEBUG) 01321 printf 01322 ("%d : _IdDcmLireEtStockerElement : " 01323 "%s (%04x,%04x) pas trouve \n", 01324 position, nomElem, numGroupe, numElem); 01325 01326 return (0); 01327 } else { 01328 if (DEBUG) 01329 printf 01330 ("%d : _IdDcmLireEtStockerElement : " 01331 "%s (%04x,%04x) \t[%s] \n", 01332 position, nomElem, numGroupe, numElem,chaine); 01333 01334 z = strlen(chaine); 01335 while (chaine[z] == ' ') { 01336 chaine[z] = 0; 01337 z--; 01338 } 01339 01340 TableauImageInfo[position] = 01341 (char *) malloc(1 + strlen(chaine)); 01342 strcpy(TableauImageInfo[position], chaine); 01343 if (DEBUG) 01344 printf 01345 ("%d : %s (_IdDcmLireEtStockerElement : " 01346 "%04x,%04x)\t[%s]\n", 01347 position, nomElem, numGroupe, numElem, 01348 chaine); 01349 01350 return (1); 01351 } 01352 } 01353 01354 // Converts an integer represented with num_byte bytes within the 01355 // buffer buff to a string. 01356 // Refer to comp.lang.faq FAQ, question 12.21 : How can I tell how much 01357 // destination buffer space I'll need for an arbitrary sprintf call? How can 01358 // I avoid overflowing the destination buffer with sprintf? 01359 01360 static char * var_itoa(void * buff, int num_byte) 01361 { 01362 char * retbuf; 01363 01364 // We double the recommended value since we also have to deal 01365 // with long integers. Pfff... 01366 #define CHAR_BIT 8 01367 retbuf = malloc(2 * ( (sizeof(int) * CHAR_BIT + 2) / 3 + 1 + 1)); 01368 switch (num_byte) { 01369 case 2: 01370 sprintf(retbuf, "%d", *((int*)buff)); 01371 break; 01372 case 4: 01373 sprintf(retbuf, "%dl", *((int*)buff)); 01374 break; 01375 default: 01376 sprintf(retbuf, "var_itoa?????"); 01377 } 01378 return retbuf; 01379 } 01380 01381 01382 /* ======================================================================= 01383 int _IdStrGetDicomTag(char * label, int *gr, int * num, char *vr) 01384 01385 recherche le Dicom tag d'un libelle donne 01386 par inspection du Dictionnaire DICOM 01387 (retourne 0 si pas trouve) 01388 ======================================================================= */ 01389 01390 01391 01392 static int _IdStrGetDcmTag (char* libelle, unsigned long *gr, unsigned long *num, char **vr) { 01393 01394 DICOM_ELEMENTS *t; 01395 int i; 01396 01397 t=_ID_dicom_elements; 01398 01399 for (i=0; t[i].dicom_group != 0xffff; i++) { 01400 if( strcmp(t[i].dicom_libelle, libelle) ==0 ) 01401 01402 { 01403 *gr= t[i].dicom_group; 01404 *num=t[i].dicom_elem; 01405 *vr =t[i].dicom_type; 01406 return(1); 01407 } 01408 } 01409 return(0); 01410 01411 } 01412 01413 01431 char * 01432 _IdDcmReadElementFromLabel(char *libelle, ID_DCM_HDR *e, char * vr, void *buff) { 01433 01434 int i; 01435 unsigned long gr; 01436 unsigned long num; 01437 char * caster; 01438 01439 i = _IdStrGetDcmTag (libelle, &gr, &num, &vr); 01440 01441 if (i == 0) { 01442 if (DEBUG) printf("champ [%s] pas trouve\n",libelle); 01443 caster = malloc(4); 01444 sprintf(caster, "???"); 01445 return (caster); 01446 //return (NULL); 01447 } 01448 buff = _IdDcmReadElement(gr, num, e); 01449 if (buff == 0) { 01450 caster = malloc(4); 01451 sprintf(caster, "???"); 01452 return (caster); 01453 } 01454 if ( (strcmp(vr,"UL") != 0) 01455 && (strcmp(vr,"US") != 0) 01456 && (strcmp(vr,"SL") != 0) 01457 && (strcmp(vr,"SS") != 0) 01458 && (gr != 0x0028 || 01459 ( num != 0x0005 && num != 0x0200) ) ) { 01460 // les champs de vr RET sont des caract 01461 // sauf (28,5) et (28,200) Pixel Location 01462 return((void *) strdup(buff)); 01463 } 01464 if ( (strcmp(vr, "US") == 0) 01465 || (strcmp(vr, "SS") == 0) 01466 || (gr == 0x0028 && 01467 (num == 0x0005 || num == 0x0200) ) ) { // les champs de vr RET sont des caract 01468 // sauf (28,5) et (28,200) Pixel Location 01469 // Buff should contain an int16 01470 caster = var_itoa(buff, 2); 01471 return(caster); 01472 } 01473 if ( (strcmp(vr,"UL") == 0) 01474 || (strcmp(vr,"SL") == 0) ) { 01475 // Buff should contain a uint32_t 01476 caster = var_itoa(buff, 2); 01477 return(caster); 01478 } 01479 if (DEBUG) printf("impossible de passer ici, mais le compilo rale\n"); 01480 return (NULL); 01481 01482 } 01483 01484 01485 // 01486 /* ============================================================================= */ 01487 // 01488 01489 01490 01491 /* ----------------------------------------------------------------------- */ 01492 static void 01493 _IdImprimerElement(char **TableauImageInfo, int numGroupe, 01494 int numElem, char *nomElem, int position) 01495 { 01496 if (!TableauImageInfo[position]) 01497 printf("%d : %s \t(%04x,%04x) pas trouve \n", position, 01498 nomElem, numGroupe, numElem); 01499 else 01500 printf("%d : %s \t(%04x,%04x)\t[%s]\n", position, 01501 nomElem, numGroupe, numElem, 01502 TableauImageInfo[position]); 01503 } 01504 01505 /* ----------------------------------------------------------------------- */ 01506 01521 int 01522 IdDcmPrintImageInfo(char **TableauImageInfo) { 01523 01524 int k; 01525 DICOM_INFO *t; 01526 t = _ID_dicom_info; 01527 01528 if (!TableauImageInfo) return(0); 01529 01530 for(k=0;k<_ID_Number_of_Items;k++) { 01531 _IdImprimerElement(TableauImageInfo, t[k].dicom_group, 01532 t[k].dicom_elem, 01533 t[k].dicom_info_libelle, 01534 t[k].dicom_info_ind); 01535 } 01536 return (1); 01537 } 01538 01539 01540 01541 /* ----------------------------------------------------------------------- */ 01542 static char * _cleanString(char *v) { 01543 01544 char *d; 01545 int i, l; 01546 l = strlen(v); 01547 for ( i=0,d=v; 01548 i<l ; 01549 i++,d++) 01550 { 01551 if (!isprint(*d)) 01552 *d = '.'; 01553 } 01554 01555 return v; 01556 } 01557 /* ----------------------------------------------------------------------- */ 01558 01559 01560 void IdDcmAffDcmHdr(ID_DCM_HDR *e, int npriv, int noffset) { 01561 01562 01563 DICOM_ELEMENTS *t = NULL; 01564 PLIST pl; 01565 PLIST_ELEMENT plelem; 01566 _ID_DCM_ELEM *ple; 01567 01568 pl=e->plist; 01569 plelem = IdLstFirst(pl); 01570 01571 while (plelem) { 01572 01573 ple= IdLstPtrObj(plelem); // le _ID_DCM_ELEM pointé par le PLIST_ELEMENT 01574 01575 if (ple->Num==0) { 01576 if(!npriv) printf("\n"); 01577 } else { 01578 for (t=_ID_dicom_elements; t->dicom_group!=0xffff; t++) { 01579 if( (t->dicom_group==ple->Gr) && (t->dicom_elem==ple->Num) ) break; 01580 } 01581 } 01582 if(!(ple->Gr%2) || !npriv) { 01583 01584 if (noffset) 01585 printf(" gr %04x num %04x long %d", 01586 ple->Gr, ple->Num, ple->LgrLueElem); 01587 else 01588 printf(" gr %04x num %04x long %d _offset %d x(%x) o(%o12)", 01589 ple->Gr, ple->Num, ple->LgrLueElem, ple->Offset,ple->Offset,ple->Offset ); 01590 } 01591 01592 if (ple->Num!=0) { 01593 01594 if(ple->VR == NULL) { 01595 if(!(ple->Gr%2) || !npriv) printf("\t%s\t%s\t\t", 01596 t->dicom_type, t->dicom_libelle); 01597 } else { 01598 if(!(ple->Gr%2) || !npriv) printf("\t%s\t%s\t\t", 01599 ple->VR, t->dicom_libelle); 01600 } 01601 01602 if ( (ple->Gr==0x0002) && (ple->Num==0x0010) ) { 01603 char * s = _IdStrShowTransfertSyntax(ple->valeurElem); 01604 printf(" : [%s] ",s); 01605 } 01606 } 01607 01608 if (ple->Num==0) { 01609 if(!(ple->Gr%2) || !npriv){ 01610 printf(" lgr du grp = %d\n -------\n", 01611 str2num(ple->valeurElem,int) ); 01612 } 01613 } else { 01614 switch (ple->LgrElem) { 01615 01616 case 2: // LGR = 2 01617 01618 if ( (strcmp(t->dicom_type, "US") == 0) 01619 || (strcmp(t->dicom_type, "SS") == 0) 01620 || (t->dicom_group == 0x0028 01621 && 01622 ( t->dicom_elem == 0x0005 01623 || t->dicom_elem == 0x0200) ) ) { 01624 01625 if(!(ple->Gr%2) || !npriv) { 01626 printf("\t \t \t %d \tx(%04x)\n", 01627 str2num(ple->valeurElem,unsigned short int), 01628 str2num(ple->valeurElem,unsigned short int) ); 01629 } 01630 } else { 01631 01632 if(!(ple->Gr%2) || !npriv){ 01633 printf("\t[%s] \t %d \tx(%04x)\n", 01634 _cleanString(ple->valeurElem), 01635 str2num(ple->valeurElem,unsigned short int), 01636 str2num(ple->valeurElem,unsigned short int)); 01637 } 01638 } 01639 break; 01640 01641 case 4 : // LGR = 4 01642 01643 if ( (strcmp(t->dicom_type,"UL") == 0) 01644 || (strcmp(t->dicom_type,"SL") == 0) ) { 01645 if(!(ple->Gr%2) || !npriv) { 01646 printf("\t \t \t %d \tx(%08x)\n", 01647 str2num(ple->valeurElem,int), 01648 str2num(ple->valeurElem,int)); 01649 } 01650 } else { 01651 if (strcmp(t->dicom_type,"FL") == 0) { 01652 if(!(ple->Gr%2) || !npriv) { 01653 printf("\t \t \t %f\t\n", 01654 str2num(ple->valeurElem,float)); 01655 } 01656 } else { 01657 if(!(ple->Gr%2) || !npriv) { 01658 printf(" \t[%s]\n",_cleanString(ple->valeurElem)); 01659 } 01660 } 01661 } 01662 break; 01663 01664 01665 case 8 : // lgr = 8 (double) 01666 01667 if (strcmp(t->dicom_type,"FD") == 0) { 01668 if(!(ple->Gr%2) || !npriv) { 01669 printf("\t \t \t %g \t\n", 01670 str2num(ple->valeurElem,double)); 01671 } 01672 } else { 01673 if(!(ple->Gr%2) || !npriv) { 01674 printf("\t[%s]\n",_cleanString(ple->valeurElem)); 01675 } 01676 } 01677 break; 01678 01679 01680 default : // AUTRES LGR 01681 01682 if (ple->LgrElem > 5000) { 01683 if(!(ple->Gr%2) || !npriv) 01684 printf(" --> Too Long (%08x). Not Printed...\n",ple->LgrElem); 01685 } else { 01686 if(!(ple->Gr%2) || !npriv) 01687 printf(" \t[%s]\n",_cleanString(ple->valeurElem)); 01688 } 01689 01690 } 01691 } 01692 plelem = IdLstNext(plelem); 01693 } 01694 } 01695 01696 // ----------------------------------------------------------------------------------------------- 01697 01708 ID_DCM_HDR * IdDcmIsDcmReadable(char * filename) { 01709 01710 // on suppose que la creation du DcmHeader est suffisante 01711 // pour que le fichier soit DcmReadble 01712 // (abusif, car un DICOMDIR permet de creer un DcmHeader 01713 // et n'est pas DcmReadable -pas de Pixels -...) 01714 01715 ID_DCM_HDR * a =IdDcmGetHeader(filename); 01716 return a; 01717 } 01718 01719 01720 // ---------------------------------------------------------------------------------------------- 01721 01722 01733 int IdDcmIsJpegLossless (ID_DCM_HDR * e) { 01734 char * Derivation_Description; 01735 char * Transfert_Syntax_UID; 01736 char * valeur = "Compress BN JPEG Lossless"; 01737 01738 if (!e) 01739 return (0); 01740 01741 Transfert_Syntax_UID = _IdDcmReadElement(0x0002, 0x0010, e); 01742 if (Transfert_Syntax_UID != NULL) { 01743 if ( (memcmp(Transfert_Syntax_UID + strlen(Transfert_Syntax_UID)-2, "70", 2) == 0) 01744 || 01745 (memcmp(Transfert_Syntax_UID + strlen(Transfert_Syntax_UID)-2, "55", 2) == 0) ) { 01746 return (1); 01747 } else { 01748 Derivation_Description = _IdDcmReadElement(0x0008, 0x2111, e); 01749 if (Derivation_Description != NULL) { 01750 if (memcmp (Derivation_Description, valeur, strlen(valeur)) == 0) 01751 return (1); 01752 } 01753 } 01754 } 01755 return (0); 01756 } 01757 01758 01759 // ---------------------------------------------------------------------------------------------- 01760 01761 01773 int IdDcmIsUncompressed (ID_DCM_HDR * e) { 01774 char * Transfert_Syntax_UID; 01775 int l; 01776 01777 if (!e) // never allocated 01778 return (0); 01779 01780 if (!e->__TrueDicom) // old ACR-NEMA 01781 return (1); 01782 01783 // IsImplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2 01784 // IsExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1 01785 // IsDeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 01786 // IsExplicitVRBigEndianTransferSyntax 1.2.840.10008.1.2.2 01787 01788 Transfert_Syntax_UID = _IdDcmReadElement(0x0002, 0x0010, e); 01789 01790 if (Transfert_Syntax_UID != NULL) { 01791 l = strlen(Transfert_Syntax_UID); 01792 if ( (memcmp(Transfert_Syntax_UID,"1.2.840.10008.1.2", l) == 0) 01793 || 01794 (memcmp(Transfert_Syntax_UID,"1.2.840.10008.1.2.1", l) == 0) 01795 || 01796 (memcmp(Transfert_Syntax_UID,"1.2.840.10008.1.2.1.99", l) == 0) 01797 || 01798 (memcmp(Transfert_Syntax_UID,"1.2.840.10008.1.2.2", l) == 0) 01799 01800 ) 01801 return (1); // uncompressed 01802 else 01803 return (0); // others 01804 } else { 01805 return (1); // No Transfer Syntax found. Hope it's uncompressed 01806 } 01807 }

Generated on Wed Oct 19 09:28:33 2005 for SIMRI3D by doxygen 1.3.7