gdcmFragment.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 GDCMFRAGMENT_H
#define GDCMFRAGMENT_H
#include "gdcmDataElement.h"
#include "gdcmByteValue.h"
#include "gdcmSmartPointer.h"
#include "gdcmParseException.h"
namespace gdcm_ns
{
// Implementation detail:
// I think Fragment should be a protected subclass of DataElement:
// looking somewhat like this:
/*
class GDCM_EXPORT Fragment : protected DataElement
{
public:
using DataElement::GetTag;
using DataElement::GetVL;
using DataElement::SetByteValue;
using DataElement::GetByteValue;
using DataElement::GetValue;
*/
// Instead I am only hiding the SetTag member...
class GDCM_EXPORT Fragment : public DataElement
{
//protected:
// void SetTag(const Tag &t);
public:
Fragment() : DataElement(Tag(0xfffe, 0xe000), 0) {}
friend std::ostream &operator<<(std::ostream &os, const Fragment &val);
VL GetLength() const;
VL ComputeLength() const;
template <typename TSwap>
std::istream &Read(std::istream &is)
{
ReadPreValue<TSwap>(is);
return ReadValue<TSwap>(is);
}
template <typename TSwap>
std::istream &ReadPreValue(std::istream &is)
{
TagField.Read<TSwap>(is);
if( !is )
{
// BogusItemStartItemEnd.dcm
throw Exception( "Problem #1" );
}
if( !ValueLengthField.Read<TSwap>(is) )
{
// GENESIS_SIGNA-JPEG-CorruptFrag.dcm
// JPEG fragment is declared to have 61902, but in fact really is only 61901
// so we end up reading 0xddff,0x00e0, and VL = 0x0 (1 byte)
throw Exception( "Problem #2" );
}
#ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
const Tag itemStart(0xfffe, 0xe000);
const Tag seqDelItem(0xfffe,0xe0dd);
if( TagField != itemStart && TagField != seqDelItem )
{
throw Exception( "Problem #3" );
}
#endif
return is;
}
template <typename TSwap>
std::istream &ReadValue(std::istream &is)
{
// Self
SmartPointer<ByteValue> bv = new ByteValue;
bv->SetLength(ValueLengthField);
if( !bv->Read<TSwap>(is) )
{
// Fragment is incomplete, but is a itemStart, let's try to push it anyway...
gdcmWarningMacro( "Fragment could not be read" );
//bv->SetLength(is.gcount());
ValueField = bv;
ParseException pe;
pe.SetLastElement( *this );
throw pe;
}
ValueField = bv;
return is;
}
template <typename TSwap>
std::istream &ReadBacktrack(std::istream &is)
{
const Tag itemStart(0xfffe, 0xe000);
const Tag seqDelItem(0xfffe,0xe0dd);
bool cont = true;
const std::streampos start = is.tellg();
const int max = 10;
int offset = 0;
while( cont )
{
TagField.Read<TSwap>(is);
assert( is );
if( TagField != itemStart && TagField != seqDelItem )
{
++offset;
is.seekg( (std::streampos)((size_t)start - offset) );
gdcmWarningMacro( "Fuzzy Search, backtrack: " << (start - is.tellg()) << " Offset: " << is.tellg() );
if( offset > max )
{
gdcmErrorMacro( "Giving up" );
throw "Impossible to backtrack";
}
}
else
{
cont = false;
}
}
assert( TagField == itemStart || TagField == seqDelItem );
if( !ValueLengthField.Read<TSwap>(is) )
{
return is;
}
// Self
SmartPointer<ByteValue> bv = new ByteValue;
bv->SetLength(ValueLengthField);
if( !bv->Read<TSwap>(is) )
{
// Fragment is incomplete, but is a itemStart, let's try to push it anyway...
gdcmWarningMacro( "Fragment could not be read" );
//bv->SetLength(is.gcount());
ValueField = bv;
ParseException pe;
pe.SetLastElement( *this );
throw pe;
}
ValueField = bv;
return is;
}
template <typename TSwap>
std::ostream &Write(std::ostream &os) const {
const Tag itemStart(0xfffe, 0xe000);
const Tag seqDelItem(0xfffe,0xe0dd);
if( !TagField.Write<TSwap>(os) )
{
assert(0 && "Should not happen");
return os;
}
assert( TagField == itemStart
|| TagField == seqDelItem );
const ByteValue *bv = GetByteValue();
// VL
// The following piece of code is hard to read in order to support such broken file as:
// CompressedLossy.dcm
if( IsEmpty() )
{
//assert( bv );
VL zero = 0;
if( !zero.Write<TSwap>(os) )
{
assert(0 && "Should not happen");
return os;
}
}
else
{
assert( ValueLengthField );
assert( !ValueLengthField.IsUndefined() );
const VL actuallen = bv->ComputeLength();
assert( actuallen == ValueLengthField || actuallen == ValueLengthField + 1 );
if( !actuallen.Write<TSwap>(os) )
{
assert(0 && "Should not happen");
return os;
}
}
// Value
if( ValueLengthField && bv )
{
// Self
assert( bv );
assert( bv->GetLength() == ValueLengthField );
if( !bv->Write<TSwap>(os) )
{
assert(0 && "Should not happen");
return os;
}
}
return os;
}
};
//-----------------------------------------------------------------------------
inline std::ostream &operator<<(std::ostream &os, const Fragment &val)
{
os << "Tag: " << val.TagField;
os << "\tVL: " << val.ValueLengthField;
if( val.ValueField )
{
os << "\t" << *(val.ValueField);
}
return os;
}
} // end namespace gdcm_ns
#endif //GDCMFRAGMENT_H
gdcm::ByteValue
Class to represent binary value (array of bytes).
Definition gdcmByteValue.h:35
gdcm::ByteValue::Write
std::ostream const & Write(std::ostream &os) const
Definition gdcmByteValue.h:167
gdcm::ByteValue::ComputeLength
VL ComputeLength() const
Definition gdcmByteValue.h:79
gdcm::ByteValue::GetLength
VL GetLength() const override
Definition gdcmByteValue.h:77
gdcm::DataElement::ValueField
ValuePtr ValueField
Definition gdcmDataElement.h:250
gdcm::DataElement::GetByteValue
const ByteValue * GetByteValue() const
Definition gdcmDataElement.h:133
gdcm::DataElement::TagField
Tag TagField
Definition gdcmDataElement.h:243
gdcm::DataElement::IsEmpty
bool IsEmpty() const
Check if Data Element is empty.
Definition gdcmDataElement.h:106
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::Exception
Exception.
Definition gdcmException.h:44
gdcm::Fragment
Class to represent a Fragment.
Definition gdcmFragment.h:44
gdcm::Fragment::operator<<
friend std::ostream & operator<<(std::ostream &os, const Fragment &val)
Definition gdcmFragment.h:216
gdcm::Fragment::ReadPreValue
std::istream & ReadPreValue(std::istream &is)
Definition gdcmFragment.h:63
gdcm::Fragment::Fragment
Fragment()
Definition gdcmFragment.h:48
gdcm::Fragment::Write
std::ostream & Write(std::ostream &os) const
Definition gdcmFragment.h:164
gdcm::Fragment::GetLength
VL GetLength() const
gdcm::Fragment::ReadBacktrack
std::istream & ReadBacktrack(std::istream &is)
Definition gdcmFragment.h:110
gdcm::Fragment::ComputeLength
VL ComputeLength() const
gdcm::Fragment::Read
std::istream & Read(std::istream &is)
Definition gdcmFragment.h:56
gdcm::Fragment::ReadValue
std::istream & ReadValue(std::istream &is)
Definition gdcmFragment.h:90
gdcm::ParseException
ParseException Standard exception handling object.
Definition gdcmParseException.h:37
gdcm::ParseException::SetLastElement
void SetLastElement(DataElement &de)
Definition gdcmParseException.h:71
gdcm::SmartPointer
Class for Smart Pointer.
Definition gdcmSmartPointer.h:40
gdcm::Tag
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element).
Definition gdcmTag.h:39
gdcm::VL
Value Length.
Definition gdcmVL.h:30
gdcm::VL::Write
const std::ostream & Write(std::ostream &os) const
Definition gdcmVL.h:99
gdcmByteValue.h
gdcmDataElement.h
gdcmParseException.h
gdcmSmartPointer.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
GDCM_EXPORT
#define GDCM_EXPORT
Definition gdcmWin32.h:34
gdcm::operator<<
std::ostream & operator<<(std::ostream &os, const Directory &d)
Definition gdcmDirectory.h:88