
| Current Path : /proc/thread-self/root/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 : //proc/thread-self/root/usr/include/gdcm-3.0/gdcmDataSet.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 GDCMDATASET_H
#define GDCMDATASET_H
#include "gdcmDataElement.h"
#include "gdcmTag.h"
#include "gdcmVR.h"
#include "gdcmElement.h"
#include "gdcmMediaStorage.h"
#include <set>
#include <iterator>
namespace gdcm_ns
{
class GDCM_EXPORT DataElementException : public std::exception {};
class PrivateTag;
/**
* \brief Class to represent a Data Set (which contains Data Elements)
* \details A Data Set represents an instance of a real world Information Object
* \note
* DATA SET:
* Exchanged information consisting of a structured set of Attribute values
* directly or indirectly related to Information Objects. The value of each
* Attribute in a Data Set is expressed as a Data Element.
* A collection of Data Elements ordered by increasing Data Element Tag
* number that is an encoding of the values of Attributes of a real world
* object.
* \note
* Implementation note. If one do:
* DataSet ds;
* ds.SetLength(0);
* ds.Read(is);
* setting length to 0 actually means try to read is as if it was a root
* DataSet. Other value are undefined (nested dataset with undefined length)
* or defined length (different from 0) means nested dataset with defined
* length.
*
* \warning
* a DataSet does not have a Transfer Syntax type, only a File does.
*/
class GDCM_EXPORT DataSet
{
friend class CSAHeader;
public:
typedef std::set<DataElement> DataElementSet;
typedef DataElementSet::const_iterator ConstIterator;
typedef DataElementSet::iterator Iterator;
typedef DataElementSet::size_type SizeType;
//typedef typename DataElementSet::iterator iterator;
ConstIterator Begin() const { return DES.begin(); }
Iterator Begin() { return DES.begin(); }
ConstIterator End() const { return DES.end(); }
Iterator End() { return DES.end(); }
const DataElementSet &GetDES() const { return DES; }
DataElementSet &GetDES() { return DES; }
void Clear() {
DES.clear();
assert( DES.empty() );
}
SizeType Size() const {
return DES.size();
}
void Print(std::ostream &os, std::string const &indent = "") const {
// CT_Phillips_JPEG2K_Decompr_Problem.dcm has a SQ of length == 0
//int s = DES.size();
//assert( s );
//std::copy(DES.begin(), DES.end(),
// std::ostream_iterator<DataElement>(os, "\n"));
ConstIterator it = DES.begin();
for( ; it != DES.end(); ++it)
{
os << indent << *it << "\n";
}
}
template <typename TDE>
unsigned int ComputeGroupLength(Tag const &tag) const
{
assert( tag.GetElement() == 0x0 );
const DataElement r(tag);
ConstIterator it = DES.find(r);
unsigned int res = 0;
for( ++it; it != DES.end()
&& it->GetTag().GetGroup() == tag.GetGroup(); ++it)
{
assert( it->GetTag().GetElement() != 0x0 );
assert( it->GetTag().GetGroup() == tag.GetGroup() );
res += it->GetLength<TDE>();
}
return res;
}
template <typename TDE>
VL GetLength() const {
if( DES.empty() ) return 0;
assert( !DES.empty() );
VL ll = 0;
assert( ll == 0 );
ConstIterator it = DES.begin();
for( ; it != DES.end(); ++it)
{
assert( !(it->GetLength<TDE>().IsUndefined()) );
if ( it->GetTag() != Tag(0xfffe,0xe00d) )
{
ll += it->GetLength<TDE>();
}
}
return ll;
}
/// Insert a DataElement in the DataSet.
/// \warning: Tag need to be >= 0x8 to be considered valid data element
void Insert(const DataElement& de) {
// FIXME: there is a special case where a dataset can have value < 0x8, see:
// $ gdcmdump --csa gdcmData/SIEMENS-JPEG-CorruptFrag.dcm
if( de.GetTag().GetGroup() >= 0x0008 || de.GetTag().GetGroup() == 0x4 )
{
// prevent user error:
if( de.GetTag() == Tag(0xfffe,0xe00d)
|| de.GetTag() == Tag(0xfffe,0xe0dd)
|| de.GetTag() == Tag(0xfffe,0xe000) )
{
}
else
{
InsertDataElement( de );
}
}
else
{
gdcmErrorMacro( "Cannot add element with group < 0x0008 and != 0x4 in the dataset: " << de.GetTag() );
}
}
/// Replace a dataelement with another one
void Replace(const DataElement& de) {
ConstIterator it = DES.find(de);
if( it != DES.end() )
{
// detect loop:
gdcmAssertAlwaysMacro( &*it != &de );
DES.erase(it);
}
DES.insert(de);
}
/// Only replace a DICOM attribute when it is missing or empty
void ReplaceEmpty(const DataElement& de) {
ConstIterator it = DES.find(de);
if( it != DES.end() && it->IsEmpty() )
{
// detect loop:
gdcmAssertAlwaysMacro( &*it != &de );
DES.erase(it);
}
DES.insert(de);
}
/// Completely remove a dataelement from the dataset
SizeType Remove(const Tag& tag) {
DataElementSet::size_type count = DES.erase(tag);
assert( count == 0 || count == 1 );
return count;
}
/// Return the DataElement with Tag 't'
/// \warning:
/// This only search at the 'root level' of the DataSet
//DataElement& GetDataElement(const Tag &t) {
// DataElement r(t);
// Iterator it = DES.find(r);
// if( it != DES.end() )
// return *it;
// return GetDEEnd();
// }
const DataElement& GetDataElement(const Tag &t) const {
const DataElement r(t);
ConstIterator it = DES.find(r);
if( it != DES.end() )
return *it;
return GetDEEnd();
}
const DataElement& operator[] (const Tag &t) const { return GetDataElement(t); }
const DataElement& operator() (uint16_t group, uint16_t element) const { return GetDataElement( Tag(group,element) ); }
/// Return the private creator of the private tag 't':
std::string GetPrivateCreator(const Tag &t) const;
/// Look up if private tag 't' is present in the dataset:
bool FindDataElement(const PrivateTag &t) const;
/// Return the dataelement
const DataElement& GetDataElement(const PrivateTag &t) const;
// DUMB: this only search within the level of the current DataSet
bool FindDataElement(const Tag &t) const {
const DataElement r(t);
//ConstIterator it = DES.find(r);
if( DES.find(r) != DES.end() )
{
return true;
}
return false;
}
// WARNING:
// This only search at the same level as the DataSet is !
const DataElement& FindNextDataElement(const Tag &t) const {
const DataElement r(t);
ConstIterator it = DES.lower_bound(r);
if( it != DES.end() )
return *it;
return GetDEEnd();
}
/// Returns if the dataset is empty
bool IsEmpty() const { return DES.empty(); };
DataSet& operator=(DataSet const &)
= default;
/*
template <typename TOperation>
void ExecuteOperation(TOperation & operation) {
assert( !DES.empty() );
DataElementSet::iterator it = Begin();
for( ; it != End(); ++it)
{
DataElement &de = (DataElement&)*it;
operation( de );
}
}
*/
template <typename TDE, typename TSwap>
std::istream &ReadNested(std::istream &is);
template <typename TDE, typename TSwap>
std::istream &Read(std::istream &is);
template <typename TDE, typename TSwap>
std::istream &ReadUpToTag(std::istream &is, const Tag &t, std::set<Tag> const & skiptags);
template <typename TDE, typename TSwap>
std::istream &ReadUpToTagWithLength(std::istream &is, const Tag &t, std::set<Tag> const & skiptags, VL & length);
template <typename TDE, typename TSwap>
std::istream &ReadSelectedTags(std::istream &is, const std::set<Tag> & tags, bool readvalues = true);
template <typename TDE, typename TSwap>
std::istream &ReadSelectedTagsWithLength(std::istream &is, const std::set<Tag> & tags, VL & length, bool readvalues = true);
template <typename TDE, typename TSwap>
std::istream &ReadSelectedPrivateTags(std::istream &is, const std::set<PrivateTag> & tags, bool readvalues = true);
template <typename TDE, typename TSwap>
std::istream &ReadSelectedPrivateTagsWithLength(std::istream &is, const std::set<PrivateTag> & tags, VL & length, bool readvalues = true);
template <typename TDE, typename TSwap>
std::ostream const &Write(std::ostream &os) const;
template <typename TDE, typename TSwap>
std::istream &ReadWithLength(std::istream &is, VL &length);
MediaStorage GetMediaStorage() const;
protected:
/* GetDEEnd is a Win32 only issue, one cannot use a dllexported
* static member data in an inline function, otherwise symbol
* will get reported as missing in any dll using the inlined function
*/
const DataElement& GetDEEnd() const;
// This function is not safe, it does not check for the value of the tag
// so depending whether we are getting called from a dataset or file meta header
// the condition is different
void InsertDataElement(const DataElement& de) {
//if( de.GetTag() == Tag(0xfffe,0xe00d) ) return;
//if( de.GetTag() == Tag(0xfffe,0xe0dd) ) return;
#ifndef NDEBUG
std::pair<Iterator,bool> pr = DES.insert(de);
if( pr.second == false )
{
gdcmWarningMacro( "DataElement: " << de << " was already found, skipping duplicate entry.\n"
"Original entry kept is: " << *pr.first );
}
#else
DES.insert(de);
#endif
assert( de.IsEmpty() || de.GetVL() == de.GetValue().GetLength() );
}
protected:
// Internal function, that will compute the actual Tag (if found) of
// a requested Private Tag (XXXX,YY,"PRIVATE")
Tag ComputeDataElement(const PrivateTag & t) const;
private:
DataElementSet DES;
static DataElement DEEnd;
friend std::ostream& operator<<(std::ostream &_os, const DataSet &);
};
//-----------------------------------------------------------------------------
inline std::ostream& operator<<(std::ostream &os, const DataSet &val)
{
val.Print(os);
return os;
}
#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPHP)
/*
* HACK: I need this temp class to be able to manipulate a std::set from python,
* swig does not support wrapping of simple class like std::set...
*/
class SWIGDataSet
{
public:
SWIGDataSet(DataSet &des):Internal(des),it(des.Begin()) {}
const DataElement& GetCurrent() const { return *it; }
void Start() { it = Internal.Begin(); }
bool IsAtEnd() const { return it == Internal.End(); }
void Next() { ++it; }
private:
DataSet & Internal;
DataSet::ConstIterator it;
};
#endif /* SWIG */
/**
* \example SimplePrint.cs
* This is a C# example on how to use gdcm::SWIGDataSet
*/
} // end namespace gdcm_ns
#include "gdcmDataSet.txx"
#endif //GDCMDATASET_H