1 /*=========================================================================
4 Module: $RCSfile: gdcmDict.cxx,v $
6 Date: $Date: 2004/07/02 13:55:27 $
7 Version: $Revision: 1.38 $
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.htm for details.
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.
17 =========================================================================*/
21 #include "gdcmDebug.h"
27 //-----------------------------------------------------------------------------
28 // Constructor / Destructor
31 * @param FileName from which to build the dictionary.
33 gdcmDict::gdcmDict(std::string & FileName) {
41 std::ifstream from(FileName.c_str());
42 dbg.Error(!from, "gdcmDict::gdcmDict: can't open dictionary",
47 from >> group; /// MEMORY LEAK in std::istream::operator>>
52 getline(from, name); /// MEMORY LEAK in std::getline<>
54 gdcmDictEntry * newEntry = new gdcmDictEntry(group, element,
56 AddNewEntry(newEntry);
66 gdcmDict::~gdcmDict() {
67 for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
69 gdcmDictEntry* EntryToDelete = tag->second;
73 // Since AddNewEntry adds symetrical in both KeyHt and NameHT we can
74 // assume all the pointed gdcmDictEntries are already cleaned-up when
80 //-----------------------------------------------------------------------------
83 * \brief Print all the dictionary entries contained in this dictionary.
84 * Entries will be sorted by tag i.e. the couple (group, element).
85 * @param os The output stream to be written to.
87 void gdcmDict::Print(std::ostream &os) {
88 os<<"Dict file name : "<<filename<<std::endl;
93 * \brief Print all the dictionary entries contained in this dictionary.
94 * Entries will be sorted by tag i.e. the couple (group, element).
95 * @param os The output stream to be written to.
97 void gdcmDict::PrintByKey(std::ostream &os)
101 for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
104 s << "(" << std::hex << std::setw(4) << tag->second->GetGroup() << ',';
105 s << std::hex << std::setw(4) << tag->second->GetElement() << ") = "
107 s << tag->second->GetVR() << ", ";
108 s << tag->second->GetFourth() << ", ";
109 s << tag->second->GetName() << "." << std::endl;
115 * \brief Print all the dictionary entries contained in this dictionary.
116 * Entries will be sorted by the name of the dictionary entries.
117 * \warning AVOID USING IT : the name IS NOT an identifier;
118 * unpredictable result
119 * @param os The output stream to be written to.
121 void gdcmDict::PrintByName(std::ostream& os) {
122 std::ostringstream s;
124 for (TagNameHT::iterator tag = NameHt.begin(); tag != NameHt.end(); ++tag){
126 s << tag->second->GetName() << ",";
127 s << tag->second->GetVR() << ", ";
128 s << tag->second->GetFourth() << ", ";
129 s << "(" << std::hex << std::setw(4) << tag->second->GetGroup() << ',';
130 s << std::hex << std::setw(4) << tag->second->GetElement() << ") = ";
131 s << std::dec << std::endl;
136 //-----------------------------------------------------------------------------
140 * \brief adds a new Dicom Dictionary Entry
141 * @param NewEntry entry to add
142 * @return false if Dicom Element already exists
144 bool gdcmDict::AddNewEntry(gdcmDictEntry *NewEntry)
147 key = NewEntry->GetKey();
149 if(KeyHt.count(key) == 1)
151 dbg.Verbose(1, "gdcmDict::AddNewEntry already present", key.c_str());
156 KeyHt[NewEntry->GetKey()] = NewEntry;
157 NameHt[NewEntry->GetName()] = NewEntry; /// MEMORY LEAK in
158 /// std::map<>::operator[]
165 * \brief replaces an already existing Dicom Element by a new one
166 * @param NewEntry new entry (overwrites any previous one with same tag)
167 * @return false if Dicom Element doesn't exist
169 bool gdcmDict::ReplaceEntry(gdcmDictEntry *NewEntry) {
170 if ( RemoveEntry(NewEntry->gdcmDictEntry::GetKey()) ) {
171 KeyHt[NewEntry->GetKey()] = NewEntry;
172 NameHt[NewEntry->GetName()] = NewEntry;
180 * \brief removes an already existing Dicom Dictionary Entry,
181 * identified by its Tag
182 * @param key (group|element)
183 * @return false if Dicom Dictionary Entry doesn't exist
185 bool gdcmDict::RemoveEntry(gdcmTagKey key)
187 if(KeyHt.count(key) == 1)
189 gdcmDictEntry* EntryToDelete = KeyHt.find(key)->second;
193 NameHt.erase(EntryToDelete->GetName());
194 delete EntryToDelete;
202 dbg.Verbose(1, "gdcmDict::RemoveEntry unfound entry", key.c_str());
208 * \brief removes an already existing Dicom Dictionary Entry,
209 * identified by its group,element number
210 * @param group Dicom group number of the Dicom Element
211 * @param element Dicom element number of the Dicom Element
212 * @return false if Dicom Dictionary Entry doesn't exist
214 bool gdcmDict::RemoveEntry (uint16_t group, uint16_t element)
216 return( RemoveEntry(gdcmDictEntry::TranslateToKey(group, element)) );
220 * \brief Get the dictionnary entry identified by it's name.
221 * @param name element of the ElVal to modify
222 * \warning : NEVER use it !
223 * the 'name' IS NOT an identifier within the Dicom Dicom Dictionary
224 * the name MAY CHANGE between two versions !
225 * @return the corresponding dictionnary entry when existing, NULL otherwise
227 gdcmDictEntry* gdcmDict::GetDictEntryByName(TagName name) {
228 if ( ! NameHt.count(name))
230 return NameHt.find(name)->second;
234 * \brief Get the dictionnary entry identified by a given tag (group,element)
235 * @param group group of the entry to be found
236 * @param element element of the entry to be found
237 * @return the corresponding dictionnary entry when existing, NULL otherwise
239 gdcmDictEntry* gdcmDict::GetDictEntryByNumber(uint16_t group, uint16_t element)
241 gdcmTagKey key = gdcmDictEntry::TranslateToKey(group, element);
242 if ( ! KeyHt.count(key))
244 return KeyHt.find(key)->second;
248 * \brief Consider all the entries of the public dicom dictionnary.
249 * Build all list of all the tag names of all those entries.
250 * \sa gdcmDictSet::GetPubDictTagNamesByCategory
251 * @return A list of all entries of the public dicom dictionnary.
253 std::list<std::string>* gdcmDict::GetDictEntryNames(void)
255 std::list<std::string> *Result = new std::list<std::string>;
256 for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
258 Result->push_back( tag->second->GetName() );
265 * \brief Consider all the entries of the public dicom dictionnary.
266 * Build an hashtable whose keys are the names of the groups
267 * (fourth field in each line of dictionary) and whose corresponding
268 * values are lists of all the dictionnary entries among that
269 * group. Note that apparently the Dicom standard doesn't explicitely
270 * define a name (as a string) for each group.
271 * A typical usage of this method would be to enable a dynamic
272 * configuration of a Dicom file browser: the admin/user can
273 * select in the interface which Dicom tags should be displayed.
274 * \warning Dicom *doesn't* define any name for any 'categorie'
275 * (the dictionnary fourth field was formerly NIH defined
276 * - and no longer he is-
277 * and will be removed when Dicom provides us a text file
278 * with the 'official' Dictionnary, that would be more friendly
279 * than asking us to perform a line by line check of the dictionnary
280 * at the beginning of each year to -try to- guess the changes)
281 * Therefore : please NEVER use that fourth field :-(
283 * @return An hashtable: whose keys are the names of the groups and whose
284 * corresponding values are lists of all the dictionnary entries
287 std::map<std::string, std::list<std::string> > *gdcmDict::GetDictEntryNamesByCategory(void)
289 std::map<std::string, std::list<std::string> > *Result = new std::map<std::string, std::list<std::string> >;
291 for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
293 (*Result)[tag->second->GetFourth()].push_back(tag->second->GetName());
298 //-----------------------------------------------------------------------------
301 //-----------------------------------------------------------------------------
304 //-----------------------------------------------------------------------------