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

acrutil.c

Go to the documentation of this file.
00001 /************************************************************************* 00002 * $Id: acrutil.c,v 1.3 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 /************************************************************************* 00037 * * PROJET : libido 00038 * NOM DU MODULE : utilacr.c * TYPE : fonction 00039 * AUTEUR : c.odet * CREATION : 07/05/1992 00040 * VERSION : 1.0 * REVISION : 16/06/1992 00041 * LANGAGE : C * 00042 * * 00043 ************************************************************************** 00044 * 00045 * Description : fonction utilitaires de gestion 00046 * du format ACRNEMA modifie UA1216 00047 * 00048 * ACR_ELEMENT *_IdAcrMakeElement(int gr, int nu,int size, long type, long init); 00049 * ACR_ELEMENT *_IdAcrAddElement(ACR_ELEMENT *liste,ACR_ELEMENT *elem); 00050 * ACR_ELEMENT *_IdAcrFreeListe(ACR_ELEMENT *liste); 00051 * ACR_ELEMENT *_IdAcrFindElement(ACR_ELEMENT *liste, int gr, int nu); 00052 * _IdAcrAdjustLength(ACR_ELEMENT *liste); 00053 * _IdAcrAffListe(ACR_ELEMENT *liste); 00054 * _AddHisto(char *l) 00055 00056 ************************************************************************** 00057 * 00058 * MODULES UTILISES : 00059 * 00060 ************************************************************************** 00061 * | | 00062 * REVISIONS : DATE | AUTEUR | DESCRIPTION 00063 *---------------------|--------------|------------------------------------ 00064 * 16/06/92 | B. BARBIER | Insertion LibIDO 00065 * / / | | 00066 * 01/10/92 | B. Barbier | V1.2-5 : normalisation des noms 00067 15/12/94 JPR modif fonctions de swap 00068 29/01/95 JPR acceleration rech. ds l'entete 00069 12/02/96 JPR info de Swap 00070 7/2/97 JPR PROBLEME pour les elements 'chaine de caract' : 00071 Ils doivent etre alloues 00072 AVANT l'appel de IdAcrReadElement 00073 10/02/97 JPR Verif Entete 00074 7/3/97 JPR _IdAcrOverWriteElement, _IdAcrGetElementLength 00075 6/5/98 JPR _IdAcrMergeListes 00076 12/5/98 JPR Modifs pour CardioVasc G.E. 00077 19.10.99 JPR Ajout libelles codes ACR / DICOM 00078 12/12/99 JPR Essai pour ACR curieux sur DEC 00079 24-01-2000 FB Initialisations 00080 27-01-2000 JPR impression offset 00081 28-01-2000 JPR _IdAcrReadElementR 00082 21-02-2000 JPR Modifs pour lire format GE pique sur MORGON 00083 12-07-2000 JPR Modif pour lire images VARIANT 00084 05-09-2000 JPR On ne swappe plus que les UL et les US 00085 07-09-2000 JPR ... et les RET 00086 18-9-2000 JPR Dorenavant, on ne recherche le type du DICOM Element 00087 que pour les groupes pairs 00088 20-11-2000 JPR Prise en compte des types OB OW SQ UN (Explicit VR) 00089 00090 00091 00092 ***********************************************************************/ 00093 #include <stdio.h> 00094 #include <stdlib.h> 00095 #include <limits.h> // For var_itoa 00096 #include <errno.h> 00097 00098 #include "idprint.h" 00099 #include <string.h> // For strlen 00100 00101 #include "iddicom.h" 00102 #include "idgen.h" 00103 #include "idima.h" 00104 #include "idacr.h" 00105 #include "idacr-restricted.h" 00106 00107 #ifdef WIN32 00108 #include <winsock.h> // Pour ntohs - BigEndianeries - 00109 #else 00110 #include <netinet/in.h> // Pour ntohs - BigEndianeries - 00111 #endif 00112 00113 00114 00115 long _IdAcrReadElement (int gr, int nu, FILE *fp, void *buff); 00116 long _IdAcrOverWriteElement (int gr, int nu, FILE *fp, void *buff); 00117 long _IdAcrGetElementLength (int gr, int nu, FILE *fp); 00118 uint32_t _IdAcrRecupLgr(FILE*, int *); 00119 void * _IdAcrReadElement_avec_creation(int gr, int num, FILE * fp, void *buff, int *lgrTrouvee); 00120 int _IdStrGetDicomTag (char* libelle, unsigned long *gr, unsigned long *num, char *vr); 00121 00122 short int SWAP_SHORT(short int a); 00123 uint32_t SWAP_LONG(uint32_t a); 00124 long _IdAcrOverWriteElementNumber(int gr, int num, FILE *fp, int nb); 00125 ACR_ELEMENT *_IdAcrModifyElement(ACR_ELEMENT *liste, ACR_ELEMENT *elem); 00126 00127 00128 00129 static int DEBUG=0; 00130 00131 static int __cas_de_fou_Philips=0; 00132 00133 static int sw; /* 0 pour pas de swapping 00134 3412 nouvelle org. des octets 00135 4321 pour les swapping 00136 2143 de long int */ 00137 00138 int __TrueDicom; /* 1 : contient DICM en 128 */ 00139 00140 int __ExplicitVR; /* 1 si le type est ecrit a l'interieur des 4 octets contenant la longueur */ 00141 00142 int __ID_offset; 00143 int __NumeroGroupePrecedent; 00144 static char VR[3]; 00145 00146 static int CardioVasc; /* 0 pour ACR/DICOM 'normal' 00147 1 pour DICOM CardioVasc */ 00148 00149 int __Papyrus; /* 0 pour ACR/DICOM-implicit-VR 00150 1 pour PAPYRUS */ 00151 00152 int __ID_CardioVascCurieux; /* 0 pour Normal (commence par (0008, 0000) */ 00153 /* 1 pour Curieux (commence par (0008, 0005) */ 00154 /* 1 pour Curieux (commence par (0008, 0002) */ 00155 00156 /* ======================================================================= 00157 * SWAP_SHORT 00158 * remet les octets dans un ordre compatible avec celui du processeur 00159 * (requiert d'avoir lance CheckSwap AVANT - pas ruse ...-) 00160 * ======================================================================= */ 00161 00162 short int SWAP_SHORT(short int a) { 00163 if ( (sw==4321) || (sw==2143) ) 00164 a =(((a<<8) & 0x0ff00) | ((a>>8)&0x00ff)); 00165 return (a); 00166 } 00167 00168 /* ======================================================================= 00169 * SWAP_LONG 00170 * remet les octets dans un ordre compatible avec celui du processeur 00171 * (requiert d'avoir lance CheckSwap AVANT - pas ruse ...-) 00172 * ======================================================================= */ 00173 00174 uint32_t SWAP_LONG(uint32_t a) { 00175 /* ATTENTION: il aura surement un pb pour les entiers negatifs ... 00176 * JPR 00177 */ 00178 switch (sw) { 00179 case 4321 : 00180 a=( ((a<<24) & 0xff000000) | ((a<<8) & 0x00ff0000) | 00181 ((a>>8) & 0x0000ff00) | ((a>>24) & 0x000000ff) ); 00182 break; 00183 case 3412 : 00184 a=( ((a<<16) & 0xffff0000) | ((a>>16) & 0x0000ffff) ); 00185 break; 00186 case 2143 : 00187 a=( ((a<<8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) ); 00188 break; 00189 default : 00190 IdPrintf("\n\n\n *******\n erreur code swap ?!?\n\n\n"); 00191 a=0; 00192 } 00193 return(a); 00194 } 00195 00196 /* 00197 * ======================================================================= 00198 * 00199 * _IdAcrTestSwap 00200 * 00201 * ======================================================================= 00202 */ 00203 00204 int 00205 _IdAcrTestSwap(uint32_t s) { 00206 00207 /* la valeur de sw montre 00208 * la nouvelle organisation des octets 00209 * dans un long int 00210 * 0 = pas de swap 00211 */ 00212 switch (s) { 00213 case 0x00040000 : 00214 sw=3412; 00215 if(DEBUG) IdPrintf("s : %08x sw : %d\n",s,sw); 00216 break; 00217 case 0x04000000 : 00218 sw=4321; 00219 if(DEBUG) IdPrintf("s : %08x sw : %d\n",s,sw); 00220 break; 00221 case 0x00000400 : 00222 sw=2143; 00223 if(DEBUG) IdPrintf("s : %08x sw : %d\n",s,sw); 00224 break; 00225 case 0x00000004 : 00226 sw=0; 00227 if(DEBUG) IdPrintf("s : %08x sw : %d\n",s,sw); 00228 break; 00229 default : 00230 sw = -1; 00231 if (DEBUG) IdPrintf ( "_IdAcrTestSwap (1): Pas trouve " 00232 "l info de Swap : s= %x -> sw=-1 \n",s); 00233 } 00234 return (sw); 00235 } 00236 00237 /* ======================================================================= 00238 00239 _IdAcrCheckSwap 00240 La seule maniere sure que l'on aie pour determiner 00241 si on est en LITTLE_ENDIAN, BIG-ENDIAN, 00242 BAD-LITTLE-ENDIAN, BAD-BIG-ENDIAN 00243 est de trouver l'element qui donne la longueur d'un 'GROUP' 00244 (on sait que la longueur de cet element vaut 0x00000004) 00245 et de regarder comment cette longueur est codee en memoire 00246 00247 Le probleme vient de ce que parfois, il n'y en a pas ... 00248 00249 On fait alors le pari qu'on a a faire a du LITTLE_ENDIAN propre. 00250 Si ce n'est pas le cas, om ne peut rien faire. 00251 00252 (il faudrait avoir des fonctions auxquelles 00253 on passe le codeSwap en parametre, pour faire des essais 'manuels') 00254 00255 ======================================================================= */ 00256 int _IdAcrCheckSwap(FILE * fp) { 00257 uint32_t bili2,x=4; 00258 char DICM[16]; 00259 00260 __Papyrus = 0; 00261 CardioVasc = 0; 00262 __ID_CardioVascCurieux = 0; 00263 00264 /* On commence par verifier si c'est du DICOM 'actuel' */ 00265 /* ------------- */ 00266 00267 fseek(fp,128L,SEEK_SET); 00268 fread(&DICM,4,1,fp); 00269 DICM[4] = 0; 00270 00271 if(memcmp(DICM, "DICM", (size_t)4) == 0) 00272 { 00273 __TrueDicom=1; 00274 __ID_offset=132L; /* a voir ... */ 00275 if (DEBUG) IdPrintf ("_IdAcrCheckSwap : C est du DICOM actuel ->%s<-\n",DICM); 00276 } 00277 else 00278 { 00279 __TrueDicom=0; 00280 __ID_offset=0L; /* a voir ... */ 00281 if (DEBUG) IdPrintf ("_IdAcrCheckSwap : Ce n'est PAS du DICOM actuel ->%s<-\n",DICM); 00282 } 00283 00284 if(__TrueDicom) 00285 { 00286 00287 rewind(fp); 00288 fseek(fp,136L,SEEK_SET);/* on saute le File Preamble (souvent a ZERO) : 128 Octets */ 00289 /* le DICM, et le 0002, 0000 */ 00290 00291 fread(&DICM,4,1,fp); /* les 2 premiers octets de la lgr peuvent valoir UL 00292 (ou OB si le premier est (0008, 0001) -> Explicit VR */ 00293 if(memcmp(DICM, "UL", (size_t)2) == 0) { 00294 __ExplicitVR = 1; 00295 if (DEBUG) IdPrintf ("_IdAcrCheckSwap : Explicit VR\n"); 00296 } else { 00297 __ExplicitVR = 0; 00298 } 00299 00300 if (x!=(x)) { /* si le HostByteOrder est different du NetworkByteOrder */ 00301 sw = 0; /* on est sur PC ou DEC --> LITTLE-ENDIAN -> Rien a faire */ 00302 if (DEBUG) IdPrintf("HostByteOrder = NetworkByteOrder\n"); 00303 00304 } else { /* on est sur une Sun ou une SGI */ 00305 sw = 4321; 00306 if (DEBUG) IdPrintf("HostByteOrder != NetworkByteOrder\n"); 00307 } 00308 00309 rewind(fp); 00310 fseek(fp,132L,SEEK_SET); 00311 return sw; 00312 00313 } /* fin TrueDicom */ 00314 00315 00316 00317 /* ----- SINON ----- */ 00318 00319 00320 00321 /* Si c'est de l'ACR 'propre', la lgr du premier element du groupe est FORCEMENT 4 */ 00322 00323 fseek(fp,4L,SEEK_SET); /* SEEK_SET = 0 */ 00324 fread(&bili2,4,1,fp); /* lgr groupe : 0000 0004 JPR */ 00325 if (DEBUG) IdPrintf( "_IdAcrCheckSwap (2) : bili2 %08x\n", bili2); 00326 00327 sw=_IdAcrTestSwap(bili2); 00328 00329 __ID_offset=0; 00330 00331 /* Si c'est de l'ACR 'pas propre', il manque la lgr du groupe */ 00332 00333 if(sw==-1) 00334 { 00335 00336 /* pour tenter de lire DICOM CardioVasc G.E. */ 00337 00338 rewind(fp); 00339 fseek(fp,136L,SEEK_SET); /* SEEK_SET = 0 */ 00340 fread(&bili2,4,1,fp); /* lgr groupe : 0000 0004 JPR */ 00341 if (DEBUG) IdPrintf( "_IdAcrCheckSwap (3) : bili2 %08x\n", bili2); 00342 sw=_IdAcrTestSwap(bili2); 00343 00344 if (sw != -1) 00345 { 00346 00347 CardioVasc = 1; 00348 rewind(fp); 00349 fseek(fp,132L,SEEK_SET); 00350 __ID_offset=132; 00351 IdPrintf("\n\n\n\n NORMALEMENT, ON NE PASSE PLUS ICI (si c'est le cas, prevenez-moi JPRx)\n"); 00352 IdPrintf("\n\nsw = %d\n\n\n",sw); 00353 if (DEBUG) IdPrintf( " <<CardioVasc (ou autre 'curiosite' ...)>>\n"); 00354 } 00355 else 00356 { 00357 /* On n'a pas trouve l'info de swap 28/11/2000 JPR */ 00358 /* Si c'est du VRAI ACR NEMA si on est sur une DEC ou un PC swap=0, SUN ou SGI SWAP=4321 */ 00359 /* si c'est du RAW, ca degagera + tard */ 00360 00361 if (DEBUG) IdPrintf("On force la chance \n"); 00362 00363 if (x!=(x)) /* si le HostByteOrder est different du NetworkByteOrder */ 00364 sw = 0; /* on est sur PC ou DEC --> LITTLE-ENDIAN -> Rien a faire */ 00365 else 00366 sw = 4321; /* on est sur Sun ou SGI */ 00367 } 00368 } 00369 00370 rewind(fp); 00371 return (sw); 00372 } 00373 00374 00375 00376 /* ======================================================================= 00377 int _IdStrGetDicomTag(char * label, int *gr, int * num, char *vr) 00378 00379 recherche le Dicom tag d'un libelle donne 00380 par inspection du Dictionnaire DICOM 00381 (retourne 0 si pas trouve) 00382 ======================================================================= */ 00383 00384 int _IdStrGetDicomTag (char* libelle, unsigned long *gr, unsigned long *num, char *vr) 00385 { 00386 00387 DICOM_ELEMENTS *t; 00388 int i; 00389 00390 t=_ID_dicom_elements; 00391 00392 for (i=0; t[i].dicom_group != 0xffff; i++) { 00393 if( strcmp(t[i].dicom_libelle, libelle) ==0 ) 00394 00395 { 00396 *gr= t[i].dicom_group; 00397 *num=t[i].dicom_elem; 00398 vr =t[i].dicom_type; 00399 return(1); 00400 } 00401 } 00402 return(0); 00403 00404 } 00405 00406 // Converts an integer represented with num_byte bytes within the 00407 // buffer buff to a string. 00408 // Refer to comp.lang.faq FAQ, question 12.21 : How can I tell how much 00409 // destination buffer space I'll need for an arbitrary sprintf call? How can 00410 // I avoid overflowing the destination buffer with sprintf? 00411 00412 static char * var_itoa(void * buff, int num_byte) 00413 { 00414 char * retbuf; 00415 00416 // We double the recommended value since we also have to deal 00417 // with long integers. Pfff... 00418 retbuf = malloc(2 * ( (sizeof(int) * CHAR_BIT + 2) / 3 + 1 + 1)); 00419 switch (num_byte) { 00420 case 2: 00421 sprintf(retbuf, "%d", *((int*)buff)); 00422 break; 00423 case 4: 00424 sprintf(retbuf, "%dl", *((int*)buff)); 00425 break; 00426 default: 00427 sprintf(retbuf, "var_itoa?????"); 00428 } 00429 return retbuf; 00430 } 00431 00448 void * 00449 _IdAcrReadElementFromLabel(char *libelle, FILE * fp, char * vr, void *buff) 00450 { 00451 int lgrTrouvee; 00452 int i; 00453 unsigned long gr; 00454 unsigned long num; 00455 char * caster; 00456 00457 i = _IdStrGetDicomTag (libelle, &gr, &num, vr); 00458 00459 if (i == 0) { 00460 if (DEBUG) IdPrintf("champ [%s] (%08x , %08x) pas trouve\n"); 00461 caster = malloc(4); 00462 sprintf(caster, "???"); 00463 return (void*)caster; 00464 //return (NULL); 00465 } 00466 buff = _IdAcrReadElement_avec_creation(gr, num, fp, buff, &lgrTrouvee); 00467 if (lgrTrouvee == 0) { 00468 caster = malloc(4); 00469 sprintf(caster, "???"); 00470 return (void*)caster; 00471 } 00472 if ( (strcmp(vr,"UL") != 0) 00473 && (strcmp(vr,"US") != 0) 00474 && (strcmp(vr,"SL") != 0) 00475 && (strcmp(vr,"SS") != 0) 00476 && (gr != 0x0028 || 00477 ( num != 0x0005 && num != 0x0200) ) ) { // les champs de vr RET sont des caract 00478 // sauf (28,5) et (28,200) Pixel Location 00479 // Buff should contain a string. End the string properly 00480 caster = (char*)buff; 00481 // FIXME : in fact we should have written 00482 // caster[lgrTrouvee + 1] = '\0' but better 'eating' one 00483 // character than depend on alloaction of buff. 00484 caster[lgrTrouvee] = '\0'; 00485 return((void *) buff); 00486 } 00487 if ( (strcmp(vr, "US") == 0) 00488 || (strcmp(vr, "SS") == 0) ) { 00489 // Buff should contain an int16 00490 caster = var_itoa(buff, 2); 00491 return((void *) caster); 00492 } 00493 if ( (strcmp(vr,"UL") == 0) 00494 || (strcmp(vr,"SL") == 0) 00495 || (gr == 0x0028 && 00496 (num == 0x0005 || num == 0x0200) ) ) { // les champs de vr RET sont des caract 00497 // sauf (28,5) et (28,200) Pixel Location 00498 00499 // Buff should contain a uint32_t 00500 caster = var_itoa(buff, 2); 00501 return((void *) caster); 00502 } 00503 if (DEBUG) IdPrintf("impossible de passer ici, mais le compilo rale\n"); 00504 return (NULL); 00505 00506 } 00507 00508 00509 00510 00511 /* ======================================================================= 00512 _IdAcrReadElement 00513 00514 lit un acr_element et le range dans buff 00515 retourne la taille de l'acr_element 00516 (non lu si buff =0) 00517 (le fichier doit deja avoir ete ouvert, 00518 et _IdAcrCheckSwap(FILE * fp) avoir ete appelle) 00519 00520 ATTENTION : C'est a l'utilisateur de savoir si l'element lu 00521 est un entier ou une chaine de caract 00522 ======================================================================= */ 00523 00524 00543 long _IdAcrReadElement(int gr, int num, FILE * fp, void *buff) 00544 { 00545 int lgrTrouvee; 00546 00547 _IdAcrReadElement_avec_creation (gr, num, fp, buff, &lgrTrouvee); 00548 00549 return(lgrTrouvee); 00550 } 00551 00552 00553 /* ======================================================================= 00554 _IdAcrReadElement_avec_creation 00555 00556 lit un acr_element 00557 le range dans buff s'il est alloue, 00558 l'alloue sinon 00559 retourne buff dans tous les cas 00560 00561 ATTENTION : C'est a l'utilisateur de savoir si l'element lu 00562 est un entier ou une chaine de caract 00563 00564 Cette fonction est rendue necessaire, car _IdAcrReadElement, 00565 utilisee helas partout, n'alloue pas. 00566 00567 (le fichier doit deja avoir ete ouvert, 00568 et _IdAcrCheckSwap(FILE * fp) avoir ete appelle) 00569 00570 00571 ======================================================================= */ 00572 00573 00574 00595 void * _IdAcrReadElement_avec_creation(int gr, int num, FILE * fp, void *buff, int *lgrTrouvee) 00596 { 00597 00598 DICOM_ELEMENTS *t = NULL; 00599 uint32_t l, l_gr; 00600 int flag; 00601 int skL; 00602 int cherche_vr=0; 00603 unsigned short g; 00604 unsigned short n; 00605 00606 if (DEBUG) IdPrintf("\t\t\t\t\trecherche (1) gr %x num %x (swapping %d)\n",gr,num,sw); 00607 00608 __cas_de_fou_Philips=0; 00609 00610 l=0; 00611 flag=0; 00612 while(fread(&g,2,1,fp)) 00613 { 00614 if(sw)g=SWAP_SHORT(((short)g)); 00615 fread(&n,2,1,fp); 00616 if(sw)n=SWAP_SHORT(((short)n)); 00617 // Lecture de la longueur de l'element 00618 l = _IdAcrRecupLgr(fp, &skL); 00619 00620 00621 if (DEBUG) IdPrintf(" -------------> gr %x num %x long %x : %d\n",g,n,l,l); 00622 00623 if(gr>g) /* on est plus haut que l'element cherche */ 00624 flag=1; /* si on ne le trouve pas des le premier coup */ 00625 /* c'est qu'il n'y est pas */ 00626 if (0) // pour voir si pb de lgr groupe 00627 /*if((gr>g)&&(n==0)) */ /* on est sur un debut de groupe */ 00628 { 00629 fread(&l_gr,4,1,fp); //on lit la longueur du groupe 00630 if(sw) l_gr = SWAP_LONG(((uint32_t)l_gr)); 00631 00632 fseek(fp,l_gr,SEEK_CUR); /* on saute le groupe */ 00633 00634 if (DEBUG) 00635 { 00636 IdPrintf(" on saute au gr sv :%d car\n",l_gr); 00637 } 00638 } 00639 00640 else if((g==gr)&&(n==num)) /* on est sur l'element recherche */ 00641 /* ------------------------------ */ 00642 { 00643 if (buff == NULL) // On alloue, en essayant de ne pas se vautrer ... 00644 00645 { // desole pour la cascade de if, 00646 // mais il n'y a pas d'operateur AND THEN en C ... 00647 00648 if ( (g/2)*2-g==0 ) // on ne recherche que pour les groupes pairs 00649 { 00650 00651 if ((l==2) ) { 00652 cherche_vr=1; // on signale qu'on a deja cherche ds dict. Dicom 00653 for (t=_ID_dicom_elements; t->dicom_group!=0xffff; t++) { 00654 if( (t->dicom_group==g) && (t->dicom_elem==n) ) break; 00655 } 00656 00657 if ( (strcmp(t->dicom_type,"UL") ==0) 00658 || (strcmp(t->dicom_type,"US") ==0) ) 00659 buff = malloc(2); /* on alloue un int 16 */ 00660 } 00661 else 00662 if ((l==4) ) { 00663 cherche_vr=1; 00664 for (t=_ID_dicom_elements; t->dicom_group!=0xffff; t++) { 00665 if( (t->dicom_group==g) && (t->dicom_elem==n) ) break; 00666 } 00667 00668 if ( (strcmp(t->dicom_type,"SL") ==0) 00669 || (strcmp(t->dicom_type,"SS") ==0) ) 00670 buff = malloc(4); /* on alloue un int 32 */ 00671 } 00672 } 00673 // On peut esperer que les subtilites c-dessus ne servent jamais... 00674 00675 buff = malloc(l+1); // c'est une chaine de caracteres 00676 } 00677 00678 fread(buff,(int)l,1,fp); 00679 00680 00681 if(sw) { 00682 if ( (g/2)*2-g==0 ) { /* on ne teste pas les groupes impairs */ 00683 00684 if ((l==4)||(l==2)) { /*pour eviter de swapper les chaines 00685 de lgr 2 ou 4 */ 00686 00687 if(cherche_vr ==0) { //si on n'a jamais inspecte le dict. Dicom 00688 00689 if (DEBUG) IdPrintf("Consultation Dictionaire DICOM" 00690 " g %08x n %08x l %d\n",g,n,l); 00691 for (t=_ID_dicom_elements; t->dicom_group!=0xffff; t++) { 00692 if( (t->dicom_group==g) && (t->dicom_elem==n) ) break; 00693 } 00694 } 00695 00696 if ( (strcmp(t->dicom_type,"UL") ==0) 00697 || (strcmp(t->dicom_type,"US") ==0) 00698 || (strcmp(t->dicom_type,"SL") ==0) 00699 || (strcmp(t->dicom_type,"SS") ==0) 00700 || (gr == 0x0028 && 00701 ( num == 0x0005 || num == 0x0200) ) ) 00702 { // les champs de vr RET sont des caract 00703 // sauf (28,5) et (28,200) Pixel Location 00704 00705 if(l==4) { 00706 *(uint32_t *) buff=SWAP_LONG ((*(uint32_t *) buff)); 00707 } 00708 00709 else if(l==2) { 00710 *(short *) buff=SWAP_SHORT ((*(short *) buff)); 00711 } 00712 00713 if(DEBUG) if ((l==4)||(l==2)) { IdPrintf("on swappe\n");} 00714 } 00715 } /* fin if l==2 ==4 */ 00716 } /* fin if g pair */ 00717 } /* fin sw */ 00718 00719 //return l; 00720 *lgrTrouvee=l; 00721 return ((void *)buff); 00722 } 00723 00724 else if((g>gr)||((gr==g)&&(n>num))) /* on a depasse l'element */ 00725 /* ---------------------- */ 00726 { 00727 if ( g > 0xff00 ) { // on est dans le cas de fou Philips 00728 // ou des Tags ne sont pas dans l'ordre 00729 if (DEBUG) IdPrintf("\t\t\t\t\t\t =============Tags pas dans l'ordre (cas de fou) " 00730 " gr %04x %d g %04x %d\n",gr,gr,g,g); 00731 __cas_de_fou_Philips=1; 00732 fseek(fp,l,SEEK_CUR); 00733 } else { 00734 00735 if(flag) /*on a deja re-essaye depuis le debut */ 00736 { /* l'element cherche n'y est pas */ 00737 fseek(fp,l,SEEK_CUR);/*on se positionne sur l'element sv */ 00738 *lgrTrouvee=0; 00739 return((void *)NULL); /* On sort JPR */ 00740 } 00741 00742 rewind(fp); 00743 if ((CardioVasc == 1) || (__TrueDicom == 1)) 00744 fseek(fp,132L,SEEK_SET); /* pour CardioVasc G.E. ??? a revoir */ 00745 00746 flag=1; /* On va re-essayer depuis le debut */ 00747 } 00748 } 00749 00750 else { /* on saute a l'element suivant */ 00751 /* ---------------------------- */ 00752 fseek(fp,l,SEEK_CUR); 00753 } 00754 } 00755 // 00756 *lgrTrouvee=0; 00757 return ((void *)NULL); 00758 } 00759 00760 00761 00762 /* ======================================================================= 00763 _IdAcrReadNextElement 00764 00765 lit l'acr_element courant 00766 00767 mode= 1 : on charge EGALEMENT les Elements 'longs' (>5000) , 00768 0 : on NE CHARGE PAS les Elements 'longs' (>5000) , 00769 00770 (le fichier doit deja avoir ete ouvert, 00771 et _IdAcrCheckSwap(FILE * fp) avoir ete appelle) 00772 00773 00774 ======================================================================= */ 00775 00776 00793 ACR_ELEMENT * _IdAcrReadNextElement(FILE *fp, int mode) 00794 { 00795 unsigned short g; 00796 unsigned short n; 00797 uint32_t l; 00798 uint32_t type=0; 00799 int skL; 00800 ACR_ELEMENT *p; 00801 DICOM_ELEMENTS *t; 00802 char * buff = NULL; 00803 00804 if (DEBUG) IdPrintf(" ===> entree ds _IdAcrReadNextElement\n"); 00805 fread(&g,2,1,fp); 00806 if (feof(fp)) {if (DEBUG) IdPrintf("_IdAcrReadNextElement : eof trouve\n");return (NULL);} 00807 if (ferror(fp)) { IdPrintf("echec lecture NumGr\n"); return (NULL);} 00808 00809 if (sw) g=SWAP_SHORT(((short)g)); 00810 /* 00811 if (g < __NumeroGroupePrecedent) { 00812 IdPrintf("Gros malaise : num de groupe pas dans l'ordre : (%04x) apres (%04x)\n",g, __NumeroGroupePrecedent ); 00813 } 00814 */ 00815 __NumeroGroupePrecedent =g; 00816 00817 fread(&n,2,1,fp); 00818 if (ferror(fp)) {IdPrintf("echec lecture NumElem\n");return (NULL);} 00819 if (feof(fp)) {IdPrintf("echec lecture NumElem\n");return (NULL);} 00820 00821 if(sw)n=SWAP_SHORT(((short)n)); 00822 00823 // Lecture de la longueur de l'element 00824 00825 l = _IdAcrRecupLgr(fp,&skL); 00826 00827 if (DEBUG) if (n!=0) IdPrintf("_IdAcrReadNextElement : " 00828 " gr %x\tnum %x\tlong %x (%d)", 00829 g,n,l,l); 00830 00831 if (l < 5000 || mode ==1) 00832 { 00833 buff=malloc(l+1); 00834 buff[l]=0; 00835 00836 if(buff) fread(buff,(int)l,1,fp); 00837 if (ferror(fp)) {IdErrPrintf("echec lecture Element\n");return (NULL);} 00838 if (feof(fp)) {IdErrPrintf("echec lecture Element\n");return (NULL);} 00839 00840 if ((n==0) && sw) *(uint32_t *) buff=SWAP_LONG ((*(uint32_t *) buff)); // n=0 : lgr du groupe 00841 else 00842 if(sw) { 00843 if ( (g/2)*2-g==0) { /* on ne teste pas les groupes impairs */ 00844 // if (1) { // on teste MEME les groupes impairs ... 00845 00846 if ((l==4)||(l==2)) { //pour eviter d'explorer de Dict. DICOM 00847 // dans le cas de chaines 00848 // de lgr 2 ou 4 00849 if (DEBUG) IdPrintf("Consultation Dictionary DICOM g %04x n %0xx l %d\n",g,n,l); 00850 00851 for (t=_ID_dicom_elements; t->dicom_group!=0xffff; t++) { 00852 if( (t->dicom_group==g) && (t->dicom_elem==n) ) break; 00853 } 00854 if ( (strcmp(t->dicom_type,"UL") ==0) 00855 || (strcmp(t->dicom_type,"US") ==0) 00856 || (strcmp(t->dicom_type,"SL") ==0) 00857 || (strcmp(t->dicom_type,"SS") ==0) 00858 || (g == 0x0028 && 00859 ( n == 0x0005 || n == 0x0200) ) ) { // seuls (28,5) de vr RET 00860 // et (28,200) sont des entiers 00861 00862 if(l==4) 00863 *(uint32_t *) buff=SWAP_LONG ((*(uint32_t *) buff)); 00864 else if(l==2) 00865 *(unsigned short *) buff=SWAP_SHORT ((*(unsigned short *) buff)); 00866 } 00867 } /* fin if l==2 ==4 */ 00868 } /* fin if g pair */ 00869 } /* fin sw */ 00870 00871 00872 switch (l) { 00873 case 2: type = BI; break; 00874 case 4: type = BD; break; 00875 default: if(l>5000) type=NO; else type = AT; 00876 } 00877 00878 } /* fin (l < 5000 || mode ==1) */ 00879 00880 else 00881 { 00882 if (DEBUG) IdPrintf(" --> Element too long. Skipped\n"); 00883 fseek(fp,l,SEEK_CUR); 00884 } 00885 00886 if (DEBUG) 00887 { 00888 if (n==0) IdPrintf(" gr %x\tnum %x\tlong %d lgr_grp = %d\n", 00889 g,n,l,*(uint32_t *) buff); 00890 00891 else if (l==2) { ((char *)buff)[2]=0; 00892 IdPrintf("\t\t[%s] \tval = %d \tx(%04x)\n", 00893 buff, *(unsigned short int *) buff, *(unsigned short int *) buff); 00894 } 00895 00896 else if (l==4) { ((char *)buff)[4]=0; 00897 IdPrintf("\t\t[%s] \tval = %d \tx(%08x)\n", 00898 buff, *(uint32_t *) buff , *(uint32_t *) buff); 00899 } 00900 00901 else if (l<5000 ) 00902 { 00903 ((char *)buff)[l]=0; 00904 IdPrintf("\t\t[%s]\n", (char *)buff); 00905 } 00906 00907 else IdPrintf(" --> Element too long. Not Printed\n"); 00908 } 00909 00910 if((p=(ACR_ELEMENT *)calloc(1, sizeof(ACR_ELEMENT)))!=0) 00911 00912 { 00913 p->group= (unsigned short int)g; 00914 p->number=(unsigned short int)n; 00915 p->length=(uint32_t)l; 00916 p->skippedLength=(uint32_t)skL; /* pour AffListe2 */ 00917 p->type= type; 00918 p->suiv= 0; 00919 p->value= (long int)(buff); 00920 } 00921 else 00922 IdPrintf("PB allocation memoire ACR_ELEMENT\n"); 00923 00924 if (DEBUG) IdPrintf(" ===> sortie de _IdAcrReadNextElement\n"); 00925 00926 return(p); 00927 00928 } 00929 00930 /* ======================================================================= 00931 _IdAcrGetElementLength 00932 00933 Recherche un acr_element et renvoie sa longueur 00934 (0 si pas trouve) 00935 00936 (le fichier doit deja avoir ete ouvert, 00937 et _IdAcrCheckSwap(FILE * fp) avoir ete appelle) 00938 00939 00940 ======================================================================= */ 00941 00955 long _IdAcrGetElementLength(int gr, int num, FILE *fp) 00956 { 00957 uint32_t l, l_gr; 00958 int flag; 00959 unsigned short g; 00960 unsigned short n; 00961 int skL; 00962 00963 if (DEBUG) IdPrintf("recherche (2) gr %x num %x (swapping %d)\n",gr,num,sw); 00964 00965 l=0; 00966 flag=0; 00967 while(fread(&g,2,1,fp)) 00968 { 00969 if(sw)g=SWAP_SHORT(((short)g)); 00970 fread(&n,2,1,fp); 00971 if(sw)n=SWAP_SHORT(((short)n)); 00972 l = _IdAcrRecupLgr(fp,&skL); 00973 00974 00975 if (DEBUG) IdPrintf(" -------------> gr %x num %x long %x : %d\n",g,n,l,l); 00976 00977 if(gr>g) /* on est plus haut que l'element cherche */ 00978 flag=1; /* si on ne le trouve pas des le premier coup */ 00979 /* c'est qu'il n'y est pas JPR */ 00980 if((gr>g)&&(n==0)) /* on est sur un debut de groupe JPR */ 00981 { 00982 00983 fread(&l_gr,4,1,fp); //on lit la longueur du groupe 00984 if(sw) l_gr = SWAP_LONG(((uint32_t)l_gr)); 00985 00986 fseek(fp,l_gr,SEEK_CUR); 00987 if (DEBUG) IdPrintf(" on saute au gr sv :%d car\n",l_gr); 00988 } 00989 00990 else if((g==gr)&&(n==num)) /* on est sur l'element recherche */ 00991 /* ------------------------------ */ 00992 { 00993 return l; /* on renvoie sa longueur */ 00994 } 00995 00996 else if((g>gr)||((gr==g)&&(n>num))) /* on a depasse l'element */ 00997 { 00998 if(flag) /*on a deja re-essaye depuis le debut */ 00999 { /* l'element cherche n'y est pas */ 01000 fseek(fp,l,SEEK_CUR);/*on se positionne sur l'element sv */ 01001 return(0); /* On sort JPR */ 01002 } 01003 fseek(fp,l,SEEK_SET); 01004 flag=1; /* On va re-essayer depuis le debut */ 01005 01006 if ((CardioVasc == 1) || (__TrueDicom == 1)) 01007 fseek(fp,132L,SEEK_SET); /* pour CardioVasc G.E. */ 01008 01009 } 01010 01011 else { /* on saute a l'element suivant */ 01012 fseek(fp,l,SEEK_CUR); 01013 } 01014 } 01015 return(0); 01016 } 01017 01018 01019 /* ======================================================================= 01020 * _IdAcrRecupLgr 01021 * 01022 * ACR-NEMA : On a toujours 01023 * GroupNumber (2 Octets) 01024 * ElementNumber (2 Octets) 01025 * ElementSize (4 Octets) 01026 * 01027 * 01028 * DICOM : On peut avoir (implicit Value Representation) 01029 * GroupNumber (2 Octets) 01030 * ElementNumber (2 Octets) 01031 * ElementSize (4 Octets) 01032 * 01033 * On peut avoir (explicit Value Representation) 01034 * GroupNumber (2 Octets) 01035 * ElementNumber (2 Octets) 01036 * ValueRepresentation (2 Octets) 01037 * ElementSize (2 Octets) 01038 * 01039 * ATTENTION : dans le cas ou ValueRepresentation = OB, OW, SQ, UN 01040 * GroupNumber (2 Octets) 01041 * ElementNumber (2 Octets) 01042 * ValueRepresentation (2 Octets) 01043 * zone reservee (2 Octets) 01044 * ElementSize (4 Octets) 01045 * 01046 * 01047 * ======================================================================= */ 01060 uint32_t _IdAcrRecupLgr(FILE *fp, int *skippedLength) 01061 { 01062 uint32_t l_gr; 01063 unsigned short int l_gr_2; 01064 int i, trouve; 01065 01066 /* 01067 * 01068 * ATTENTION : 01069 * 01070 * c'est TRES gorret 01071 * mais je n'ai pas le temps d'inventer qq chose de propre :-( 01072 * 01073 */ 01074 01075 int nbCode=26; // nombre d'elements dans la table de type DICOM_VR definie dans dicom.c 01076 01077 01078 if (__ExplicitVR == 1) { 01079 01080 fread(VR,2,1,fp); 01081 VR[2]=0; 01082 01083 // ATTENTION : 01084 // Ce n'est pas parce qu'on a trouve UL la premiere fois qu'on respecte 01085 // Explicit VR tout le temps 01086 // (cf e=film ...) 01087 // A completer par le test de ttes les valeurs possibles :-( 01088 01089 for(i=0,trouve=0;i<nbCode;i++) { 01090 //printf(" %d , %s\n", i,_ID_dicom_vr[i].dicom_VR); 01091 if(memcmp(_ID_dicom_vr[i].dicom_VR,VR,(size_t)2)==0) { 01092 trouve=1; 01093 break; 01094 } 01095 } 01096 01097 if ( trouve == 0) { 01098 01099 // On est mal : implicit VR repere 01100 // mais ce n'est pas un code connu ... 01101 // On reconstitue la longueur 01102 01103 if(DEBUG) IdPrintf("Explicit VR, mais pas trouve de code connu\n"); 01104 memcpy(&l_gr, VR,(size_t)2); 01105 fread( ((char*)&l_gr)+2,2,1,fp); 01106 if(sw) l_gr = SWAP_LONG(((uint32_t)l_gr)); 01107 if(DEBUG) IdPrintf("lgr deduite : %08x , %d\n",l_gr,l_gr); 01108 01109 if ( (int)l_gr == -1) { 01110 l_gr=0; 01111 } 01112 *skippedLength = 4; 01113 return(l_gr); 01114 } 01115 01116 // On repart dans la sequence 'sensee' 01117 01118 if(DEBUG) IdPrintf("VR : [%01x , %01x] en position %d du tableau\n", VR[0],VR[1],i); 01119 //printf(" %d , %s\n", i,_ID_dicom_vr[i].dicom_VR); 01120 if ( 01121 (!memcmp( VR,"OB",(size_t)2 )) || 01122 (!memcmp( VR,"OW",(size_t)2 )) || 01123 (!memcmp( VR,"SQ",(size_t)2 )) || 01124 (!memcmp( VR,"UN",(size_t)2 )) ) { 01125 01126 // les 2 octets suivants sont reserves 01127 01128 if(DEBUG) IdPrintf("les 2 octets suivants sont reserves\n"); 01129 fread(VR,2,1,fp); //on les saute 01130 fread(&l_gr,4,1,fp); //on lit la lgr sur QUATRE octets 01131 if(sw) l_gr = SWAP_LONG(((uint32_t)l_gr)); 01132 *skippedLength = 8; 01133 01134 } else { 01135 fread(&l_gr_2,2,1,fp); //on lit la lgr sur DEUX octets 01136 if(sw) l_gr_2 = SWAP_SHORT((unsigned short)l_gr_2); 01137 01138 if ( l_gr_2 == 0xffff) { 01139 l_gr = 0; 01140 } else { 01141 l_gr = l_gr_2; 01142 } 01143 *skippedLength = 4; 01144 } 01145 } else { // Explicit VR = 0 01146 01147 fread(&l_gr,4,1,fp); //on lit la lgr sur QUATRE octets 01148 if(sw)l_gr=SWAP_LONG(((long)l_gr)); 01149 *skippedLength = 4; 01150 } 01151 01152 if (l_gr == 0xffffffff) 01153 l_gr = 0; 01154 01155 return(l_gr); 01156 } 01157 01158 01159 01160 01161 /* =============================================== 01162 * 01163 * 01164 * ATTENTION : 01165 * Les trois fonctions qui suivent NE MARCHENT PAS 01166 * pour du DICOM en Explicit Value Representation 01167 * La VRAIE solution sera de faire un VRAI DICOM writer (?!) 01168 * 01169 ================================================= */ 01170 01171 01172 01173 01174 01175 /* ======================================================================= 01176 _IdAcrOverWriteElementNumber 01177 01178 Remplace le numero d'un acr_element existant par une valeur donnee 01179 (0 si pas trouve) 01180 A MANIER AVEC PRECAUTION 01181 01182 ATTENTION : le fichier doit avoir ete ouvert en ID_RFILE_P_BIN ... (rb+) 01183 ======================================================================= */ 01184 01185 long _IdAcrOverWriteElementNumber(int gr, int num, FILE *fp, int nb) 01186 { 01187 unsigned short g; 01188 unsigned short n; 01189 unsigned short numero; 01190 01191 uint32_t l, l_gr; 01192 int flag; 01193 int i, skL; 01194 numero=nb; /* on passe en USHORT */ 01195 01196 if (DEBUG) IdPrintf("recherche (3) gr %x num %x (swapping %d)\n",gr,num,sw); 01197 01198 l=0; 01199 flag=0; 01200 while(fread(&g,2,1,fp)) 01201 { 01202 if(sw)g=SWAP_SHORT(((short)g)); 01203 fread(&n,2,1,fp); 01204 if(sw)n=SWAP_SHORT(((short)n)); 01205 l = _IdAcrRecupLgr(fp,&skL); 01206 01207 if (DEBUG) IdPrintf(" -------------> gr %x num %x long %x : %d\n",g,n,l,l); 01208 01209 if(gr>g) /* on est plus haut que l'element cherche */ 01210 flag=1; /* si on ne le trouve pas des le premier coup */ 01211 /* c'est qu'il n'y est pas JPR */ 01212 if((gr>g)&&(n==0)) /* on est sur un debut de groupe JPR */ 01213 { 01214 fread(&l_gr,4,1,fp); 01215 if(sw)l_gr=SWAP_LONG(((long)l_gr)); /* on lit sa longueur */ 01216 fseek(fp,l_gr,SEEK_CUR); 01217 if (DEBUG) IdPrintf(" on saute au gr sv :%d car\n",l_gr); 01218 return(0); 01219 } 01220 01221 else if((g==gr)&&(n==num)) /* on est sur l'element recherche */ 01222 /* ------------------------------ */ 01223 { 01224 /* on se repositionne sur le numero Element */ 01225 /* ATTENTION : ne marchera pas pour les Explicit VR skL !=4 ... */ 01226 /* a rectifier */ 01227 fseek(fp, -6, SEEK_CUR); 01228 01229 if(sw)numero=SWAP_SHORT(((short)numero)); /* A VOIR ... du VRAI DICOM est tjs en littleEndian */ 01230 01231 for (i=0;i<2;i++) { 01232 putc( ((char *)&numero)[i] , fp); 01233 } 01234 01235 return l; 01236 } 01237 01238 else if((g>gr)||((gr==g)&&(n>num))) /* on a depasse l'element */ 01239 { 01240 if(flag) /*on a deja re-essaye depuis le debut */ 01241 { /* l'element cherche n'y est pas */ 01242 fseek(fp,l,SEEK_CUR);/*on se positionne sur l'element sv */ 01243 return(0); /* On sort JPR */ 01244 } 01245 fseek(fp,l,SEEK_SET); 01246 flag=1; /* On va re-essayer depuis le debut */ 01247 } 01248 else { /* on saute a l'element suivant */ 01249 fseek(fp,l,SEEK_CUR); 01250 } 01251 } 01252 return(0); 01253 } 01254 01255 /* ======================================================================= 01256 _IdAcrOverWriteElement 01257 01258 Ecrase un acr_element existant par une valeur prise dans dans buff 01259 retourne la taille de l'acr_element qui a ete remplace 01260 (0 si pas trouve) 01261 01262 ATTENTION : le fichier doit avoir ete ouvert en ID_RFILE_P_BIN ... (rb+) 01263 01264 ATTENTION : Un probleme majeur risque de se poser avec les int32 et les int16 01265 (la question du swap en ecriture n'a pas ete traitee) 01266 01267 DONC : pour le moment, se limiter aux chaines de caracteres 01268 01269 ATTENTION : pour des raisons non encore elucidees, 01270 Si la lgr est superieure a celle sur disque 01271 malgre les precautions prises 01272 ca se passe MAL 01273 ======================================================================= */ 01274 01275 long _IdAcrOverWriteElement(int gr, int num, FILE *fp, void *buff) 01276 01277 { 01278 unsigned short g; 01279 unsigned short n; 01280 long l, l_gr, ptr; 01281 int flag, skL; 01282 int i; 01283 int retCode; 01284 01285 if (DEBUG) IdPrintf("_IdAcrOverWriteElement :recherche (4) gr %x num %x (swapping %d)\n",gr,num,sw); 01286 01287 l=0; 01288 flag=0; 01289 while(fread(&g,2,1,fp)) 01290 { 01291 if(sw)g=SWAP_SHORT(((short)g)); 01292 fread(&n,2,1,fp); 01293 if(sw)n=SWAP_SHORT(((short)n)); 01294 // Lecture de la longueur de l'element 01295 l = _IdAcrRecupLgr(fp, &skL); 01296 if (DEBUG) IdPrintf(" _IdAcrOverWriteElement-------------> gr %x num %x long %x : %d\n",g,n,l,l); 01297 01298 if(gr>g) /* on est plus haut que l'element cherche */ 01299 flag=1; /* si on ne le trouve pas des le premier coup */ 01300 /* c'est qu'il n'y est pas JPR */ 01301 if (0) 01302 /*if((gr>g)&&(n==0))*/ /* on est sur un debut de groupe JPR */ 01303 { 01304 fread(&l_gr,4,1,fp); 01305 if(sw)l_gr=SWAP_LONG(((long)l_gr)); /* on lit sa longueur */ 01306 fseek(fp,l_gr,SEEK_CUR); 01307 if (DEBUG) IdPrintf(" on saute au gr sv :%d car\n",l_gr); 01308 } 01309 01310 else if((g==gr)&&(n==num)) /* on est sur l'element recherche */ 01311 /* ------------------------------ */ 01312 { 01313 if (DEBUG) IdPrintf("_IdAcrOverWriteElement-------------------------on re-ecrit (%04x,%04x) lgr %d\n",g,n,l); 01314 01315 fgetpos(fp,(fpos_t *)&ptr); 01316 fsetpos(fp,(fpos_t *)&ptr); 01317 01318 for (i=0;i<l;i++) 01319 {// printf("%d %c\n", i,((char *)buff)[i]); 01320 retCode=fputc(((char *)buff)[i],fp); 01321 //printf("%d %08x\n",retCode,retCode); 01322 if(retCode == EOF) { 01323 IdPrintf("Erreur re-ecriture\n"); 01324 switch(errno) { 01325 case EAGAIN : IdPrintf("EAGAIN\n"); break; 01326 case EBADF : IdPrintf("EBADF\n"); break; 01327 case EFBIG : IdPrintf("EFBIG\n"); break; 01328 case EINTR : IdPrintf("EINTR\n"); break; 01329 case EIO : IdPrintf("EIO\n"); break; 01330 case ENOSPC : IdPrintf("ENOSPC\n"); break; 01331 case EPIPE : IdPrintf("EPIPE\n"); break; 01332 case ENOMEM : IdPrintf("ENOMEM\n"); break; 01333 case ENXIO : IdPrintf("ENXIO\n"); break; 01334 } 01335 } 01336 } 01337 01338 fgetpos(fp,(fpos_t *)&ptr); 01339 fsetpos(fp,(fpos_t *)&ptr); 01340 01341 return l; 01342 } 01343 01344 else if((g>gr)||((gr==g)&&(n>num))) /* on a depasse l'element */ 01345 { 01346 if(flag) /*on a deja re-essaye depuis le debut */ 01347 { /* l'element cherche n'y est pas */ 01348 fseek(fp,l,SEEK_CUR);/*on se positionne sur l'element sv */ 01349 return(0); /* On sort JPR */ 01350 } 01351 fseek(fp,l,SEEK_SET); 01352 flag=1; /* On va re-essayer depuis le debut */ 01353 } 01354 else { /* on saute a l'element suivant */ 01355 fseek(fp,l,SEEK_CUR); 01356 } 01357 } 01358 return(0); 01359 } 01360 01361 /* ======================================================================= 01362 _IdAcrModifElementLength 01363 01364 Recherche un acr_element et MODIFIE sa longueur 01365 01366 ATTENTION : CASSE TOUT si cet element n'est pas celui des PIXELS... 01367 01368 ATTENTION : le fichier doit avoir ete ouvert en ID_RFILE_P_BIN ... (rb+) 01369 ======================================================================= */ 01370 01371 long _IdAcrModifElementLength(int gr, int num, FILE *fp, uint32_t newLength) 01372 { 01373 unsigned short g; 01374 unsigned short n; 01375 uint32_t l, l_gr, lgrEcr; 01376 int flag,skL; 01377 01378 if (DEBUG) IdPrintf("recherche (5) gr %x num %x (swapping %d)\n",gr,num,sw); 01379 01380 l=0; 01381 flag=0; 01382 while(fread(&g,2,1,fp)) 01383 { 01384 if(sw)g=SWAP_SHORT(((short)g)); 01385 fread(&n,2,1,fp); 01386 if(sw)n=SWAP_SHORT(((short)n)); 01387 01388 // Lecture de la longueur de l'element 01389 l = _IdAcrRecupLgr(fp, &skL); 01390 01391 if (DEBUG) IdPrintf(" -------------> gr %x num %x long %x : %d\n",g,n,l,l); 01392 01393 if(gr>g) /* on est plus haut que l'element cherche */ 01394 flag=1; /* si on ne le trouve pas des le premier coup */ 01395 /* c'est qu'il n'y est pas JPR */ 01396 if((gr>g)&&(n==0)) /* on est sur un debut de groupe JPR */ 01397 { 01398 fread(&l_gr,4,1,fp); 01399 if(sw)l_gr=SWAP_LONG(((long)l_gr)); /* on lit sa longueur */ 01400 fseek(fp,l_gr,SEEK_CUR); 01401 01402 if (DEBUG) IdPrintf(" on saute au gr sv :%d car\n",l_gr); 01403 } 01404 01405 else if((g==gr)&&(n==num)) /* on est sur l'element recherche */ 01406 /* ------------------------------ */ 01407 { 01408 fseek (fp, -4, SEEK_CUR); 01409 lgrEcr = fwrite(&newLength ,4,1,fp); 01410 return(lgrEcr); 01411 } 01412 01413 else if((g>gr)||((gr==g)&&(n>num))) /* on a depasse l'element */ 01414 { 01415 if(flag) /*on a deja re-essaye depuis le debut */ 01416 { /* l'element cherche n'y est pas */ 01417 fseek(fp,l,SEEK_CUR);/*on se positionne sur l'element sv */ 01418 return(0); /* On sort JPR */ 01419 } 01420 fseek(fp,l,SEEK_SET); 01421 flag=1; /* On va re-essayer depuis le debut */ 01422 } 01423 01424 else { /* on saute a l'element suivant */ 01425 fseek(fp,l,SEEK_CUR); 01426 } 01427 } 01428 return(0); 01429 } 01430 01431 01432 /* =============================================== 01433 * 01434 * 01435 * A partir d ici, plus de probleme 01436 * 01437 * 01438 ================================================= */ 01439 01440 01441 01442 01443 01444 /* ======================================================================= 01445 _IdAcrMakeElement 01446 01447 creation d'un acr_element d'entete ACRNEMA 01448 ======================================================================= */ 01449 01450 ACR_ELEMENT *_IdAcrMakeElement(int gr, int nu, long int size, int type, long int init) 01451 01452 /* ATTENTION : init pointeur sur une chaine de char(types AN,AT) 01453 * ou valeur (types BI,BD) 01454 */ 01455 { 01456 ACR_ELEMENT *p; 01457 01458 if (DEBUG) IdPrintf("MakeElement gr %x nu %x size %d type %x init %d\n",gr,nu,size,type,init); 01459 01460 if(size & 1)size+=1; /* size doit etre paire */ 01461 01462 if((p=(ACR_ELEMENT *)calloc(1, sizeof(ACR_ELEMENT)))!=0) 01463 01464 { 01465 p->group= (short int)gr; 01466 p->number=(short int)nu; 01467 p->length=(uint32_t)size; 01468 p->type= type; 01469 p->suiv= 0; 01470 p->value= init; 01471 } 01472 else 01473 IdPrintf("PB allocation memoire 1\n"); 01474 return(p); 01475 } 01476 01477 /* ======================================================================= 01478 * _IdAcrAddElement 01479 * 01480 * insertion d'un acr_element dans la liste d'entete ACRNEMA 01481 * ======================================================================= */ 01482 01483 ACR_ELEMENT *_IdAcrAddElement(ACR_ELEMENT *liste, ACR_ELEMENT *elem) 01484 { 01485 ACR_ELEMENT *p,*pp; 01486 int flag; 01487 01488 if(!elem)return(0); 01489 01490 /*if (DEBUG) IdPrintf ("AddElement %p %p \n",liste,elem);*/ 01491 01492 flag=0; /* pas d'insertion effectuee */ 01493 01494 if (DEBUG) IdPrintf ("_IdAcrAddElement on ajoute : group : %04x elem : %04x lgr : %d ", elem->group, elem->number, elem->length); 01495 if (DEBUG) IdPrintf("\n"); 01496 01497 /* liste vide */ 01498 if(liste==0) 01499 return(elem); 01500 /* liste non vide */ 01501 p=liste; 01502 pp=0; 01503 01504 01505 01506 while( (p!=0) && (!flag)) { 01507 01508 // laiser les 4 lignes commentees 01509 //if (DEBUG) { IdPrintf ("\t\t_IdAcrAddElement on Explore : group : %04x elem : %04x lgr : %d", 01510 // p->group, p->number, p->length); 01511 // IdPrintf("\n"); 01512 //} 01513 01514 if( (p->group < elem->group) || 01515 ((p->group == elem->group) && (p->number < elem->number))) { 01516 pp=p;p=p->suiv; 01517 01518 } else { 01519 if( (p->group > elem->group) || 01520 ((p->group == elem->group) && (p->number > elem->number))) { 01521 flag=1; 01522 if(pp) { 01523 pp->suiv=elem; 01524 elem->suiv=p; 01525 } else { 01526 elem->suiv=p; 01527 liste=elem; 01528 } 01529 } else { /* element identique */ 01530 IdPrintf("ACR_ELEMENT deja present. : (%x, %x)\n",p->group,p->number); 01531 flag=1; 01532 } 01533 } 01534 } 01535 01536 if(!flag) 01537 pp->suiv=elem; 01538 01539 return(liste); 01540 } 01541 01542 01543 01544 /* ======================================================================= 01545 * _IdAcrAppendElement 01546 * 01547 * insertion d'un acr_element EN FIN d'une liste d'entete ACRNEMA 01548 * (sans elimination des doublons, sans test de la sequence croissante) 01549 * ======================================================================= */ 01550 01551 ACR_ELEMENT *_IdAcrAppendElement(ACR_ELEMENT *liste, ACR_ELEMENT *elem) 01552 { 01553 ACR_ELEMENT *p,*pp; 01554 01555 if(!elem)return(0); 01556 01557 /*if (DEBUG) IdPrintf ("_IdAcrAppendElement %p %p \n",liste,elem);*/ 01558 01559 if (DEBUG) IdPrintf ("_IdAcrAppendElement on ajoute : group : %04x elem : %04x lgr : %d ", elem->group, elem->number, elem->length); 01560 if (DEBUG) IdPrintf("\n"); 01561 01562 /* liste vide */ 01563 if(liste==0) 01564 return(elem); 01565 /* liste non vide */ 01566 p=liste; 01567 pp=0; 01568 01569 while (p!=0) { 01570 pp=p;p=p->suiv; 01571 } 01572 01573 pp->suiv=elem; 01574 01575 return(liste); 01576 } 01577 01578 01579 /* ======================================================================= 01580 * _IdAcrModifyElement 01581 * 01582 * Remplacement d'un acr_element dans la liste d'entete ACRNEMA (pour Marcela) 01583 * ======================================================================= */ 01584 01585 ACR_ELEMENT *_IdAcrModifyElement(ACR_ELEMENT *liste, ACR_ELEMENT *elem) 01586 { 01587 ACR_ELEMENT *p, *pp, *prec; 01588 int flag; 01589 01590 if(!elem)return(0); 01591 01592 if (DEBUG) IdPrintf ("_IdAcrModifyElement %p %p \n",liste,elem); 01593 01594 flag=0; /* pas d'insertion effectuee */ 01595 01596 if (DEBUG) IdPrintf ("_IdAcrModifyElement on ajoute : group : %04x elem : %04x lgr : %d ", elem->group, elem->number, elem->length); 01597 if (DEBUG) IdPrintf("\n"); 01598 01599 /* liste vide */ 01600 01601 if(liste==0) { 01602 IdPrintf("Tentative de modif d'un ACR Elem dans une ACR List vide\n"); 01603 return(NULL); 01604 } 01605 /* liste non vide */ 01606 01607 p= liste; 01608 prec=liste; 01609 pp= 0; 01610 01611 while( (p!=0) && (!flag)) 01612 { 01613 if (DEBUG) IdPrintf ("\t\t_IdAcrModifyElement on Explore : group : %04x elem : %04x lgr : %d", 01614 p->group, p->number, p->length); 01615 if (DEBUG) IdPrintf("\n"); 01616 01617 if( (p->group < elem->group) || 01618 ((p->group == elem->group) && (p->number < elem->number))) 01619 {pp=p; prec=p; p=p->suiv;} 01620 01621 else { 01622 if( (p->group > elem->group) || 01623 ((p->group == elem->group) && (p->number == elem->number))) 01624 { 01625 elem->suiv=p->suiv; 01626 prec->suiv=elem; 01627 free(p); 01628 } 01629 else { 01630 IdPrintf("ACR_ELEMENT absent. Modif Impossible : (%x, %x)\n",p->group,p->number); 01631 flag=1; 01632 } 01633 } 01634 } 01635 return(liste); 01636 } 01637 01638 01639 /* ======================================================================= 01640 * _IdAcrFreeListe 01641 * 01642 * liberation de la place utilisee par l'entete ACRNEMA 01643 * ======================================================================= */ 01644 01645 01646 ACR_ELEMENT *_IdAcrFreeListe(ACR_ELEMENT *liste) 01647 { 01648 ACR_ELEMENT *p,*pp; 01649 p=liste; 01650 while(p) 01651 { 01652 pp=p->suiv; 01653 free(p); 01654 p=pp; 01655 } 01656 return(0); 01657 } 01658 01659 /* ======================================================================= 01660 * _IdAcrMergeListes 01661 * 01662 * Interclassement de 2 listes d'ACR_ELEMENT dans une entete ACRNEMA 01663 * ======================================================================= */ 01664 01665 ACR_ELEMENT *_IdAcrMergeListes(ACR_ELEMENT *listeOriginale, ACR_ELEMENT *listeAajouter) 01666 { 01667 ACR_ELEMENT *p,*pp; 01668 p=listeAajouter; 01669 while(p) 01670 { 01671 pp=p->suiv; 01672 listeAajouter=_IdAcrAddElement(listeOriginale,p); 01673 if(listeAajouter==0) return(0); 01674 p=pp; 01675 } 01676 return(listeOriginale); 01677 } 01678 01679 /* ======================================================================= 01680 * _IdAcrFindElement 01681 * 01682 * Recherche EN MEMOIRE d'un Element de la (future) ACRNEMA 01683 * ======================================================================= */ 01684 01685 ACR_ELEMENT *_IdAcrFindElement(ACR_ELEMENT *liste, int gr, int nu) 01686 { 01687 ACR_ELEMENT *p; 01688 p=liste; 01689 while(p && ((gr != p->group) || (nu != p->number))) 01690 { 01691 p=p->suiv; 01692 } 01693 return(p); 01694 } 01695 01696 /* ======================================================================= 01697 * _IdAcrAdjustLength 01698 * 01699 * Aligne la taille de al liste d'ACR_ELEMENT 01700 * sur unr frontiere DICOM compatible 01701 * ======================================================================= */ 01702 01703 void _IdAcrAdjustLength(ACR_ELEMENT *liste) 01704 { 01705 ACR_ELEMENT *p; 01706 long g; 01707 int s; 01708 long s_tot; 01709 s=0; 01710 s_tot=0; 01711 g = -1; /*BB 18-JUN-1992 08:53:54 : g=-1;*/ 01712 p=liste; 01713 while(p) 01714 { 01715 if(g != p->group) 01716 { 01717 if(g != -1) 01718 { 01719 (_IdAcrFindElement(liste,g,0))->value=s; 01720 s_tot+=s+12; 01721 s=0; 01722 } 01723 g=p->group; 01724 } 01725 else 01726 { 01727 if(p->number) s += p->length + 8; 01728 } 01729 p=p->suiv; 01730 } 01731 01732 (_IdAcrFindElement(liste,g,0))->value=s; 01733 s_tot+=s+12; 01734 (_IdAcrFindElement(liste,8,1))->value=s_tot-24; 01735 } 01736 01737 /* ======================================================================= 01738 * _IdAcrAffListe (pour liste creee par LibIDO) 01739 * ======================================================================= */ 01740 01741 void _IdAcrAffListe(ACR_ELEMENT *liste) 01742 { 01743 ACR_ELEMENT *p; 01744 p=liste; 01745 while(p) 01746 { 01747 IdPrintf(" %04x\t%04x long.=%d \tvaleur ", 01748 p->group,p->number,p->length); 01749 switch(p->type) 01750 { 01751 case BI:IdPrintf("%d\n", p->value); break; 01752 case BD:IdPrintf("%d\n", p->value); break; 01753 case AN:IdPrintf("[%s]\n",(char *)p->value); break; 01754 case AT:IdPrintf("[%s]\n",(char *)p->value); break; 01755 case NO:IdPrintf("%x\n", p->value); break; 01756 } 01757 p=p->suiv; 01758 } 01759 } 01760 01761 /* ======================================================================= 01762 * _IdAcrAffListeBref (pour Liste cree par _IdAcrInquireHeader) 01763 * ======================================================================= */ 01764 01765 void _IdAcrAffListeBref(ACR_ELEMENT *liste) 01766 { 01767 ACR_ELEMENT *p; 01768 p=liste; 01769 while(p) 01770 { 01771 IdPrintf(" %04x\t%04x long.=%d \tvaleur ", 01772 p->group,p->number,p->length); 01773 switch(p->type) 01774 { 01775 case BI:IdPrintf("%d [%8x]\n", *(short int *)(p->value), *(short int *)(p->value)); break; 01776 case BD:IdPrintf("%d [%8x]\n", *(uint32_t *)(p->value), *(uint32_t *)(p->value)); break; 01777 case AN:IdPrintf("[%s]\n",(char *)p->value); break; 01778 case AT:IdPrintf("[%s]\n",(char *)p->value); break; 01779 case NO:IdPrintf("%8x\n", p->value); break; 01780 default:IdPrintf(" ?? %d [%8x]\n", p->value, p->value); break; 01781 } 01782 p=p->suiv; 01783 } 01784 } 01785 01786 /* ======================================================================= 01787 * _IdAcrAffListe2 (Reserve a l'affichage du resultat de IdAcrInquireHeader) 01788 * ======================================================================= */ 01789 01790 void _IdAcrAffListe2(ACR_ELEMENT * liste, int npriv, int noffset) 01791 { 01792 ACR_ELEMENT *p; 01793 DICOM_ELEMENTS *t = NULL; 01794 long _offset =0; 01795 01796 01797 _offset = __ID_offset + 2 + 2 + 4; 01798 01799 01800 p=liste; 01801 01802 IdPrintf("\n\n\t\tATTENTION : Les chaines de caracteres de longueur 2 ou 4 \n" 01803 "\t(des groupes de num IMPAIR) peuvent avoir ete 'swappees'\n\n"); 01804 01805 while(p) { 01806 // if (DEBUG)IdPrintf(" ?? gr %04x num %04x long %d\n", p->group, p->number, p->length); 01807 01808 if (p->number==0) { 01809 if(!npriv) IdPrintf("\n"); 01810 } else { 01811 for (t=_ID_dicom_elements; t->dicom_group!=0xffff; t++) { 01812 if( (t->dicom_group==p->group) && (t->dicom_elem==p->number) ) break; 01813 } 01814 } 01815 01816 if(!(p->group%2) || !npriv) { 01817 01818 if (noffset) 01819 IdPrintf(" gr %04x num %04x long %d", 01820 p->group, p->number, p->length); 01821 else 01822 01823 IdPrintf(" gr %04x num %04x long %d _offset %d", 01824 p->group, p->number, p->length, _offset); 01825 } 01826 01827 _offset += 2 +2 + p->skippedLength + p->length; 01828 01829 if (p->number!=0) { 01830 if(!(p->group%2) || !npriv) IdPrintf("\t%s\t%s\t\t", 01831 t->dicom_type, t->dicom_libelle); 01832 } 01833 01834 if (p->number==0) { 01835 if(!(p->group%2) || !npriv) IdPrintf(" lgr du grp = %d\n -------\n", 01836 *(long *)(p->value)); 01837 } 01838 01839 01840 /* MANQUE le retrait, avant impression en %s, des caract non ASCII */ 01841 01842 else if (p->length==2) { 01843 if ( (strcmp(t->dicom_type, "US") == 0) 01844 || (strcmp(t->dicom_type, "SS") == 0) 01845 || (t->dicom_group == 0x0028 && 01846 (t->dicom_elem == 0x0005 || t->dicom_elem == 0x0200) ) ) { 01847 01848 if(!(p->group%2) || !npriv) { 01849 IdPrintf("\t \t \t %d \tx(%04x)\n", 01850 *(short int *)(p->value) , *(short int *)p->value); 01851 } 01852 } 01853 else 01854 01855 if(!(p->group%2) || !npriv){ IdPrintf("\t[%s] \t %d \tx(%04x)\n", 01856 (char*)p->value,*(short int *)p->value, *(short int *)p->value);} 01857 01858 } 01859 01860 else if (p->length==4) { 01861 if ( (strcmp(t->dicom_type,"UL") == 0) 01862 || (strcmp(t->dicom_type,"SL") == 0) ) { 01863 if(!(p->group%2) || !npriv) { 01864 IdPrintf("\t \t \t %d \tx(%08x)\n", 01865 (int *)p->value, *(short int *)p->value); 01866 } 01867 } else { 01868 if(!(p->group%2) || !npriv) { 01869 IdPrintf("\t[%s] \t %d \tx(%08x)\n", 01870 (char*)p->value,*(long *)p->value, *(long *)p->value); 01871 } 01872 } 01873 01874 } 01875 01876 else { 01877 if (p->length > 5000) { 01878 if(!(p->group%2) || !npriv) 01879 IdPrintf(" --> Too Long. Not Printed...\n"); 01880 } else { 01881 if(!(p->group%2) || !npriv) IdPrintf(" \t[%s]\n",p->value); 01882 } 01883 } 01884 p=p->suiv; 01885 } 01886 } 01887 01888 01889 01890 /* ======================================================================= 01891 _IdAcrAddHisto 01892 ======================================================================= */ 01893 01894 int 01895 _IdAcrAddHisto(char *l) 01896 { 01897 FILE *fphisto; 01898 01899 if((fphisto=fopen("_t_histo.tmp","a"))!=0) 01900 { 01901 fseek(fphisto,0L,SEEK_END); 01902 fwrite(l,strlen(l),1,fphisto); 01903 fclose(fphisto); 01904 } 01905 return 0; 01906 } 01907

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