gdcmItem.h
Go to the documentation of this file.
/*=========================================================================
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 GDCMITEM_H
#define GDCMITEM_H
#include "gdcmDataElement.h"
#include "gdcmDataSet.h"
#include "gdcmParseException.h"
#include "gdcmSwapper.h"
#ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
#include "gdcmByteSwapFilter.h"
#endif
namespace gdcm_ns
{
class DataSet;
class GDCM_EXPORT Item : public DataElement
{
public:
Item() : DataElement(Tag(0xfffe, 0xe000), 0xFFFFFFFF), NestedDataSet() {}
friend std::ostream& operator<< (std::ostream &os, const Item &val);
void Clear() {
this->DataElement::Clear();
NestedDataSet.Clear();
}
template <typename TDE>
VL GetLength() const;
void InsertDataElement(const DataElement & de) {
NestedDataSet.Insert(de);
// Update the length
if( !IsUndefinedLength() )
{
assert( 0 && "InsertDataElement" );
//ValueLengthField += de.GetLength();
}
}
const DataElement& GetDataElement(const Tag& t) const
{
return NestedDataSet.GetDataElement(t);
}
// Completely defines it with the nested dataset
// destroy anything present
void SetNestedDataSet(const DataSet& nested)
{
NestedDataSet = nested;
}
// Return a const ref to the Nested Data Set
const DataSet &GetNestedDataSet() const
{
return NestedDataSet;
}
DataSet &GetNestedDataSet()
{
return NestedDataSet;
}
//Value const & GetValue() const { return *NestedDataSet; }
Item(Item const &val):DataElement(val)
{
NestedDataSet = val.NestedDataSet;
}
template <typename TDE, typename TSwap>
std::istream &Read(std::istream &is) {
// Superclass
{
DataSet &nested = NestedDataSet;
nested.Clear();
assert( nested.IsEmpty() );
}
if( !TagField.Read<TSwap>(is) )
{
throw Exception("Should not happen (item)");
return is;
}
#ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
// MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm
if( TagField == Tag(0xfeff, 0x00e0)
|| TagField == Tag(0xfeff, 0xdde0) )
{
gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField );
// Invert previously read TagField since wrong endianness:
TagField = Tag( SwapperDoOp::Swap( TagField.GetGroup() ), SwapperDoOp::Swap( TagField.GetElement() ) );
assert ( TagField == Tag(0xfffe, 0xe000)
|| TagField == Tag(0xfffe, 0xe0dd) );
if( !ValueLengthField.Read<SwapperDoOp>(is) )
{
assert(0 && "Should not happen");
return is;
}
// Self
// Some file written by GDCM 1.0 we write 0xFFFFFFFF instead of 0x0
if( TagField == Tag(0xfffe,0xe0dd) )
{
if( ValueLengthField )
{
gdcmErrorMacro( "ValueLengthField is not 0" );
}
}
//else if( ValueLengthField == 0 )
// {
// //assert( TagField == Tag( 0xfffe, 0xe0dd) );
// if( TagField != Tag( 0xfffe, 0xe0dd) )
// {
// gdcmErrorMacro( "SQ: " << TagField << " has a length of 0" );
// }
// }
else if( ValueLengthField.IsUndefined() )
{
DataSet &nested = NestedDataSet;
nested.Clear();
assert( nested.IsEmpty() );
std::streampos start = is.tellg();
try
{
nested.template ReadNested<TDE,SwapperDoOp>(is);
ByteSwapFilter bsf(nested);
bsf.ByteSwap();
}
catch(ParseException &pe)
{
(void)pe;
// MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm
// You have to byteswap the length but not the tag...sigh
gdcmWarningMacro( "Attempt to read nested Item without byteswapping the Value Length." );
start -= is.tellg();
assert( start < 0 );
is.seekg( start, std::ios::cur );
nested.Clear();
nested.template ReadNested<TDE,SwapperNoOp>(is);
ByteSwapFilter bsf(nested);
// Tag are read in big endian, need to byteswap them back...
bsf.SetByteSwapTag(true);
bsf.ByteSwap();
}
catch(Exception &e)
{
// MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm
throw e;
}
catch(...)
{
assert(0);
}
}
else /* if( ValueLengthField.IsUndefined() ) */
{
DataSet &nested = NestedDataSet;
nested.Clear();
assert( nested.IsEmpty() );
nested.template ReadWithLength<TDE,SwapperDoOp>(is, ValueLengthField);
ByteSwapFilter bsf(nested);
bsf.ByteSwap();
}
return is;
}
// http://groups.google.com/group/comp.protocols.dicom/msg/c07efcf5e759fc83
// Bug_Philips_ItemTag_3F3F.dcm
if( TagField == Tag(0x3f3f, 0x3f00) )
{
//TagField = Tag(0xfffe, 0xe000);
}
#endif
if( TagField != Tag(0xfffe, 0xe000) && TagField != Tag(0xfffe, 0xe0dd) )
{
gdcmDebugMacro( "Invalid Item, found tag: " << TagField);
throw Exception( "Not a valid Item" );
}
assert( TagField == Tag(0xfffe, 0xe000) || TagField == Tag(0xfffe, 0xe0dd) );
if( !ValueLengthField.Read<TSwap>(is) )
{
assert(0 && "Should not happen");
return is;
}
// Self
if( TagField == Tag(0xfffe,0xe0dd) )
{
// Some file written by GDCM 1.0 were written with 0xFFFFFFFF instead of 0x0
if( ValueLengthField )
{
gdcmDebugMacro( "ValueLengthField is not 0 but " << ValueLengthField );
}
}
else if( ValueLengthField.IsUndefined() )
{
DataSet &nested = NestedDataSet;
nested.Clear();
assert( nested.IsEmpty() );
nested.template ReadNested<TDE,TSwap>(is);
}
else /* if( ValueLengthField.IsUndefined() ) */
{
assert( !ValueLengthField.IsUndefined() );
DataSet &nested = NestedDataSet;
nested.Clear();
assert( nested.IsEmpty() );
nested.template ReadWithLength<TDE,TSwap>(is, ValueLengthField);
}
return is;
}
template <typename TDE, typename TSwap>
const std::ostream &Write(std::ostream &os) const {
#ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
if( TagField == Tag(0x3f3f,0x3f00) && false )
{
Tag t(0xfffe, 0xe000);
t.Write<TSwap>(os);
}
else
#endif
{
assert ( TagField == Tag(0xfffe, 0xe000)
|| TagField == Tag(0xfffe, 0xe0dd) );
// Not sure how this happen
if( TagField == Tag(0xfffe, 0xe0dd) )
{
gdcmWarningMacro( "SeqDelItem found in defined length Sequence" );
assert( ValueLengthField == 0 );
assert( NestedDataSet.Size() == 0 );
}
if( !TagField.Write<TSwap>(os) )
{
assert(0 && "Should not happen");
return os;
}
}
if( ValueLengthField.IsUndefined() )
{
if( !ValueLengthField.Write<TSwap>(os) )
{
assert(0 && "Should not happen");
return os;
}
}
else
{
const VL dummy = NestedDataSet.GetLength<TDE>();
assert( dummy % 2 == 0 );
//assert( ValueLengthField == dummy );
if( !dummy.Write<TSwap>(os) )
{
assert(0 && "Should not happen");
return os;
}
}
// Self
NestedDataSet.Write<TDE,TSwap>(os);
if( ValueLengthField.IsUndefined() )
{
const Tag itemDelItem(0xfffe,0xe00d);
itemDelItem.Write<TSwap>(os);
VL zero = 0;
zero.Write<TSwap>(os);
}
return os;
}
/*
There are three special SQ related Data Elements that are not ruled by the VR encoding rules conveyed
by the Transfer Syntax. They shall be encoded as Implicit VR. These special Data Elements are Item
(FFFE,E000), Item Delimitation Item (FFFE,E00D), and Sequence Delimitation Item (FFFE,E0DD).
However, the Data Set within the Value Field of the Data Element Item (FFFE,E000) shall be encoded
according to the rules conveyed by the Transfer Syntax.
*/
bool FindDataElement(const Tag &t) const {
return NestedDataSet.FindDataElement( t );
}
private:
/* NESTED DATA SET a Data Set contained within a Data Element of an other Data Set.
* May be nested recursively.
* Only Data Elements with VR = SQ may, themselves, contain Data Sets
*/
DataSet NestedDataSet;
};
//-----------------------------------------------------------------------------
inline std::ostream& operator<<(std::ostream& os, const Item &val)
{
os << val.TagField;
os << "\t" << val.ValueLengthField << "\n";
val.NestedDataSet.Print( os, "\t" );
return os;
}
} // end namespace gdcm_ns
#include "gdcmItem.txx"
#endif //GDCMITEM_H
gdcm::ByteSwapFilter
ByteSwapFilter.
Definition gdcmByteSwapFilter.h:28
gdcm::ByteSwapFilter::SetByteSwapTag
void SetByteSwapTag(bool b)
Definition gdcmByteSwapFilter.h:36
gdcm::ByteSwapFilter::ByteSwap
bool ByteSwap()
gdcm::DataElement::Clear
void Clear()
Clear Data Element (make Value empty and invalidate Tag & VR).
Definition gdcmDataElement.h:112
gdcm::DataElement::IsUndefinedLength
bool IsUndefinedLength() const
return if Value Length if of undefined length
Definition gdcmDataElement.h:153
gdcm::DataElement::TagField
Tag TagField
Definition gdcmDataElement.h:243
gdcm::DataElement::ReadWithLength
std::istream & ReadWithLength(std::istream &is, VL &length)
Definition gdcmDataElement.h:233
gdcm::DataElement::ValueLengthField
VL ValueLengthField
Definition gdcmDataElement.h:245
gdcm::DataElement::DataElement
DataElement(const Tag &t=Tag(0), const VL &vl=0, const VR &vr=VR::INVALID)
Definition gdcmDataElement.h:61
gdcm::DataSet
Class to represent a Data Set (which contains Data Elements).
Definition gdcmDataSet.h:56
gdcm::DataSet::Clear
void Clear()
Definition gdcmDataSet.h:70
gdcm::DataSet::IsEmpty
bool IsEmpty() const
Returns if the dataset is empty.
Definition gdcmDataSet.h:228
gdcm::DataSet::Print
void Print(std::ostream &os, std::string const &indent="") const
Definition gdcmDataSet.h:79
gdcm::Exception
Exception.
Definition gdcmException.h:44
gdcm::Item
Class to represent an Item.
Definition gdcmItem.h:46
gdcm::Item::Item
Item()
Definition gdcmItem.h:48
gdcm::Item::GetLength
VL GetLength() const
gdcm::Item::GetDataElement
const DataElement & GetDataElement(const Tag &t) const
Definition gdcmItem.h:68
gdcm::Item::Item
Item(Item const &val)
Definition gdcmItem.h:91
gdcm::Item::Clear
void Clear()
Definition gdcmItem.h:51
gdcm::Item::operator<<
friend std::ostream & operator<<(std::ostream &os, const Item &val)
Definition gdcmItem.h:315
gdcm::Item::Read
std::istream & Read(std::istream &is)
Definition gdcmItem.h:97
gdcm::Item::GetNestedDataSet
DataSet & GetNestedDataSet()
Definition gdcmItem.h:84
gdcm::Item::SetNestedDataSet
void SetNestedDataSet(const DataSet &nested)
Definition gdcmItem.h:75
gdcm::Item::GetNestedDataSet
const DataSet & GetNestedDataSet() const
Definition gdcmItem.h:80
gdcm::Item::InsertDataElement
void InsertDataElement(const DataElement &de)
Definition gdcmItem.h:59
gdcm::Item::Write
const std::ostream & Write(std::ostream &os) const
Definition gdcmItem.h:239
gdcm::Item::FindDataElement
bool FindDataElement(const Tag &t) const
Definition gdcmItem.h:303
gdcm::ParseException
ParseException Standard exception handling object.
Definition gdcmParseException.h:37
gdcm::SwapperDoOp
Definition gdcmSwapper.h:54
gdcm::SwapperDoOp::Swap
static T Swap(T val)
gdcm::Tag
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element).
Definition gdcmTag.h:39
gdcm::Tag::Write
const std::ostream & Write(std::ostream &os) const
Write a tag in binary rep.
Definition gdcmTag.h:169
gdcm::VL
Value Length.
Definition gdcmVL.h:30
gdcm::VL::Write
const std::ostream & Write(std::ostream &os) const
Definition gdcmVL.h:99
gdcm::VL::GetLength
VL GetLength() const
Definition gdcmVL.h:68
gdcmByteSwapFilter.h
gdcmDataElement.h
gdcmDataSet.h
gdcmParseException.h
gdcmSwapper.h
gdcmWarningMacro
#define gdcmWarningMacro(msg)
Warning.
Definition gdcmTrace.h:142
gdcmErrorMacro
#define gdcmErrorMacro(msg)
Error this is pretty bad, more than just warning It could mean lost of data, something not handle....
Definition gdcmTrace.h:165
gdcmDebugMacro
#define gdcmDebugMacro(msg)
Debug.
Definition gdcmTrace.h:119
GDCM_EXPORT
#define GDCM_EXPORT
Definition gdcmWin32.h:34