]> Creatis software - gdcm.git/blob - src/gdcmDocEntrySet.cxx
Strange name gdcm::SerieHeader turned to gdcm::SerieHelper
[gdcm.git] / src / gdcmDocEntrySet.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDocEntrySet.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/02/02 10:02:17 $
7   Version:   $Revision: 1.51 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 #include "gdcmDocEntrySet.h"
19
20 #include "gdcmDebug.h"
21 #include "gdcmCommon.h"
22 #include "gdcmDictSet.h"
23 #include "gdcmGlobal.h"
24 #include "gdcmDocEntry.h"
25 #include "gdcmSeqEntry.h"
26 #include "gdcmValEntry.h"
27 #include "gdcmBinEntry.h"
28
29 namespace gdcm 
30 {
31 //-----------------------------------------------------------------------------
32 // Constructor / Destructor
33
34 //-----------------------------------------------------------------------------
35 // Public
36 /**
37  * \brief   Get the "std::string representable" value of the Dicom entry
38  * @param   group  Group number of the searched tag.
39  * @param   elem Element number of the searched tag.
40  * @return  Corresponding element value when it exists,
41  *          and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
42  */
43 std::string DocEntrySet::GetEntryValue(uint16_t group, uint16_t elem)
44 {
45    ContentEntry *entry = dynamic_cast<ContentEntry *>(GetDocEntry(group,elem));
46    if( entry )
47       return entry->GetValue();
48    return GDCM_UNFOUND;
49 }
50
51 /**
52  * \brief   Gets (from Header) a 'non string' element value 
53  * @param group   group number of the Entry 
54  * @param elem  element number of the Entry
55  * @return Pointer to the 'non string' area
56  */
57 void *DocEntrySet::GetEntryBinArea(uint16_t group, uint16_t elem) 
58 {
59    BinEntry *entry = GetBinEntry(group, elem);
60    if( entry )
61       return entry->GetBinArea();
62    return 0;
63 }
64
65 /**
66  * \brief   Searches within Header Entries (Dicom Elements) parsed with 
67  *          the public and private dictionaries 
68  *          for the value length of a given tag..
69  * @param   group  Group number of the searched tag.
70  * @param   elem Element number of the searched tag.
71  * @return  Corresponding element length; -2 if not found
72  */
73 int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
74 {
75    DocEntry *entry = GetDocEntry(group, elem);
76    if( entry )
77       return entry->GetLength();
78    return -1;
79 }
80
81 /**
82  * \brief   Searches within Header Entries (Dicom Elements) parsed with 
83  *          the public [and private dictionaries] 
84  *          for the element value representation of a given tag..
85  *          Obtaining the VR (Value Representation) might be needed by caller
86  *          to convert the string typed content to caller's native type 
87  *          (think of C++ vs Python). The VR is actually of a higher level
88  *          of semantics than just the native C++ type.
89  * @param   group  Group number of the searched tag.
90  * @param   elem Element number of the searched tag.
91  * @return  Corresponding element value representation when it exists,
92  *          and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
93  */
94 std::string DocEntrySet::GetEntryVR(uint16_t group, uint16_t elem)
95 {
96    DocEntry *entry = GetDocEntry(group, elem);
97    if( entry )
98       return entry->GetVR();
99    return GDCM_UNFOUND;
100 }
101
102 /**
103  * \brief  Same as \ref Document::GetDocEntry except it only
104  *         returns a result when the corresponding entry is of type
105  *         ValEntry.
106  * @param   group  Group number of the searched Dicom Element 
107  * @param   elem Element number of the searched Dicom Element  
108  * @return When present, the corresponding ValEntry. 
109  */
110 ValEntry *DocEntrySet::GetValEntry(uint16_t group, uint16_t elem)
111 {
112    DocEntry *currentEntry = GetDocEntry(group, elem);
113    if ( !currentEntry )
114       return NULL;
115
116    return dynamic_cast<ValEntry*>(currentEntry);
117 }
118
119 /**
120  * \brief  Same as \ref Document::GetDocEntry except it only
121  *         returns a result when the corresponding entry is of type
122  *         BinEntry.
123  * @param   group  Group number of the searched Dicom Element
124  * @param   elem Element number of the searched Dicom Element
125  * @return When present, the corresponding BinEntry. 
126  */
127 BinEntry *DocEntrySet::GetBinEntry(uint16_t group, uint16_t elem)
128 {
129    DocEntry *currentEntry = GetDocEntry(group, elem);
130    if ( !currentEntry )
131    {
132       gdcmVerboseMacro( "No corresponding BinEntry " << std::hex << group <<
133                          "," << elem);
134       return NULL;
135    }
136
137    return dynamic_cast<BinEntry*>(currentEntry);
138 }
139
140 /**
141  * \brief  Same as \ref Document::GetDocEntry except it only
142  *         returns a result when the corresponding entry is of type
143  *         SeqEntry.
144  * @param   group  Group number of the searched Dicom Element 
145  * @param   elem Element number of the searched Dicom Element  
146  * @return When present, the corresponding SeqEntry. 
147  */
148 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
149 {
150    DocEntry *currentEntry = GetDocEntry(group, elem);
151    if ( !currentEntry )
152    {
153       gdcmVerboseMacro( "No corresponding SeqEntry " << std::hex << group <<
154                         "," << elem);
155       return NULL;
156    }
157
158    return dynamic_cast<SeqEntry*>(currentEntry);
159 }
160
161 /**
162  * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
163  *          through it's (group, element) and modifies it's content with
164  *          the given value.
165  * @param   content new value (string) to substitute with
166  * @param   group  group number of the Dicom Element to modify
167  * @param   elem element number of the Dicom Element to modify
168  */
169 bool DocEntrySet::SetValEntry(std::string const &content, 
170                               uint16_t group, uint16_t elem) 
171 {
172    ValEntry *entry = GetValEntry(group, elem);
173    if (!entry )
174    {
175       gdcmVerboseMacro( "No corresponding ValEntry " << std::hex << group <<
176                          "," << elem << " element (try promotion first).");
177       return false;
178    }
179    return SetValEntry(content,entry);
180 }
181
182 /**
183  * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
184  *          through it's (group, element) and modifies it's content with
185  *          the given value.
186  * @param   content new value (void*  -> uint8_t*) to substitute with
187  * @param   lgth new value length
188  * @param   group  group number of the Dicom Element to modify
189  * @param   elem element number of the Dicom Element to modify
190  */
191 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth, 
192                               uint16_t group, uint16_t elem) 
193 {
194    BinEntry *entry = GetBinEntry(group, elem);
195    if (!entry )
196    {
197       gdcmVerboseMacro( "No corresponding ValEntry " << std::hex << group <<
198                         "," << elem << " element (try promotion first).");
199       return false;
200    }
201
202    return SetBinEntry(content,lgth,entry);
203
204
205 /**
206  * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
207  *          and modifies it's content with the given value.
208  * @param  content new value (string) to substitute with
209  * @param  entry Entry to be modified
210  */
211 bool DocEntrySet::SetValEntry(std::string const &content, ValEntry *entry)
212 {
213    if(entry)
214    {
215       entry->SetValue(content);
216       return true;
217    }
218    return false;
219 }
220
221 /**
222  * \brief   Accesses an existing BinEntry (i.e. a Dicom Element)
223  *          and modifies it's content with the given value.
224  * @param   content new value (void*  -> uint8_t*) to substitute with
225  * @param  entry Entry to be modified 
226  * @param  lgth new value length
227  */
228 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth, BinEntry *entry)
229 {
230    if(entry)
231    {
232       entry->SetBinArea(content);  
233       entry->SetLength(lgth);
234       entry->SetValue(GDCM_BINLOADED);
235       return true;
236    }
237    return false;
238 }
239
240 /**
241  * \brief   Modifies the value of a given Doc Entry (Dicom Element)
242  *          when it exists. Create it with the given value when unexistant.
243  * @param   value (string) Value to be set
244  * @param   group   Group number of the Entry 
245  * @param   elem  Element number of the Entry
246  * @param   vr  V(alue) R(epresentation) of the Entry -if private Entry-
247  * \return  pointer to the modified/created Header Entry (NULL when creation
248  *          failed).
249  */ 
250 ValEntry *DocEntrySet::InsertValEntry(std::string const &value, 
251                                       uint16_t group, uint16_t elem,
252                                       TagName const &vr )
253 {
254    ValEntry *valEntry = 0;
255    DocEntry *currentEntry = GetDocEntry( group, elem);
256    
257    if (currentEntry)
258    {
259       valEntry = dynamic_cast<ValEntry *>(currentEntry);
260
261       // Verify the VR
262       if( valEntry )
263          if( valEntry->GetVR()!=vr )
264             valEntry = NULL;
265
266       // if currentEntry doesn't correspond to the requested valEntry
267       if( !valEntry)
268       {
269          if( !RemoveEntry(currentEntry) )
270          {
271             gdcmVerboseMacro( "Removal of previous DocEntry failed.");
272
273             return NULL;
274          }
275       }
276    }
277
278    // Create a new valEntry if necessary
279    if( !valEntry )
280    {
281       valEntry = NewValEntry(group, elem, vr);
282
283       if ( !AddEntry(valEntry) )
284       {
285          gdcmVerboseMacro("AddEntry failed although this is a creation.");
286
287          delete valEntry;
288          return NULL;
289       }
290    }
291
292    // Set the binEntry value
293    SetValEntry(value, valEntry); // The std::string value
294    return valEntry;
295 }
296
297 /*
298  * \brief   Modifies the value of a given Header Entry (Dicom Element)
299  *          when it exists. Create it with the given value when unexistant.
300  *          A copy of the binArea is made to be kept in the Document.
301  * @param   binArea (binary) value to be set
302  * @param   group   Group number of the Entry 
303  * @param   elem  Element number of the Entry
304  * @param   vr  V(alue) R(epresentation) of the Entry -if private Entry-
305  * \return  pointer to the modified/created Header Entry (NULL when creation
306  *          failed).
307  */
308 BinEntry *DocEntrySet::InsertBinEntry(uint8_t *binArea, int lgth, 
309                                       uint16_t group, uint16_t elem,
310                                       TagName const &vr )
311 {
312    BinEntry *binEntry = 0;
313    DocEntry *currentEntry = GetDocEntry( group, elem);
314
315    // Verify the currentEntry
316    if (currentEntry)
317    {
318       binEntry = dynamic_cast<BinEntry *>(currentEntry);
319
320       // Verify the VR
321       if( binEntry )
322          if( binEntry->GetVR()!=vr )
323             binEntry = NULL;
324
325       // if currentEntry doesn't correspond to the requested valEntry
326       if( !binEntry)
327       {
328          if( !RemoveEntry(currentEntry) )
329          {
330             gdcmVerboseMacro( "Removal of previous DocEntry failed.");
331
332             return NULL;
333          }
334       }
335    }
336
337    // Create a new binEntry if necessary
338    if( !binEntry)
339    {
340       binEntry = NewBinEntry(group, elem, vr);
341
342       if ( !AddEntry(binEntry) )
343       {
344          gdcmVerboseMacro( "AddEntry failed allthough this is a creation.");
345
346          delete binEntry;
347          return NULL;
348       }
349    }
350
351    // Set the binEntry value
352    uint8_t *tmpArea;
353    if( lgth>0 && binArea )
354    {
355       tmpArea = new uint8_t[lgth];
356       memcpy(tmpArea,binArea,lgth);
357    }
358    else
359    {
360       tmpArea = 0;
361    }
362    if( !SetBinEntry(tmpArea,lgth,binEntry) )
363    {
364       if( tmpArea )
365       {
366          delete[] tmpArea;
367       }
368    }
369
370    return binEntry;
371 }  
372
373 /*
374  * \brief   Modifies the value of a given Header Entry (Dicom Element)
375  *          when it exists. Creates it when unexistant.
376  * @param   group   Group number of the Entry 
377  * @param   elem  Element number of the Entry
378  * \return  pointer to the modified/created SeqEntry (NULL when creation
379  *          failed).
380  */
381 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
382 {
383    SeqEntry *seqEntry = 0;
384    DocEntry *currentEntry = GetDocEntry( group, elem);
385
386    // Verify the currentEntry
387    if( currentEntry )
388    {
389       seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
390
391       // Verify the VR
392       if( seqEntry )
393          if( seqEntry->GetVR()!="SQ" )
394             seqEntry = NULL;
395
396       // if currentEntry doesn't correspond to the requested valEntry
397       if( !seqEntry )
398       {
399          if (!RemoveEntry(currentEntry))
400          {
401             gdcmVerboseMacro( "Removal of previous DocEntry failed.");
402
403             return NULL;
404          }
405       }
406    }
407    // Create a new seqEntry if necessary
408    if( !seqEntry )
409    {
410       seqEntry = NewSeqEntry(group, elem);
411
412       if( !AddEntry(seqEntry) )
413       {
414          gdcmVerboseMacro( "AddEntry failed allthough this is a creation.");
415
416          delete seqEntry;
417          return NULL;
418       }
419    }
420    return seqEntry;
421
422  
423 /**
424  * \brief   Checks if a given Dicom Element exists within the H table
425  * @param   group   Group number of the searched Dicom Element 
426  * @param   elem  Element number of the searched Dicom Element 
427  * @return true is found
428  */
429 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
430 {
431    return GetDocEntry(group,elem)!=NULL;
432 }
433
434 /**
435  * \brief   Request a new virtual dict entry to the dict set
436  * @param   group group  number of the underlying DictEntry
437  * @param   elem  element number of the underlying DictEntry
438  * @param   vr    VR (Value Representation) of the underlying DictEntry
439  * @param   vm    VM (Value Multiplicity)   of the underlying DictEntry
440  * @param   name   english name
441  */
442 DictEntry* DocEntrySet::NewVirtualDictEntry( uint16_t group,uint16_t elem,
443                                              TagName const & vr,
444                                              TagName const & vm,
445                                              TagName const & name )
446 {
447    return Global::GetDicts()->NewVirtualDictEntry(group,elem,vr,vm,name);
448 }
449
450 /**
451  * \brief   Build a new Val Entry from all the low level arguments. 
452  *          Check for existence of dictionary entry, and build
453  *          a default one when absent.
454  * @param   group group   number of the new Entry
455  * @param   elem  element number of the new Entry
456  * @param   vr     VR of the new Entry 
457  */
458 ValEntry *DocEntrySet::NewValEntry(uint16_t group,uint16_t elem,
459                                    TagName const & vr) 
460 {
461    DictEntry *dictEntry = GetDictEntry(group, elem, vr);
462    gdcmAssertMacro(dictEntry);
463
464    ValEntry *newEntry = new ValEntry(dictEntry);
465    if (!newEntry) 
466    {
467       gdcmVerboseMacro( "Failed to allocate ValEntry");
468       return 0;
469    }
470    return newEntry;
471 }
472
473
474 /**
475  * \brief   Build a new Bin Entry from all the low level arguments. 
476  *          Check for existence of dictionary entry, and build
477  *          a default one when absent.
478  * @param   group group   number of the new Entry
479  * @param   elem  element number of the new Entry
480  * @param   vr     VR of the new Entry 
481  */
482 BinEntry *DocEntrySet::NewBinEntry(uint16_t group, uint16_t elem,
483                                    TagName const &vr) 
484 {
485    DictEntry *dictEntry = GetDictEntry(group, elem, vr);
486    gdcmAssertMacro(dictEntry);
487
488    BinEntry *newEntry = new BinEntry(dictEntry);
489    if (!newEntry) 
490    {
491       gdcmVerboseMacro( "Failed to allocate BinEntry");
492       return 0;
493    }
494    return newEntry;
495 }
496
497 /**
498  * \brief   Build a new Seq Entry from all the low level arguments. 
499  *          Check for existence of dictionary entry, and build
500  *          a default one when absent.
501  * @param   group group   number of the new Entry
502  * @param   elem  element number of the new Entry
503  */
504 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem) 
505 {
506    DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
507    gdcmAssertMacro(dictEntry);
508
509    SeqEntry *newEntry = new SeqEntry( dictEntry );
510    if (!newEntry)
511    {
512       gdcmVerboseMacro( "Failed to allocate SeqEntry");
513       return 0;
514    }
515    return newEntry;
516 }
517
518 //-----------------------------------------------------------------------------
519 // Protected
520 /**
521  * \brief   Searches [both] the public [and the shadow dictionary (when they
522  *          exist)] for the presence of the DictEntry with given
523  *          group and element. The public dictionary has precedence on the
524  *          shadow one.
525  * @param   group  group number of the searched DictEntry
526  * @param   elem element number of the searched DictEntry
527  * @return  Corresponding DictEntry when it exists, NULL otherwise.
528  */
529 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem) 
530 {
531    DictEntry *found = 0;
532    Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
533    if (!pubDict) 
534    {
535       gdcmVerboseMacro( "We SHOULD have a default dictionary");
536    }
537    else
538    {
539       found = pubDict->GetEntry(group, elem);  
540    }
541    return found;
542 }
543
544 /**
545  * \brief   Searches [both] the public [and the shadow dictionary (when they
546  *          exist)] for the presence of the DictEntry with given
547  *          group and element, and create a new virtual DictEntry if necessary
548  * @param   group  group number of the searched DictEntry
549  * @param   elem element number of the searched DictEntry
550  * @param   vr Value Representation to use, if necessary 
551  * @return  Corresponding DictEntry when it exists, NULL otherwise.
552  */
553 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
554                                      TagName const &vr)
555 {
556    DictEntry *dictEntry = GetDictEntry(group,elem);
557    DictEntry *goodEntry = dictEntry;
558    std::string goodVR = vr;
559
560    if (elem == 0x0000) goodVR="UL";
561
562    if ( goodEntry )
563    {
564       if ( goodVR != goodEntry->GetVR()
565         && goodVR != GDCM_UNKNOWN )
566       {
567          goodEntry = NULL;
568       }
569    }
570
571    // Create a new virtual DictEntry if necessary
572    if (!goodEntry)
573    {
574       if (dictEntry)
575       {
576          goodEntry = NewVirtualDictEntry(group, elem, goodVR, "FIXME", 
577                                          dictEntry->GetName() );
578       }
579       else
580       {
581          goodEntry = NewVirtualDictEntry(group, elem, goodVR);
582       }
583    }
584    return goodEntry;
585 }
586
587 //-----------------------------------------------------------------------------
588 // Private
589
590 //-----------------------------------------------------------------------------
591 // Print
592
593 //-----------------------------------------------------------------------------
594 } // end namespace gdcm