
| Current Path : /usr/include/gdcm-3.0/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //usr/include/gdcm-3.0/gdcmDict.h |
/*=========================================================================
Program: GDCM (Grassroots DICOM). A DICOM library
Copyright (c) 2006-2011 Mathieu Malaterre
All rights reserved.
See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#ifndef GDCMDICT_H
#define GDCMDICT_H
#include "gdcmTypes.h"
#include "gdcmTag.h"
#include "gdcmPrivateTag.h"
#include "gdcmDictEntry.h"
#include "gdcmSystem.h"
#include <iostream>
#include <iomanip>
#include <map>
/*
* FIXME / TODO
* I need to seriously rewrite this mess. a class template should work for both a public
* and a private dict
*/
namespace gdcm
{
// Data Element Tag
/**
* \brief Class to represent a map of DictEntry
* \note bla
* TODO FIXME: For Element == 0x0 need to return
* Name = Group Length
* ValueRepresentation = UL
* ValueMultiplicity = 1
*/
class GDCM_EXPORT Dict
{
public:
typedef std::map<Tag, DictEntry> MapDictEntry;
typedef MapDictEntry::iterator Iterator;
typedef MapDictEntry::const_iterator ConstIterator;
//static DictEntry GroupLengthDictEntry; // = DictEntry("Group Length",VR::UL,VM::VM1);
Dict():DictInternal() {
assert( DictInternal.empty() );
}
Dict &operator=(const Dict &_val) = delete;
Dict(const Dict &_val) = delete;
friend std::ostream& operator<<(std::ostream& _os, const Dict &_val);
ConstIterator Begin() const { return DictInternal.begin(); }
ConstIterator End() const { return DictInternal.end(); }
bool IsEmpty() const { return DictInternal.empty(); }
void AddDictEntry(const Tag &tag, const DictEntry &de)
{
#ifndef NDEBUG
MapDictEntry::size_type s = DictInternal.size();
#endif
DictInternal.insert(
MapDictEntry::value_type(tag, de));
assert( s < DictInternal.size() );
}
const DictEntry &GetDictEntry(const Tag &tag) const
{
MapDictEntry::const_iterator it =
DictInternal.find(tag);
if (it == DictInternal.end())
{
#ifdef UNKNOWNPUBLICTAG
// test.acr
if( tag != Tag(0x28,0x15)
&& tag != Tag(0x28,0x16)
&& tag != Tag(0x28,0x199)
// gdcmData/TheralysGDCM1.dcm
&& tag != Tag(0x20,0x1)
// gdcmData/0019004_Baseline_IMG1.dcm
&& tag != Tag(0x8348,0x339)
&& tag != Tag(0xb5e8,0x338)
// gdcmData/dicomdir_Acusson_WithPrivate_WithSR
&& tag != Tag(0x40,0xa125)
)
{
assert( 0 && "Impossible" );
}
#endif
it = DictInternal.find( Tag(0xffff,0xffff) );
return it->second;
}
assert( DictInternal.count(tag) == 1 );
return it->second;
}
/// Function to return the Keyword from a Tag
const char *GetKeywordFromTag(Tag const & tag) const
{
MapDictEntry::const_iterator it =
DictInternal.find(tag);
if (it == DictInternal.end())
{
return nullptr;
}
assert( DictInternal.count(tag) == 1 );
return it->second.GetKeyword();
}
/// Lookup DictEntry by keyword. Even if DICOM standard defines keyword
/// as being unique. The lookup table is built on Tag. Therefore
/// looking up a DictEntry by Keyword is more inefficient than looking up
/// by Tag.
const DictEntry &GetDictEntryByKeyword(const char *keyword, Tag & tag) const
{
MapDictEntry::const_iterator it =
DictInternal.begin();
if( keyword )
{
for(; it != DictInternal.end(); ++it)
{
if( strcmp( keyword, it->second.GetKeyword() ) == 0 )
{
// Found a match !
tag = it->first;
break;
}
}
}
else
{
it = DictInternal.end();
}
if (it == DictInternal.end())
{
tag = Tag(0xffff,0xffff);
it = DictInternal.find( tag );
return it->second;
}
assert( DictInternal.count(tag) == 1 );
return it->second;
}
/// Inefficient way of looking up tag by name. Technically DICOM
/// does not garantee uniqueness (and Curve / Overlay are there to prove it). But
/// most of the time name is in fact uniq and can be uniquely link to a tag
const DictEntry &GetDictEntryByName(const char *name, Tag & tag) const
{
MapDictEntry::const_iterator it =
DictInternal.begin();
if( name )
{
for(; it != DictInternal.end(); ++it)
{
if( strcmp( name, it->second.GetName() ) == 0 )
{
// Found a match !
tag = it->first;
break;
}
}
}
else
{
it = DictInternal.end();
}
if (it == DictInternal.end())
{
tag = Tag(0xffff,0xffff);
it = DictInternal.find( tag );
return it->second;
}
assert( DictInternal.count(tag) == 1 );
return it->second;
}
protected:
friend class Dicts;
void LoadDefault();
private:
MapDictEntry DictInternal;
};
//-----------------------------------------------------------------------------
inline std::ostream& operator<<(std::ostream& os, const Dict &val)
{
Dict::MapDictEntry::const_iterator it = val.DictInternal.begin();
for(;it != val.DictInternal.end(); ++it)
{
const Tag &t = it->first;
const DictEntry &de = it->second;
os << t << " " << de << '\n';
}
return os;
}
// TODO
// For private dict, element < 0x10 should automatically defined:
// Name = "Private Creator"
// ValueRepresentation = LO
// ValueMultiplicity = 1
// Owner = ""
/**
* \brief Private Dict
*/
class GDCM_EXPORT PrivateDict
{
typedef std::map<PrivateTag, DictEntry> MapDictEntry;
friend std::ostream& operator<<(std::ostream& os, const PrivateDict &val);
public:
PrivateDict() = default;
~PrivateDict() = default;
void AddDictEntry(const PrivateTag &tag, const DictEntry &de)
{
#ifndef NDEBUG
MapDictEntry::size_type s = DictInternal.size();
#endif
DictInternal.insert(
MapDictEntry::value_type(tag, de));
// The following code should only be used when manually constructing a Private.xml file by hand
// it will get rid of VR::UN duplicate (ie. if a VR != VR::Un can be found)
#if defined(NDEBUG) && 0
if( s == DictInternal.size() )
{
MapDictEntry::iterator it =
DictInternal.find(tag);
assert( it != DictInternal.end() );
DictEntry &duplicate = it->second;
assert( de.GetVR() == VR::UN || duplicate.GetVR() == VR::UN );
assert( de.GetVR() != duplicate.GetVR() );
if( duplicate.GetVR() == VR::UN )
{
assert( de.GetVR() != VR::UN );
duplicate.SetVR( de.GetVR() );
duplicate.SetVM( de.GetVM() );
assert( GetDictEntry(tag).GetVR() != VR::UN );
assert( GetDictEntry(tag).GetVR() == de.GetVR() );
assert( GetDictEntry(tag).GetVM() == de.GetVM() );
}
return;
}
#endif
assert( s < DictInternal.size() /*&& std::cout << tag << "," << de << std::endl*/ );
}
/// Remove entry 'tag'. Return true on success (element was found
/// and remove). return false if element was not found.
bool RemoveDictEntry(const PrivateTag &tag)
{
MapDictEntry::size_type s =
DictInternal.erase(tag);
assert( s == 1 || s == 0 );
return s == 1;
}
bool FindDictEntry(const PrivateTag &tag) const
{
MapDictEntry::const_iterator it =
DictInternal.find(tag);
if (it == DictInternal.end())
{
return false;
}
return true;
}
const DictEntry &GetDictEntry(const PrivateTag &tag) const
{
// if 0x10 -> return Private Creator
MapDictEntry::const_iterator it =
DictInternal.find(tag);
if (it == DictInternal.end())
{
//assert( 0 && "Impossible" );
it = DictInternal.find( PrivateTag(0xffff,0xffff,"GDCM Private Sentinel" ) );
assert (it != DictInternal.end());
return it->second;
}
assert( DictInternal.count(tag) == 1 );
return it->second;
}
void PrintXML() const
{
MapDictEntry::const_iterator it = DictInternal.begin();
std::cout << "<dict edition=\"2008\">\n";
for(;it != DictInternal.end(); ++it)
{
const PrivateTag &t = it->first;
const DictEntry &de = it->second;
std::cout << " <entry group=\"" << std::hex << std::setw(4)
<< std::setfill('0') << t.GetGroup() << "\"" <<
" element=\"xx" << std::setw(2) << std::setfill('0')<< t.GetElement() << "\"" << " vr=\""
<< de.GetVR() << "\" vm=\"" << de.GetVM() << "\" owner=\""
<< t.GetOwner();
const char *name = de.GetName();
if( *name == 0 )
{
std::cout << "\"/>\n";
}
else
{
std::cout << "\" name=\"" << de.GetName() << "\"/>\n";
}
}
std::cout << "</dict>\n";
}
bool IsEmpty() const { return DictInternal.empty(); }
protected:
friend class Dicts;
void LoadDefault();
private:
PrivateDict &operator=(const PrivateDict &_val) = delete;
PrivateDict(const PrivateDict &_val) = delete;
MapDictEntry DictInternal;
};
//-----------------------------------------------------------------------------
inline std::ostream& operator<<(std::ostream& os, const PrivateDict &val)
{
PrivateDict::MapDictEntry::const_iterator it = val.DictInternal.begin();
for(;it != val.DictInternal.end(); ++it)
{
const PrivateTag &t = it->first;
const DictEntry &de = it->second;
os << t << " " << de << '\n';
}
return os;
}
} // end namespace gdcm
#endif //GDCMDICT_H