5 static void _Swap(void* im, int swap, int lgr, int nb);
7 /////////////////////////////////////////////////////////////////
10 * \brief Constructor dedicated to writing a new DICOMV3 part10 compliant
11 * file (see SetFileName, SetDcmTag and Write)
12 * Opens (in read only and when possible) an existing file and checks
13 * for DICOM compliance. Returns NULL on failure.
14 * \Note the in-memory representation of all available tags found in
15 * the DICOM header is post-poned to first header information access.
16 * This avoid a double parsing of public part of the header when
17 * one sets an a posteriori shadow dictionary (efficiency can be
18 * seen as a side effect).
20 * @param filename file to be opened for parsing
25 gdcmFile::gdcmFile(string & filename)
26 :gdcmHeader(filename.c_str())
30 gdcmFile::gdcmFile(const char * filename)
36 /////////////////////////////////////////////////////////////////
39 * \brief Renvoie la longueur A ALLOUER pour recevoir les pixels de l'image
40 * ou DES images dans le cas d'un multiframe
41 * ATTENTION : il ne s'agit PAS de la longueur du groupe des Pixels
42 * (dans le cas d'images compressees, elle n'a pas de sens).
44 * @return longueur a allouer
47 size_t gdcmFile::GetImageDataSize(void) {
51 str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
52 if (str_nb == "gdcm::Unfound" ) {
55 nb = atoi(str_nb.c_str() );
59 size_t lgrTotale = GetXSize() * GetYSize() * GetZSize() *(nb/8);
65 /////////////////////////////////////////////////////////////////
72 void * gdcmFile::GetImageData (void) {
74 // Longueur en Octets des Pixels a lire
75 size_t taille = GetImageDataSize();// ne faudrait-il pas la stocker?
76 _Pixels = (char *) malloc(taille);
77 GetImageDataIntoVector(_Pixels, taille);
79 // On l'affecte à un champ du dcmFile
83 // ca fait double emploi, il faudra nettoyer ça
90 /////////////////////////////////////////////////////////////////
93 * \brief amene en mémoire dans une zone précisee par l'utilisateur
94 * les Pixels d'une image NON COMPRESSEE
95 * \Warning Aucun test n'est fait pour le moment sur le caractere compresse ou non de l'image
103 int gdcmFile::GetImageDataIntoVector (void* destination, size_t MaxSize) {
106 // dans quel cas la MaxSize sert-elle a quelque chose?
107 // que fait-on si la taille de l'image est + gde que Maxize?
108 // que fait-on si la taille de l'image est + petite que Maxize?
111 void * Pixels = destination; // pour garder le code identique avec GetImageData
113 int nb, nbu, highBit, signe;
114 string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe;
116 unsigned short int mask = 0xffff;
118 // Longueur en Octets des Pixels a lire
119 size_t _lgrTotale = GetImageDataSize(); // ne faudrait-il pas la stocker?
121 // si lgrTotale < MaxSize ==> Gros pb
122 // -> on résoud à la goret
124 if ( _lgrTotale < MaxSize ) MaxSize = _lgrTotale;
126 GetPixels(MaxSize, destination);
128 // Nombre de Bits Alloues pour le stockage d'un Pixel
129 str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
131 if (str_nb == "gdcm::Unfound" ) {
134 nb = atoi(str_nb.c_str() );
137 // Nombre de Bits Utilises
138 str_nbu=GetPubElValByNumber(0x0028,0x0101);
140 if (str_nbu == "gdcm::Unfound" ) {
143 nbu = atoi(str_nbu.c_str() );
146 // Position du Bit de Poids Fort
147 str_highBit=GetPubElValByNumber(0x0028,0x0102);
149 if (str_highBit == "gdcm::Unfound" ) {
152 highBit = atoi(str_highBit.c_str() );
156 str_signe=GetPubElValByNumber(0x0028,0x0103);
158 if (str_signe == "gdcm::Unfound" ) {
161 signe = atoi(str_signe.c_str() );
164 // On remet les Octets dans le bon ordre si besoin est
166 int _sw = GetSwapCode();
168 _Swap (destination, _sw, _lgrTotale, nb);
171 // On remet les Bits des Octets dans le bon ordre si besoin est
173 // ATTENTION : Jamais confronté a des pixels stockes sur 32 bits
174 // avec moins de 32 bits utilises
175 // et dont le bit de poids fort ne serait pas la ou on l'attend ...
176 // --> ne marchera pas dans ce cas
178 mask = mask >> (nb-nbu);
179 int l=(int)MaxSize/(nb/8);
180 unsigned short *deb = (unsigned short *)Pixels;
181 for(int i=0;i<l;i++) {
182 *deb = (*deb >> (nbu-highBit-1)) & mask;
187 // VOIR s'il ne faudrait pas l'affecter à un champ du dcmHeader
194 // Je laisse le code integral, au cas ça puisse etre reutilise ailleurs
197 static void _Swap(void* im, int swap, int lgr, int nb) {
216 ((unsigned short int*)im)[i]= ((((unsigned short int*)im)[i])>>8)
217 | ((((unsigned short int*)im)[i])<<8);
221 printf("valeur de SWAP (16 bits) non autorisee : %d\n", swap);
233 faible= ((unsigned long int*)im)[i]&0x0000ffff; /* 4321 */
234 fort =((unsigned long int*)im)[i]>>16;
235 fort= (fort>>8) | (fort<<8);
236 faible=(faible>>8) | (faible<<8);
238 ((unsigned long int*)im)[i]=(s32<<16)|fort;
244 faible= ((unsigned long int*)im)[i]&0x0000ffff; /* 2143 */
245 fort=((unsigned long int*)im)[i]>>16;
246 fort= (fort>>8) | (fort<<8);
247 faible=(faible>>8) | (faible<<8);
249 ((unsigned long int*)im)[i]=(s32<<16)|faible;
255 faible= ((unsigned long int*)im)[i]&0x0000ffff; /* 3412 */
256 fort=((unsigned long int*)im)[i]>>16;
258 ((unsigned long int*)im)[i]=(s32<<16)|fort;
263 printf("valeur de SWAP (32 bits) non autorisee : %d\n", swap);
268 /////////////////////////////////////////////////////////////////
272 * \warning doit-etre etre publique ? FIXME JPR
274 * @param Data TODO JPR
275 * @param ExpectedSize TODO JPR
279 int gdcmFile::SetImageData(void * Data, size_t ExpectedSize) {
281 SetImageDataSize(ExpectedSize);
284 lgrTotale = ExpectedSize;
290 /////////////////////////////////////////////////////////////////
295 * \warning WARNING doit-etre etre publique ? FIXME JPR
297 * @param ImageDataSize TODO JPR
301 void gdcmFile::SetImageDataSize(size_t ImageDataSize) {
307 // suppose que le ElValue (0x7fe0, 0x0010) existe ...
309 sprintf(car,"%d",ImageDataSize);
311 SetPubElValByNumber(content2, 0x7fe0, 0x0010);
314 sprintf(car,"%d",ImageDataSize);
316 SetPubElValByNumber(content1, 0x7fe0, 0x0000);
320 /////////////////////////////////////////////////////////////////
323 * \brief Ecrit sur disque les pixels d'UNE image
324 * Aucun test n'est fait sur l'"Endiannerie" du processeur.
325 * Ca sera à l'utilisateur d'appeler son Reader correctement
326 * (Equivalent a IdImaWriteRawFile) FIXME JPR
328 * @param nomFichier TODO JPR
333 int gdcmFile::WriteRawData (string nomFichier) {
336 fp1 = fopen(nomFichier.c_str(),"wb");
338 printf("Echec ouverture (ecriture) Fichier [%s] \n",nomFichier.c_str());
342 fwrite (Pixels,lgrTotale, 1, fp1);
349 /////////////////////////////////////////////////////////////////
352 * \brief Ecrit sur disque UNE image Dicom
353 * Aucun test n'est fait sur l'"Endiannerie" du processeur.
354 * Ca fonctionnera correctement (?) sur processeur Intel
355 * (Equivalent a IdDcmWrite) FIXME JPR
357 * @param nomFichier TODO JPR
362 int gdcmFile::WriteDcmImplVR (string nomFichier) {
363 return WriteBase(nomFichier, ImplicitVR);
366 int gdcmFile::WriteDcmImplVR (const char* nomFichier) {
367 return WriteDcmImplVR (string (nomFichier));
370 /////////////////////////////////////////////////////////////////
374 * @param nomFichier TODO JPR
379 int gdcmFile::WriteDcmExplVR (string nomFichier) {
380 return WriteBase(nomFichier, ExplicitVR);
383 /////////////////////////////////////////////////////////////////
386 * \brief Ecrit sur disque UNE image ACR-NEMA
387 * (a l'attention des logiciels cliniques
388 * qui ne prennent en entrée QUE des images ACR ...
389 * si un header DICOM est fourni en entree,
390 * les groupes < 0x0008 et les groupes impairs sont ignores)
391 * Aucun test n'est fait sur l'"Endiannerie" du processeur.
392 * Ca fonctionnera correctement (?) sur processeur Intel
393 * (Equivalent a IdDcmWrite)
395 * @param nomFichier TODO JPR
400 int gdcmFile::WriteAcr (string nomFichier) {
401 return WriteBase(nomFichier, ACR);
404 int gdcmFile::WriteBase (string nomFichier, FileType type) {
407 fp1 = fopen(nomFichier.c_str(),"wb");
409 printf("Echec ouverture (ecriture) Fichier [%s] \n",nomFichier.c_str());
413 if ( (type == ImplicitVR) || (type == ExplicitVR) ) {
415 // Ecriture Dicom File Preamble
416 filePreamble=(char*)calloc(128,1);
417 fwrite(filePreamble,128,1,fp1);
418 fwrite("DICM",4,1,fp1);
421 gdcmHeader::Write(fp1, type);
422 fwrite(Pixels, lgrTotale, 1, fp1);