4 #include <iddcm-restricted.h>
13 #include <winsock.h> // Pour ntohs - BigEndianeries -
15 #include <netinet/in.h> // Pour ntohs - BigEndianeries -
18 #define LGR_ENTETE_A_LIRE 256 // on ne lit plus que le debut
22 static char * var_itoa(void * , int );
24 static guint32 _IdDcmRecupLgr(ID_DCM_HDR *, int, int*, int *);
25 static int _IdDcmCheckSwap(ID_DCM_HDR *);
26 static int _IdDcmLireEtStockerElement(ID_DCM_HDR *, char **, int,
28 static char ** _IdDcmInquireImageInfoXXX (ID_DCM_HDR *, char **);
30 static void _setAcrLibido(ID_DCM_HDR *);
32 // -----------------------------------------------------------------
36 * \brief Alloue un ID_DCM_HDR
37 * @return Pointeur sur structure Allouée, NULL si échec
40 ID_DCM_HDR * IdDcmHdrAlloc () {
41 ID_DCM_HDR *e = (ID_DCM_HDR *) g_malloc0 (sizeof(ID_DCM_HDR));
44 e->deb = (char *) g_malloc(LGR_ENTETE_A_LIRE);
47 printf("Echec alloc ID_DCM_HDR\n");
50 e->plist = IdLstAlloc();
55 printf("Echec alloc ID_DCM_HDR->deb\n");
56 return (ID_DCM_HDR *)NULL;
61 // ------------------------------------------------------------------
64 * \brief Libere un ID_DCM_HDR
65 * @param e pointeur sur le ID_DCM_HDR a liberer.
69 void IdDcmHdrFree (ID_DCM_HDR * e) {
72 if (e->deb) g_free(e->deb);
73 if (e->deb) g_free(e->plist); // LIBERER LES ELEMENTS DE LA LISTE AVANT
78 /* =======================================================================
80 * remet les octets dans un ordre compatible avec celui du processeur
81 * ======================================================================= */
83 short int _IdDcmSWAP_SHORT(short int a,int sw) {
84 if ( (sw==4321) || (sw==2143) )
85 a =(((a<<8) & 0x0ff00) | ((a>>8)&0x00ff));
89 /* =======================================================================
91 * remet les octets dans un ordre compatible avec celui du processeur
92 * ======================================================================= */
94 guint32 _IdDcmSWAP_LONG(guint32 a, int sw) {
95 /* ATTENTION: il pourrait y avoir un pb pour les entiers negatifs ...
100 a=( ((a<<24) & 0xff000000) | ((a<<8) & 0x00ff0000) |
101 ((a>>8) & 0x0000ff00) | ((a>>24) & 0x000000ff) );
105 a=( ((a<<16) & 0xffff0000) | ((a>>16) & 0x0000ffff) );
109 a=( ((a<<8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) );
112 printf("\n\n\n *******\n erreur code swap ?!?\n\n\n");
118 // -----------------------------------------------------------------------------------
121 * \brief renvoie un pointeur sur le ID_DCM_HDR correspondant au fichier
122 * @param filename Nom du fichier ACR / LibIDO / DICOM
123 * @return le ID_DCM_HDR
126 ID_DCM_HDR * IdDcmGetHeader(char *filename) {
133 printf("echec alloc HDR \n");
137 if((e->fp=fopen(filename,ID_RFILE_BIN))==0) { // OK
139 printf ("echec ouverture %s\n",filename);
143 e->filename = strdup(filename);
145 fseek(e->fp, 0L, SEEK_END);
147 * obtains the current value of the file-position
148 * indicator for the stream pointed to by stream
150 e->taille_fich = ftell(e->fp);
152 if(DEBUG) printf("IdDcmGetHeader : lgr fich %f\n",(float)e->taille_fich); // FORMAT IMPRESSION long int ???
156 e->sw= _IdDcmCheckSwap(e);
157 e->__NumeroGroupePrecedent = 0; // Pour etre sur que le premier sera + grand
158 e->grPixelTrouve = 0;
159 e->PixelsTrouves = 0;
162 while ( (ple=_IdDcmReadNextElement(e,e->sw)) ) {
163 IdLstAddLast(e->plist, ple);
166 // Positionnement ACR_LIBIDO
174 static void _setAcrLibido(ID_DCM_HDR *e) {
177 PLIST_ELEMENT plelem;
180 // Positionnement ACR_LIBIDO
181 if(DEBUG) printf("Entree ds _setAcrLibido\n");
184 if ( e->__TrueDicom == 0) {
185 // Recognition Code --> n'existe plus en DICOM V3 ...
188 plelem = IdLstFirst(pl);
190 ple= IdLstPtrObj(plelem);
191 if(DEBUG) printf("gr %04x Num %04x\n", ple->Gr, ple->Num);
192 if(ple->Gr > 0x0008) break; // On a depasse
193 if(ple->Gr == 0x0008) {
194 if(ple->Num > 0x0010) break; // On a depasse
195 if(ple->Num == 0x0010) {
196 if ( (memcmp(ple->valeurElem,"ACRNEMA_LIBIDO",14)==0)
198 || (memcmp(ple->valeurElem,"CANRME_AILIBOD",14)==0)) {
199 // en cas d'objet ACRLibido fait sr 1 autre machine)
203 } // fin if ple->Num==0x0010
204 } // fin ple->Gr==0x0008
205 plelem = IdLstNext(plelem);
207 } // fin if TrueDicom
209 if(DEBUG) printf("ACR_LIBIDO = %d\n", e->ACR_LIBIDO);
212 /* =======================================================================
215 * ACR-NEMA : On a toujours
216 * GroupNumber (2 Octets)
217 * ElementNumber (2 Octets)
218 * ElementSize (4 Octets)
221 * DICOM : On peut avoir (implicit Value Representation)
222 * GroupNumber (2 Octets)
223 * ElementNumber (2 Octets)
224 * ElementSize (4 Octets)
226 * On peut avoir (explicit Value Representation)
227 * GroupNumber (2 Octets)
228 * ElementNumber (2 Octets)
229 * ValueRepresentation (2 Octets)
230 * ElementSize (2 Octets)
232 * ATTENTION : dans le cas ou ValueRepresentation = OB, OW, SQ, UN
233 * GroupNumber (2 Octets)
234 * ElementNumber (2 Octets)
235 * ValueRepresentation (2 Octets)
236 * zone reservee (2 Octets)
237 * ElementSize (4 Octets)
240 * ======================================================================= */
243 * \brief recupere la longueur d'un champ DICOM.
244 * (le fichier doit deja avoir ete ouvert,
245 * _IdAcrCheckSwap(ID_DCM_HDR *e) avoir ete appele)
246 * et la partie 'group' ainsi que la partie 'elem'
247 * de l'acr_element doivent avoir ete lues.
248 * @param sw code swap
249 * @param skippedLength pointeur sur nombre d'octets que l'on a saute qd la lecture est finie
250 * @param longueurLue pointeur sur longueur (en nombre d'octets) effectivement lue
252 * @return longueur retenue pour le champ
255 static guint32 _IdDcmRecupLgr(ID_DCM_HDR *e, int sw, int *skippedLength, int *longueurLue) {
257 unsigned short int l_gr_2;
266 int nbCode=26; // nombre d'elements dans la table de type DICOM_VR definie dans dicom.c
268 /* ================ */
270 // ID_DCM_HDR *e sert uniquement de passe-plat pour __ExplicitVR
273 if (e->__ExplicitVR == 1) {
274 lgrLue=fread (&VR, (size_t)2,(size_t)1, e->fp);
278 // Ce n'est pas parce qu'on a trouve UL la premiere fois qu'on respecte
279 // Explicit VR tout le temps
282 for(i=0,trouve=0;i<nbCode;i++) {
283 if(memcmp(_ID_dicom_vr[i].dicom_VR,VR,(size_t)2)==0) {
284 (e->pleCourant)->VR=_ID_dicom_vr[i].dicom_VR;
292 // On est mal : implicit VR repere
293 // mais ce n'est pas un code connu ...
294 // On reconstitue la longueur
296 if(DEBUG) printf("IdDcmRecupLgr : Explicit VR, mais pas trouve de code connu\n");
297 memcpy(&l_gr, VR,(size_t)2);
299 lgrLue=fread ( ((char*)&l_gr)+2, (size_t)2, (size_t)1, e->fp);
301 if(sw) l_gr = _IdDcmSWAP_LONG(((guint32)l_gr),sw);
303 if(DEBUG) printf("IdDcmRecupLgr : lgr deduite : %08x , %d\n",l_gr,l_gr);
306 if ( (int)l_gr == -1) {
310 if (DEBUG) printf(" 1 : lgr %08x (%d )skippedLength %d\n",l_gr,l_gr, *skippedLength);
314 // On repart dans la sequence 'sensee'
316 if(DEBUG) printf("VR : [%01x , %01x] (%c%c) en position %d du tableau\n", VR[0],VR[1],VR[0],VR[1],i);
317 //printf(" %d , %s\n", i,_ID_dicom_vr[i].dicom_VR);
320 (!memcmp( VR,"OB",(size_t)2 )) ||
321 (!memcmp( VR,"OW",(size_t)2 )) ||
322 (!memcmp( VR,"SQ",(size_t)2 )) ||
323 (!memcmp( VR,"UN",(size_t)2 )) ) {
325 // les 2 octets suivants sont reserves
327 if(DEBUG) printf("IdDcmRecupLgr : les 2 octets suivants sont reserves\n");
329 fseek(e->fp, 2L,SEEK_CUR);
331 //on lit la lgr sur QUATRE octets
333 lgrLue=fread (&l_gr, (size_t)4,(size_t)1, e->fp);
335 if(sw) l_gr = _IdDcmSWAP_LONG(((guint32)l_gr),sw);
339 //on lit la lgr sur DEUX octets
341 lgrLue=fread (&l_gr_2, (size_t)2,(size_t)1, e->fp);
343 if(sw) l_gr_2 = _IdDcmSWAP_SHORT((unsigned short)l_gr_2,sw);
348 if ( l_gr_2 == 0xffff) {
355 } else { // Explicit VR = 0
357 //on lit la lgr sur QUATRE octets
359 lgrLue=fread (&l_gr, (size_t)4,(size_t)1, e->fp);
361 if(sw)l_gr=_IdDcmSWAP_LONG(((long)l_gr),sw);
367 // Traitement des curiosites sur la longueur
369 if ( (int)l_gr == 0xffffffff)
372 if(!memcmp( VR,"SQ",(size_t)2 )) { // ca annonce une SEQUENCE d'items ?!
373 l_gr=0; // on lira donc les items de la sequence
374 if (DEBUG) printf(" SQ trouve : lgr %d \n",l_gr);
377 if (DEBUG) printf(" 2 : lgr %08x (%d) skippedLength %d\n",l_gr,l_gr, *skippedLength);
381 /* =======================================================================
382 _IdDcmReadNextElement
384 lit l'acr_element courant
385 le fichier doit deja avoir ete ouvert,
387 ======================================================================= */
391 * \brief lit le dicom_element suivant.
392 * (le fichier doit deja avoir ete ouvert,
393 * _IdAcrCheckSwap(ID_DCM_HDR *e) avoir ete appele)
394 * @param e ID_DCM_HDR dans lequel effectuer la recherche.
395 * @param sw code swap.
396 * @return En cas de succes, 1
400 _ID_DCM_ELEM * _IdDcmReadNextElement(ID_DCM_HDR * e, int sw) {
409 _ID_DCM_ELEM *nouvDcmElem;
411 if (DEBUG) printf(" ===> entree ds _IdDcmReadNextElement\n");
413 if(e->offsetCourant == e->taille_fich) { // On a atteint la fin du fichier
414 if (DEBUG) printf(" On a atteint la fin du fichier\n");
418 posFich = ftell(e->fp);
419 printf("lgrFich %f positionDsFich %f offset courant %f\n",
420 (float)e->taille_fich,
422 (float)e->offsetCourant);
426 nouvDcmElem = (_ID_DCM_ELEM *)g_malloc(sizeof(_ID_DCM_ELEM));
428 printf("Echec alloc _ID_DCM_ELEM *nouvDcmElem\n");
432 e->pleCourant = nouvDcmElem;
434 // ------------------------- Lecture Num group : g
436 lgrLue=fread (&g, (size_t)2,(size_t)1, e->fp);
439 if (DEBUG) printf("_IdDcmReadNextElement : eof trouve\n");
443 if (DEBUG) printf(" IdDcmReadNextElement : echec lecture NumGr\n");
447 if (DEBUG) printf("_IdDcmReadNextElement : "
450 if (sw) g=_IdDcmSWAP_SHORT(((short)g),sw);
453 e->__NumeroGroupePrecedent =g;
455 // ------------------------- Lecture Num Elem : n
457 lgrLue=fread (&n, (size_t)2,(size_t)1, e->fp);
460 if (DEBUG) printf("_IdDcmReadNextElement : eof trouve\n");
464 if (DEBUG) printf(" IdDcmReadNextElement : echec lecture NumElem\n");
468 if (DEBUG) printf("_IdDcmReadNextElement : "
471 if(sw)n=_IdDcmSWAP_SHORT(((short)n),sw);
474 // ------------------------- Lecture longueur element : l
476 l = _IdDcmRecupLgr(e, sw, &skL, &nouvDcmElem->LgrLueElem);
478 if(g==0xfffe) l=0; // pour sauter les indicateurs de 'SQ'
480 nouvDcmElem->LgrElem=l;
482 if (DEBUG) if (n!=0) printf("_IdDcmReadNextElement : "
483 " gr %04x\tnum %04x\tlong %08x (%d)\n",
486 // ------------------------- Lecture Valeur element
488 nouvDcmElem->valeurElem = g_malloc(l+1);
489 if(nouvDcmElem->valeurElem) {
490 nouvDcmElem->valeurElem[l]= 0;
492 if (DEBUG) printf(" IdDcmReadNextElement : echec Alloc valeurElem lgr : %d\n",l);
496 // ------------------------ On n'amene pas en mémoire les Elem 'trop longs'
498 lgrLue=fread (nouvDcmElem->valeurElem, (size_t)l,(size_t)1, e->fp);
500 e->offsetCourant += 2 + 2 + skL; // gr + num + lgr
501 nouvDcmElem->Offset = e->offsetCourant;
502 e->offsetCourant += l; // debut elem suivant
505 // ------------------------- Doit-on le Swapper ?
508 if ((n==0) && sw) { // n=0 : lgr du groupe : guint32
509 *(guint32 *) nouvDcmElem->valeurElem =
510 _IdDcmSWAP_LONG ((*(guint32 *) nouvDcmElem->valeurElem),sw);
511 nouvDcmElem->Swap = 1;
514 if ( (g/2)*2-g==0) { /* on ne teste pas les groupes impairs */
516 if ((l==4)||(l==2)) { /*pour eviter de swapper les chaines
519 printf("Consultation Dictionary DICOM g %04x n %0xx l %d\n",
522 for (t=_ID_dicom_elements; t->dicom_group!=0xffff; t++) {
523 if( (t->dicom_group==g) && (t->dicom_elem==n) ) {
524 nouvDcmElem->VR= t->dicom_type;
528 if ( (strcmp(t->dicom_type,"UL") ==0)
529 || (strcmp(t->dicom_type,"US") ==0)
530 || (strcmp(t->dicom_type,"SL") ==0)
531 || (strcmp(t->dicom_type,"SS") ==0)
533 ( n == 0x0005 || n == 0x0200) ) ) { // seuls (28,5) de vr RET
534 // et (28,200) sont des entiers
535 // ... jusqu'a preuve du contraire
536 nouvDcmElem->Swap = 1;
539 *(guint32 *) nouvDcmElem->valeurElem=
540 _IdDcmSWAP_LONG ((*(guint32 *) nouvDcmElem->valeurElem),sw);
541 nouvDcmElem->valInt =
542 _IdDcmSWAP_LONG ((*(guint32 *) nouvDcmElem->valeurElem),sw);
545 *(unsigned short *) nouvDcmElem->valeurElem=
546 _IdDcmSWAP_SHORT ((*(unsigned short *)nouvDcmElem->valeurElem),sw);
547 nouvDcmElem->valShort =
548 _IdDcmSWAP_SHORT ((*(unsigned short *)nouvDcmElem->valeurElem),sw);
551 } /* fin if l==2 ==4 */
552 } /* fin if g pair */
557 // ------------------------- A-t-on trouve l'info donnant le 'num groupe' des Pixels ?
560 if (!e->grPixelTrouve) { // on n a pas encore trouve les pixels
562 if (n > 0x0200 || g == 0x7FE0 ) { // on a depasse (28,200)
564 e->numPixel = 0x0010;
565 e->grPixelTrouve = 1;
566 if (DEBUG) printf("------------------------grPixel %04x numPixel %04x\n",
567 e->grPixel,e->numPixel);
570 } else { // on est sur (28,200)
573 e->grPixelTrouve = 1;
575 *((char*)(&e->grPixel)+i) = *(nouvDcmElem->valeurElem+i);
578 if (DEBUG) printf("------------------------GrPixel %04x\n",
581 if (e->grPixel != 0x7FE0) // Vieux pb Philips
582 e->numPixel = 0x1010; // encore utile ??
584 e->numPixel = 0x0010;
585 if (DEBUG) printf("------------------------grPixel %04x numPixel %04x\n",
586 e->grPixel,e->numPixel);
590 } else { // on vient de trouver les pixels
591 if (g == e->grPixel) {
592 if (n == e->numPixel) {
593 e->PixelPosition = nouvDcmElem->Offset;
594 e->PixelsTrouves = 1;
595 if (DEBUG) printf(" \t===> Pixels Trouves\n");
601 //printf("nb Elem %d\n",e->nbElem);
606 /* =======================================================================
609 La seule maniere sure que l'on aie pour determiner
610 si on est en LITTLE_ENDIAN, BIG-ENDIAN,
611 BAD-LITTLE-ENDIAN, BAD-BIG-ENDIAN
612 est de trouver l'element qui donne la longueur d'un 'GROUP'
613 (on sait que la longueur de cet element vaut 0x00000004)
614 et de regarder comment cette longueur est codee en memoire
616 Le probleme vient de ce que parfois, il n'y en a pas ...
618 On fait alors le pari qu'on a a faire a du LITTLE_ENDIAN propre.
619 (Ce qui est la norme -pas respectee- depuis ACR-NEMA)
620 Si ce n'est pas le cas, on ne peut rien faire.
622 (il faudrait avoir des fonctions auxquelles
623 on passe le code Swap en parametre, pour faire des essais 'manuels')
625 ======================================================================= */
628 _IdDcmCheckSwap(ID_DCM_HDR * e) {
629 guint32 s, x=4; // x : pour ntohs
634 char deb[LGR_ENTETE_A_LIRE];
637 // On teste le processeur
639 if (x==ntohs(x)) { /* si le HostByteOrder est le meme que le NetworkByteOrder */
645 //printf("\t\t\t\te->net2host %d \n",e->net2host);
647 /* On commence par verifier si c'est du DICOM 'actuel' */
650 lgrLue = fread(deb,1,LGR_ENTETE_A_LIRE,e->fp);
653 if(memcmp(entCur, "DICM", (size_t)4) == 0) {
655 if (DEBUG) printf ("_IdDcmCheckSwap : C est du DICOM actuel \n");
658 if (DEBUG) printf ("_IdDcmCheckSwap : Ce n'est PAS du DICOM actuel\n");
662 entCur = deb+136; /* on saute le File Preamble (souvent a ZERO) : 128 Octets */
663 /* le DICM, et le 0002, 0000 */
664 if(memcmp(entCur, "UL", (size_t)2) == 0) {
665 /* les 2 premiers octets de la lgr peuvent valoir UL --> Explicit VR */
667 if (DEBUG) printf ("_IdDcmCheckSwap : Explicit VR\n");
670 if (DEBUG) printf ("_IdDcmCheckSwap : PAS Explicit VR\n");
673 if (e->net2host == 0) { /* si le HostByteOrder est different du NetworkByteOrder */
674 sw = 0; /* on est sur PC ou DEC --> LITTLE-ENDIAN -> Rien a faire */
675 if (DEBUG) printf("HostByteOrder = NetworkByteOrder\n");
677 } else { /* on est sur une Sun ou une SGI */
679 if (DEBUG) printf("HostByteOrder != NetworkByteOrder\n");
683 fseek (e->fp, 132L, SEEK_SET); //On se positionne sur le debut des info
684 e->offsetCourant=132;
687 } /* fin TrueDicom */
689 /* ----- SINON ----- */
691 /* Si c'est de l'ACR 'propre', la lgr du premier element du groupe est FORCEMENT 4 */
694 s=str2num(entCur,int);
698 sw=3412; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
701 sw=4321; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
704 sw=2143; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
707 sw=0; if(DEBUG) printf("s : %08x sw : %d\n",s,sw);
711 if (DEBUG) printf (" Pas trouve l info de Swap; On va parier\n");
714 /* Si c'est de l'ACR 'pas propre', il manque la lgr du groupe */
717 /* On n'a pas trouve l'info de swap 28/11/2000 JPR */
718 /* Si c'est du VRAI ACR NEMA si on est sur une DEC ou un PC swap=0, SUN ou SGI SWAP=4321 */
719 /* si c'est du RAW, ca degagera + tard */
721 if (DEBUG) printf("On force la chance \n");
723 if (x!=ntohs(x)) /* si le HostByteOrder est different du NetworkByteOrder */
724 sw = 0; /* on est sur PC ou DEC --> LITTLE-ENDIAN -> Rien a faire */
726 sw = 4321; /* on est sur Sun ou SGI */
729 rewind(e->fp); // les info commencent au debut
736 /* ================================================================== */
741 * \brief renvoie dans un tableau de chaines de caracteres
742 la description des info pertinentes d'une image ACR /DCM
743 (la soixantaine de champs utiles)
744 a partir du nom du fichier
746 * @param filename Nom du fichier.
750 * Pour avoir la liste a jour des elements renvoyes dans ce tableau,
751 * Consulter src/idacr.h et src/dicom.c
754 /* Pour rajouter une entree ici,
756 penser a modifier le fichier dicom.c
757 penser a modifier la fonction idacr.h
759 pour maintenir la coherence.
763 IdDcmInquireImageInfoFromFile(char *filename) {
768 e = IdDcmGetHeader(filename);
771 printf("fichier %s : gros problème :\n", filename);
772 IdErrno = IDERR_NON_ACR_FILE;
776 imageInfo = _IdDcmInquireImageInfoXXX(e, NULL);
785 /* ================================================================== */
790 * \brief renvoie dans un tableau de chaines de caracteres
791 * la description des info pertinentes d'une image ACR /DCM
792 * a partir d'un ID_DCM_HDR deja fabrique
794 * @param e ID_DCM_HDR de l'image
797 * Pour avoir la liste a jour des elements renvoyes dans ce tableau,
798 * Consulter src/idacr.h et src/dicom.c
803 /* Pour rajouter une entree ici,
805 penser a modifier le fichier dicom.c
806 penser a modifier la fonction idacr.h
808 pour maintenir la coherence.
812 IdDcmInquireImageInfoFromDcmHdr(ID_DCM_HDR *e)
817 printf("ID_DCM_HDR pas alloue\n");
818 IdErrno = IDERR_NON_ACR_FILE;
822 imageInfo = _IdDcmInquireImageInfoXXX(e, NULL);
827 /* ----------------------------------------------------------------------- */
830 _IdDcmInquireImageInfoXXX(ID_DCM_HDR *e, char **imageInfo)
833 int boolTrouveQqChose=0,trouv,k;
840 (char **) g_malloc0((_ID_Number_of_Items + 1) *
843 for(k=0;k<_ID_Number_of_Items;k++) {
844 trouv=_IdDcmLireEtStockerElement(e, imageInfo,t[k].dicom_group, t[k].dicom_elem,
845 t[k].dicom_info_libelle, t[k].dicom_info_ind);
846 if(trouv) boolTrouveQqChose=1;
849 if(boolTrouveQqChose)
855 /* -----------------------------------------------------------------------
856 * ID_DCM_HDR *e : doit avoir ete cree dans l'appelant
857 * char **TableauImageInfo : doit avoir ete alloue dans l'appelant;
858 * ses elements sont alloues dans la fonction
859 * int numGroupe : gr et el du Tag DICOM
861 * char *nomElem : libelle imprime si element pas trouve
862 * int position : indice dans TableauImageInfo
863 -----------------------------------------------------------------------*/
865 _IdDcmLireEtStockerElement(ID_DCM_HDR *e, char **TableauImageInfo, int numGroupe,
866 int numElem, char *nomElem, int position) {
873 //if (!( chaine = _IdDcmReadElement(numGroupe, numElem, e) )) {
874 if (!( chaine = _IdDcmReadElementNoSQ(numGroupe, numElem, e) )) {
878 ("%d : _IdDcmLireEtStockerElement : "
879 "%s (%04x,%04x) pas trouve \n",
880 position, nomElem, numGroupe, numElem);
886 ("%d : _IdDcmLireEtStockerElement : "
887 "%s (%04x,%04x) \t[%s] \n",
888 position, nomElem, numGroupe, numElem,chaine);
891 while (chaine[z] == ' ') {
896 TableauImageInfo[position] =
897 (char *) g_malloc(1 + strlen(chaine));
898 strcpy(TableauImageInfo[position], chaine);
901 ("%d : %s (_IdDcmLireEtStockerElement : "
902 "%04x,%04x)\t[%s]\n",
903 position, nomElem, numGroupe, numElem,
910 // Converts an integer represented with num_byte bytes within the
911 // buffer buff to a string.
912 // Refer to comp.lang.faq FAQ, question 12.21 : How can I tell how much
913 // destination buffer space I'll need for an arbitrary sprintf call? How can
914 // I avoid overflowing the destination buffer with sprintf?
916 static char * var_itoa(void * buff, int num_byte)
920 // We double the recommended value since we also have to deal
921 // with long integers. Pfff...
922 retbuf = g_malloc(2 * ( (sizeof(int) * CHAR_BIT + 2) / 3 + 1 + 1));
925 sprintf(retbuf, "%d", *((int*)buff));
928 sprintf(retbuf, "%dl", *((int*)buff));
931 sprintf(retbuf, "var_itoa?????");
937 /* =======================================================================
938 int _IdStrGetDicomTag(char * label, int *gr, int * num, char *vr)
940 recherche le Dicom tag d'un libelle donne
941 par inspection du Dictionnaire DICOM
942 (retourne 0 si pas trouve)
943 ======================================================================= */
947 static int _IdStrGetDcmTag (char* libelle, unsigned long *gr, unsigned long *num, char **vr) {
952 t=_ID_dicom_elements;
954 for (i=0; t[i].dicom_group != 0xffff; i++) {
955 if( strcmp(t[i].dicom_libelle, libelle) ==0 )
958 *gr= t[i].dicom_group;
959 *num=t[i].dicom_elem;
960 *vr =t[i].dicom_type;
971 * \brief Tente de lire un dicom_element a partir de son libelle. Le
972 * resultat est range dans buff.
973 * @param libelle Libelle de l'acr_element a lire. Il s'agit du dernier
974 * champ de la variable globale _ID_dicom_elements, tel que
975 * "Group Length", "Priority" ou encore "AE Title".
976 * @param e ID_DCM_HDR dans lequel effectuer la recherche.
977 * @param vr DICOM_VR (cf la variable globale _ID_dicom_vr) retourne',
978 * pour permettre a l'appelant d'interpreter le contenu de buff.
979 * @param buff Ou placer l'acr_element en cas de succes. Si NULL,
980 * l'allocation est faite localement.
981 * @return En cas de succes, le contenu de l'acr_element lu. Null
987 _IdDcmReadElementFromLabel(char *libelle, ID_DCM_HDR *e, char * vr, void *buff) {
994 i = _IdStrGetDcmTag (libelle, &gr, &num, &vr);
997 if (DEBUG) printf("champ [%s] pas trouve\n",libelle);
998 caster = g_malloc(4);
999 sprintf(caster, "???");
1003 buff = _IdDcmReadElement(gr, num, e);
1005 caster = g_malloc(4);
1006 sprintf(caster, "???");
1009 if ( (strcmp(vr,"UL") != 0)
1010 && (strcmp(vr,"US") != 0)
1011 && (strcmp(vr,"SL") != 0)
1012 && (strcmp(vr,"SS") != 0)
1014 ( num != 0x0005 && num != 0x0200) ) ) {
1015 // les champs de vr RET sont des caract
1016 // sauf (28,5) et (28,200) Pixel Location
1017 return((void *) strdup(buff));
1019 if ( (strcmp(vr, "US") == 0)
1020 || (strcmp(vr, "SS") == 0)
1022 (num == 0x0005 || num == 0x0200) ) ) { // les champs de vr RET sont des caract
1023 // sauf (28,5) et (28,200) Pixel Location
1024 // Buff should contain an int16
1025 caster = var_itoa(buff, 2);
1028 if ( (strcmp(vr,"UL") == 0)
1029 || (strcmp(vr,"SL") == 0) ) {
1030 // Buff should contain a guint32
1031 caster = var_itoa(buff, 2);
1034 if (DEBUG) printf("impossible de passer ici, mais le compilo rale\n");
1041 /* ============================================================================= */
1046 /* ----------------------------------------------------------------------- */
1048 _IdImprimerElement(char **TableauImageInfo, int numGroupe,
1049 int numElem, char *nomElem, int position)
1051 if (!TableauImageInfo[position])
1052 printf("%d : %s \t(%04x,%04x) pas trouve \n", position,
1053 nomElem, numGroupe, numElem);
1055 printf("%d : %s \t(%04x,%04x)\t[%s]\n", position,
1056 nomElem, numGroupe, numElem,
1057 TableauImageInfo[position]);
1060 /* ----------------------------------------------------------------------- */
1064 * \brief imprime la description des info 'pertinentes' d'une image DICOM
1065 * obtenue par IdDcmInquireImageInfoFromXXX (File/DcmHdr)
1067 * @param TableauImageInfo Tableau des info.
1069 * Pour avoir la liste a jour des DICOM Elements renvoyes par IdDcmInquireImageInfo
1070 * Consultez le fichier src/dicom.c
1073 * 0 : pointeur sur Tableau NULL
1077 IdDcmPrintImageInfo(char **TableauImageInfo) {
1083 if (!TableauImageInfo) return(0);
1085 for(k=0;k<_ID_Number_of_Items;k++) {
1086 _IdImprimerElement(TableauImageInfo, t[k].dicom_group,
1088 t[k].dicom_info_libelle,
1089 t[k].dicom_info_ind);
1096 /* ----------------------------------------------------------------------- */
1099 void IdDcmAffDcmHdr(ID_DCM_HDR *e, int npriv, int noffset) {
1102 DICOM_ELEMENTS *t = NULL;
1104 PLIST_ELEMENT plelem;
1107 /* MANQUE le retrait, avant impression en %s, des caract non ASCII */
1110 plelem = IdLstFirst(pl);
1114 ple= IdLstPtrObj(plelem); // le _ID_DCM_ELEM pointé par le PLIST_ELEMENT
1117 if(!npriv) printf("\n");
1119 for (t=_ID_dicom_elements; t->dicom_group!=0xffff; t++) {
1120 if( (t->dicom_group==ple->Gr) && (t->dicom_elem==ple->Num) ) break;
1123 if(!(ple->Gr%2) || !npriv) {
1126 printf(" gr %04x num %04x long %d",
1127 ple->Gr, ple->Num, ple->LgrLueElem);
1129 printf(" gr %04x num %04x long %d _offset %d",
1130 ple->Gr, ple->Num, ple->LgrLueElem, ple->Offset);
1135 if(ple->VR == NULL) {
1136 if(!(ple->Gr%2) || !npriv) printf("\t%s\t%s\t\t",
1137 t->dicom_type, t->dicom_libelle);
1139 if(!(ple->Gr%2) || !npriv) printf("\t%s\t%s\t\t",
1140 ple->VR, t->dicom_libelle);
1145 if(!(ple->Gr%2) || !npriv){
1146 printf(" lgr du grp = %d\n -------\n",
1147 str2num(ple->valeurElem,int) );
1150 switch (ple->LgrElem) {
1154 if ( (strcmp(t->dicom_type, "US") == 0)
1155 || (strcmp(t->dicom_type, "SS") == 0)
1156 || (t->dicom_group == 0x0028
1158 ( t->dicom_elem == 0x0005
1159 || t->dicom_elem == 0x0200) ) ) {
1161 if(!(ple->Gr%2) || !npriv) {
1162 printf("\t \t \t %d \tx(%04x)\n",
1163 str2num(ple->valeurElem,unsigned short int),
1164 str2num(ple->valeurElem,unsigned short int) );
1168 if(!(ple->Gr%2) || !npriv){
1169 printf("\t[%s] \t %d \tx(%04x)\n",
1171 str2num(ple->valeurElem,unsigned short int),
1172 str2num(ple->valeurElem,unsigned short int));
1179 if ( (strcmp(t->dicom_type,"UL") == 0)
1180 || (strcmp(t->dicom_type,"SL") == 0) ) {
1181 if(!(ple->Gr%2) || !npriv) {
1182 printf("\t \t \t %d \tx(%08x)\n",
1183 str2num(ple->valeurElem,int),
1184 str2num(ple->valeurElem,int));
1187 if(!(ple->Gr%2) || !npriv) {
1188 printf("\t[%s] \t %d \tx(%08x)\n",
1190 str2num(ple->valeurElem,int),
1191 str2num(ple->valeurElem,int));
1196 default : // AUTRES LGR
1198 if (ple->LgrElem > 5000) {
1199 if(!(ple->Gr%2) || !npriv)
1200 printf(" --> Too Long. Not Printed...\n");
1202 if(!(ple->Gr%2) || !npriv)
1203 printf(" \t[%s]\n",ple->valeurElem);
1207 plelem = IdLstNext(plelem);
1211 // -----------------------------------------------------------------------------------------------
1215 * \brief Verifie le caractère Acr/Dcm/LibIdo d'un fichier.
1217 * @param filename Nom du Fichier
1218 * @return ID_DCM_HDR (ca sera fait pour plus tard) si lisible
1223 ID_DCM_HDR * IdDcmIsDcmReadable(char * filename) {
1225 return IdDcmReadFile(filename, 0xFFFF);
1229 // ----------------------------------------------------------------------------------------------
1234 * \brief Verifie le caractère Jpeg Lossless d'un fichier, a partir du DCM_HDR.
1236 * @param e ID_DCM_HDR deja cree
1237 * @return 1 si Jpeg Losless
1242 int IdDcmIsJpegLossless (ID_DCM_HDR * e) {
1243 char * Derivation_Description;
1244 char * Transfert_Syntax_UID;
1245 char * valeur = "Compress BN JPEG Lossless";
1250 Transfert_Syntax_UID = _IdDcmReadElement(0x0002, 0x0010, e);
1251 if (Transfert_Syntax_UID != NULL) {
1252 if ( (memcmp(Transfert_Syntax_UID + strlen(Transfert_Syntax_UID)-2, "70", 2) == 0)
1254 (memcmp(Transfert_Syntax_UID + strlen(Transfert_Syntax_UID)-2, "55", 2) == 0) ) {
1257 Derivation_Description = _IdDcmReadElement(0x0008, 0x2111, e);
1258 if (Derivation_Description != NULL) {
1259 if (memcmp (Derivation_Description, valeur, strlen(valeur)) == 0)