Program: gdcm
Module: $RCSfile: gdcmDocument.cxx,v $
Language: C++
- Date: $Date: 2004/06/25 19:37:05 $
- Version: $Revision: 1.35 $
+ Date: $Date: 2004/07/16 15:18:05 $
+ Version: $Revision: 1.49 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
const unsigned int gdcmDocument::HEADER_LENGTH_TO_READ = 256;
// Refer to gdcmDocument::SetMaxSizeLoadEntry()
-const unsigned int gdcmDocument::MAX_SIZE_LOAD_ELEMENT_VALUE = 0x7fffffff;// 4096;
-
-const unsigned int gdcmDocument::MAX_SIZE_PRINT_ELEMENT_VALUE = 0x7fffffff;//64;
+const unsigned int gdcmDocument::MAX_SIZE_LOAD_ELEMENT_VALUE = 0xfff; // 4096
+const unsigned int gdcmDocument::MAX_SIZE_PRINT_ELEMENT_VALUE = 0x7fffffff;
//-----------------------------------------------------------------------------
// Constructor / Destructor
bool exception_on_error,
bool enable_sequences,
bool ignore_shadow)
- : gdcmElementSet(-1) {
- enableSequences=enable_sequences;
- IgnoreShadow =ignore_shadow;
-
+ : gdcmElementSet(-1)
+{
+ IgnoreShadow = ignore_shadow;
+ //enableSequences=enable_sequences;
+ (void)enable_sequences;
+ enableSequences = true; // JPR // TODO : remove params out of the constructor
SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
Filename = inFilename;
Initialise();
// Load 'non string' values
std::string PhotometricInterpretation = GetEntryByNumber(0x0028,0x0004);
- if( PhotometricInterpretation == "PALETTE COLOR " ) {
+ if( PhotometricInterpretation == "PALETTE COLOR " )
+ {
LoadEntryVoidArea(0x0028,0x1200); // gray LUT
LoadEntryVoidArea(0x0028,0x1201); // R LUT
LoadEntryVoidArea(0x0028,0x1202); // G LUT
* @param exception_on_error
*/
gdcmDocument::gdcmDocument(bool exception_on_error)
- :gdcmElementSet(-1) {
+ :gdcmElementSet(-1)
+{
(void)exception_on_error;
- enableSequences=0;
+ //enableSequences=0; // ?!? JPR
SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
Initialise();
/**
* \brief Canonical destructor.
*/
-gdcmDocument::~gdcmDocument (void) {
+gdcmDocument::~gdcmDocument ()
+{
RefPubDict = NULL;
RefShaDict = NULL;
// Recursive clean up of sequences
- for (TagDocEntryHT::iterator it = tagHT.begin(); it != tagHT.end(); ++it )
+ for (TagDocEntryHT::const_iterator it = tagHT.begin();
+ it != tagHT.end(); ++it )
{
- delete it->second;
+ delete it->second;
}
tagHT.clear();
}
* \brief Prints The Dict Entries of THE public Dicom Dictionary
* @return
*/
-void gdcmDocument::PrintPubDict(std::ostream & os) {
+void gdcmDocument::PrintPubDict(std::ostream & os)
+{
RefPubDict->Print(os);
}
* \brief Prints The Dict Entries of THE shadow Dicom Dictionary
* @return
*/
-void gdcmDocument::PrintShaDict(std::ostream & os) {
+void gdcmDocument::PrintShaDict(std::ostream & os)
+{
RefShaDict->Print(os);
}
/**
* \brief Get the public dictionary used
*/
-gdcmDict *gdcmDocument::GetPubDict(void) {
+gdcmDict *gdcmDocument::GetPubDict()
+{
return RefPubDict;
}
/**
* \brief Get the shadow dictionary used
*/
-gdcmDict *gdcmDocument::GetShaDict(void) {
+gdcmDict *gdcmDocument::GetShaDict()
+{
return RefShaDict;
}
* \brief Set the shadow dictionary used
* \param dict dictionary to use in shadow
*/
-bool gdcmDocument::SetShaDict(gdcmDict *dict){
- RefShaDict=dict;
+bool gdcmDocument::SetShaDict(gdcmDict *dict)
+{
+ RefShaDict = dict;
return !RefShaDict;
}
* \brief Set the shadow dictionary used
* \param dictName name of the dictionary to use in shadow
*/
-bool gdcmDocument::SetShaDict(DictKey dictName){
- RefShaDict=gdcmGlobal::GetDicts()->GetDict(dictName);
+bool gdcmDocument::SetShaDict(DictKey dictName)
+{
+ RefShaDict = gdcmGlobal::GetDicts()->GetDict(dictName);
return !RefShaDict;
}
* @return true when gdcmDocument is the one of a reasonable Dicom/Acr file,
* false otherwise.
*/
-bool gdcmDocument::IsReadable(void) {
- if(Filetype==gdcmUnknown) {
+bool gdcmDocument::IsReadable()
+{
+ if( Filetype == gdcmUnknown)
+ {
+ std::cout << " gdcmDocument::IsReadable: Filetype " << Filetype
+ << " " << "gdcmUnknown " << gdcmUnknown << std::endl; //JPR
dbg.Verbose(0, "gdcmDocument::IsReadable: wrong filetype");
return false;
}
- if(!tagHT.empty()<=0) {
+
+ if(tagHT.empty())
+ {
dbg.Verbose(0, "gdcmDocument::IsReadable: no tags in internal"
" hash table.");
return false;
}
- return(true);
+ return true;
}
* the current document. False either when the document contains
* no Transfer Syntax, or when the Tranfer Syntaxes don't match.
*/
-bool gdcmDocument::IsGivenTransferSyntax(const std::string & SyntaxToCheck)
+bool gdcmDocument::IsGivenTransferSyntax(std::string const & syntaxToCheck)
{
- gdcmDocEntry *Entry = GetDocEntryByNumber(0x0002, 0x0010);
- if ( !Entry )
+ gdcmDocEntry *entry = GetDocEntryByNumber(0x0002, 0x0010);
+ if ( !entry )
+ {
return false;
+ }
// The entry might be present but not loaded (parsing and loading
// happen at differente stages): try loading and proceed with check...
- LoadDocEntrySafe(Entry);
- if (gdcmValEntry* ValEntry = dynamic_cast< gdcmValEntry* >(Entry) )
+ LoadDocEntrySafe(entry);
+ if (gdcmValEntry* valEntry = dynamic_cast< gdcmValEntry* >(entry) )
{
- std::string Transfer = ValEntry->GetValue();
+ std::string transfer = valEntry->GetValue();
+
// The actual transfer (as read from disk) might be padded. We
// first need to remove the potential padding. We can make the
// weak assumption that padding was not executed with digits...
- while ( ! isdigit(Transfer[Transfer.length()-1]) )
+ while ( ! isdigit(transfer[transfer.length()-1]) )
{
- Transfer.erase(Transfer.length()-1, 1);
+ transfer.erase(transfer.length()-1, 1);
}
- if ( Transfer == SyntaxToCheck )
+ if ( transfer == syntaxToCheck )
+ {
return true;
+ }
}
return false;
}
* \sa \ref gdcmDocument::IsGivenTransferSyntax.
* @return True when ImplicitVRLittleEndian found. False in all other cases.
*/
-bool gdcmDocument::IsImplicitVRLittleEndianTransferSyntax(void)
+bool gdcmDocument::IsImplicitVRLittleEndianTransferSyntax()
{
return IsGivenTransferSyntax(UI1_2_840_10008_1_2);
}
* and if it corresponds to a ExplicitVRLittleEndian one.
* @return True when ExplicitVRLittleEndian found. False in all other cases.
*/
-bool gdcmDocument::IsExplicitVRLittleEndianTransferSyntax(void)
+bool gdcmDocument::IsExplicitVRLittleEndianTransferSyntax()
{
return IsGivenTransferSyntax(UI1_2_840_10008_1_2_1);
}
* and if it corresponds to a DeflatedExplicitVRLittleEndian one.
* @return True when DeflatedExplicitVRLittleEndian found. False in all other cases.
*/
-bool gdcmDocument::IsDeflatedExplicitVRLittleEndianTransferSyntax(void)
+bool gdcmDocument::IsDeflatedExplicitVRLittleEndianTransferSyntax()
{
return IsGivenTransferSyntax(UI1_2_840_10008_1_2_1_99);
}
* and if it corresponds to a Explicit VR Big Endian one.
* @return True when big endian found. False in all other cases.
*/
-bool gdcmDocument::IsExplicitVRBigEndianTransferSyntax(void)
+bool gdcmDocument::IsExplicitVRBigEndianTransferSyntax()
{
return IsGivenTransferSyntax(UI1_2_840_10008_1_2_2);
}
* and if it corresponds to a JPEGBaseLineProcess1 one.
* @return True when JPEGBaseLineProcess1found. False in all other cases.
*/
-bool gdcmDocument::IsJPEGBaseLineProcess1TransferSyntax(void)
+bool gdcmDocument::IsJPEGBaseLineProcess1TransferSyntax()
{
return IsGivenTransferSyntax(UI1_2_840_10008_1_2_4_50);
}
* and if it corresponds to a JPEGExtendedProcess2-4 one.
* @return True when JPEGExtendedProcess2-4 found. False in all other cases.
*/
-bool gdcmDocument::IsJPEGExtendedProcess2_4TransferSyntax(void)
+bool gdcmDocument::IsJPEGExtendedProcess2_4TransferSyntax()
{
return IsGivenTransferSyntax(UI1_2_840_10008_1_2_4_51);
}
* and if it corresponds to a JPEGExtendeProcess3-5 one.
* @return True when JPEGExtendedProcess3-5 found. False in all other cases.
*/
-bool gdcmDocument::IsJPEGExtendedProcess3_5TransferSyntax(void)
+bool gdcmDocument::IsJPEGExtendedProcess3_5TransferSyntax()
{
return IsGivenTransferSyntax(UI1_2_840_10008_1_2_4_52);
}
* @return True when JPEGSpectralSelectionProcess6-8 found. False in all
* other cases.
*/
-bool gdcmDocument::IsJPEGSpectralSelectionProcess6_8TransferSyntax(void)
+bool gdcmDocument::IsJPEGSpectralSelectionProcess6_8TransferSyntax()
{
return IsGivenTransferSyntax(UI1_2_840_10008_1_2_4_53);
}
* @return True when RLE Lossless found. False in all
* other cases.
*/
-bool gdcmDocument::IsRLELossLessTransferSyntax(void)
+bool gdcmDocument::IsRLELossLessTransferSyntax()
{
return IsGivenTransferSyntax(UI1_2_840_10008_1_2_5);
}
* other cases.
*/
-bool gdcmDocument::IsJPEGLossless(void)
+bool gdcmDocument::IsJPEGLossless()
{
return ( IsGivenTransferSyntax(UI1_2_840_10008_1_2_4_55)
|| IsGivenTransferSyntax(UI1_2_840_10008_1_2_4_57)
* @return True when JPEG2000 (Lossly or LossLess) found. False in all
* other cases.
*/
-bool gdcmDocument::IsJPEG2000(void)
+bool gdcmDocument::IsJPEG2000()
{
return ( IsGivenTransferSyntax(UI1_2_840_10008_1_2_4_90)
|| IsGivenTransferSyntax(UI1_2_840_10008_1_2_4_91) );
* \brief Predicate for dicom version 3 file.
* @return True when the file is a dicom version 3.
*/
-bool gdcmDocument::IsDicomV3(void) {
+bool gdcmDocument::IsDicomV3()
+{
// Checking if Transfert Syntax exists is enough
// Anyway, it's to late check if the 'Preamble' was found ...
// And ... would it be a rich idea to check ?
// (some 'no Preamble' DICOM images exist !)
- return (GetDocEntryByNumber(0x0002, 0x0010) != NULL);
+ return GetDocEntryByNumber(0x0002, 0x0010) != NULL;
}
/**
* (ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown)
* @return the FileType code
*/
-FileType gdcmDocument::GetFileType(void) {
+FileType gdcmDocument::GetFileType()
+{
return Filetype;
}
FILE *gdcmDocument::OpenFile(bool exception_on_error)
throw(gdcmFileError)
{
- fp=fopen(Filename.c_str(),"rb");
+ fp = fopen(Filename.c_str(),"rb");
if(!fp)
{
- if(exception_on_error)
+ if(exception_on_error)
+ {
throw gdcmFileError("gdcmDocument::gdcmDocument(const char *, bool)");
+ }
else
{
dbg.Verbose(0, "gdcmDocument::OpenFile cannot open file: ",
if ( fp )
{
- guint16 zero;
+ uint16_t zero;
fread(&zero, (size_t)2, (size_t)1, fp);
//ACR -- or DICOM with no Preamble --
if( zero == 0x0008 || zero == 0x0800 || zero == 0x0002 || zero == 0x0200)
+ {
return fp;
+ }
//DICOM
fseek(fp, 126L, SEEK_CUR);
char dicm[4];
fread(dicm, (size_t)4, (size_t)1, fp);
if( memcmp(dicm, "DICM", 4) == 0 )
+ {
return fp;
+ }
fclose(fp);
dbg.Verbose(0, "gdcmDocument::OpenFile not DICOM/ACR", Filename.c_str());
}
- else {
+ else
+ {
dbg.Verbose(0, "gdcmDocument::OpenFile cannot open file", Filename.c_str());
}
- return NULL;
+
+ return 0;
}
/**
* \brief closes the file
* @return TRUE if the close was successfull
*/
-bool gdcmDocument::CloseFile(void) {
+bool gdcmDocument::CloseFile()
+{
int closed = fclose(fp);
fp = (FILE *)0;
- if (! closed)
- return false;
- return true;
+
+ return closed;
}
/**
* (ACR-NEMA, ExplicitVR, ImplicitVR)
* \return Always true.
*/
-void gdcmDocument::Write(FILE* fp,FileType filetype) {
-///
-/// ==============
-/// The stuff is rewritten using the SeQuence based
-/// tree-like stucture (cf : Print )
-/// To be checked
-/// =============
-
+void gdcmDocument::Write(FILE* fp,FileType filetype)
+{
/// \todo move the following lines (and a lot of others, to be written)
/// to a future function CheckAndCorrectHeader
/// \todo Refer to standards on page 21, chapter 6.2
/// "Value representation": values with a VR of UI shall be
/// padded with a single trailing null
- /// Dans le cas suivant on doit pader manuellement avec un 0
+ /// in the following case we have to padd manually with a 0
SetEntryLengthByNumber(18, 0x0002, 0x0010);
}
SetEntryLengthByNumber(20, 0x0002, 0x0010);
}
-
+
/**
* \todo rewrite later, if really usefull
- * ('Group Length' element is optional in DICOM)
- *
- * --> Warning : un-updated odd groups lengthes can causes pb
- * --> (xmedcon breaks)
- * --> to be re- written with future org.
+ * - 'Group Length' element is optional in DICOM
+ * - but un-updated odd groups lengthes can causes pb
+ * (xmedcon breaker)
*
* if ( (filetype == ImplicitVR) || (filetype == ExplicitVR) )
* UpdateGroupLength(false,filetype);
* UpdateGroupLength(true,ACR);
*/
- gdcmElementSet::Write(fp,filetype);
+ gdcmElementSet::Write(fp,filetype); // This one is recursive
- // return true;
}
/**
*/
gdcmValEntry * gdcmDocument::ReplaceOrCreateByNumber(
- std::string Value,
- guint16 Group,
- guint16 Elem )
+ std::string value,
+ uint16_t group,
+ uint16_t elem )
{
- gdcmDocEntry* CurrentEntry;
- gdcmValEntry* ValEntry;
+ gdcmValEntry* valEntry;
- CurrentEntry = GetDocEntryByNumber( Group, Elem);
- if (!CurrentEntry)
+ gdcmDocEntry* currentEntry = GetDocEntryByNumber( group, elem);
+ if (!currentEntry)
{
// The entry wasn't present and we simply create the required ValEntry:
- CurrentEntry = NewDocEntryByNumber(Group, Elem);
- if (!CurrentEntry)
+ currentEntry = NewDocEntryByNumber(group, elem);
+ if (!currentEntry)
{
dbg.Verbose(0, "gdcmDocument::ReplaceOrCreateByNumber: call to"
" NewDocEntryByNumber failed.");
return NULL;
}
- ValEntry = new gdcmValEntry(CurrentEntry);
- if ( !AddEntry(ValEntry))
+ valEntry = new gdcmValEntry(currentEntry);
+ if ( !AddEntry(valEntry))
{
dbg.Verbose(0, "gdcmDocument::ReplaceOrCreateByNumber: AddEntry"
" failed allthough this is a creation.");
}
else
{
- ValEntry = dynamic_cast< gdcmValEntry* >(CurrentEntry);
- if ( !ValEntry )
+ valEntry = dynamic_cast< gdcmValEntry* >(currentEntry);
+ if ( !valEntry )
{
// We need to promote the gdcmDocEntry to a gdcmValEntry:
- ValEntry = new gdcmValEntry(CurrentEntry);
- if (!RemoveEntry(CurrentEntry))
+ valEntry = new gdcmValEntry(currentEntry);
+ if (!RemoveEntry(currentEntry))
{
dbg.Verbose(0, "gdcmDocument::ReplaceOrCreateByNumber: removal"
" of previous DocEntry failed.");
return NULL;
}
- if ( !AddEntry(ValEntry))
+ if ( !AddEntry(valEntry))
{
dbg.Verbose(0, "gdcmDocument::ReplaceOrCreateByNumber: adding"
" promoted ValEntry failed.");
}
}
- SetEntryByNumber(Value, Group, Elem);
+ SetEntryByNumber(value, group, elem);
- return ValEntry;
+ return valEntry;
}
/*
gdcmBinEntry * gdcmDocument::ReplaceOrCreateByNumber(
void *voidArea,
int lgth,
- guint16 Group,
- guint16 Elem)
+ uint16_t group,
+ uint16_t elem)
{
- gdcmDocEntry* a;
gdcmBinEntry* b = 0;
- a = GetDocEntryByNumber( Group, Elem);
- if (a == NULL) {
- a =NewBinEntryByNumber(Group, Elem);
- if (a == NULL)
- return NULL;
+ gdcmDocEntry* a = GetDocEntryByNumber( group, elem);
+ if (!a)
+ {
+ a = NewBinEntryByNumber(group, elem);
+ if (!a)
+ {
+ return 0;
+ }
b = new gdcmBinEntry(a);
AddEntry(b);
+ b->SetVoidArea(voidArea);
}
- SetEntryByNumber(voidArea, lgth, Group, Elem);
- b->SetVoidArea(voidArea);
+ SetEntryByNumber(voidArea, lgth, group, elem);
+ //b->SetVoidArea(voidArea); //what if b == 0 !!
return b;
}
-
-
/**
* \brief Set a new value if the invoked element exists
* Seems to be useless !!!
* @param Elem element number of the Entry
* \return boolean
*/
-bool gdcmDocument::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 Elem )
+bool gdcmDocument::ReplaceIfExistByNumber(const char* value, uint16_t group,
+ uint16_t elem )
{
- std::string v = Value;
- SetEntryByNumber(v, Group, Elem);
+ std::string v = value;
+ SetEntryByNumber(v, group, elem);
return true;
}
* @param element Element number of the searched Dicom Element
* @return number of occurences
*/
-int gdcmDocument::CheckIfEntryExistByNumber(guint16 group, guint16 element ) {
+int gdcmDocument::CheckIfEntryExistByNumber(uint16_t group, uint16_t element )
+{
std::string key = gdcmDictEntry::TranslateToKey(group, element );
return tagHT.count(key);
}
* @return Corresponding element value when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
-std::string gdcmDocument::GetEntryByName(std::string tagName) {
+std::string gdcmDocument::GetEntryByName(TagName tagName)
+{
gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName);
- if( dictEntry == NULL)
+ if( !dictEntry )
+ {
return GDCM_UNFOUND;
+ }
return GetEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement());
}
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
-std::string gdcmDocument::GetEntryVRByName(TagName tagName) {
+std::string gdcmDocument::GetEntryVRByName(TagName tagName)
+{
gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName);
if( dictEntry == NULL)
return GDCM_UNFOUND;
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
-std::string gdcmDocument::GetEntryByNumber(guint16 group, guint16 element){
- TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+std::string gdcmDocument::GetEntryByNumber(uint16_t group, uint16_t element)
+{
+ gdcmTagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ /// \todo use map methods, instead of multimap JPR
if ( ! tagHT.count(key))
return GDCM_UNFOUND;
return ((gdcmValEntry *)tagHT.find(key)->second)->GetValue();
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
-std::string gdcmDocument::GetEntryVRByNumber(guint16 group, guint16 element) {
+std::string gdcmDocument::GetEntryVRByNumber(uint16_t group, uint16_t element)
+{
gdcmDocEntry* elem = GetDocEntryByNumber(group, element);
if ( !elem )
return GDCM_UNFOUND;
* @param element Element number of the searched tag.
* @return Corresponding element length; -2 if not found
*/
-int gdcmDocument::GetEntryLengthByNumber(guint16 group, guint16 element) {
+int gdcmDocument::GetEntryLengthByNumber(uint16_t group, uint16_t element)
+{
gdcmDocEntry* elem = GetDocEntryByNumber(group, element);
if ( !elem )
return -2;
* @param tagName name of the searched Dicom Element.
* @return true when found
*/
-bool gdcmDocument::SetEntryByName(std::string content,std::string tagName) {
+bool gdcmDocument::SetEntryByName(std::string content,std::string tagName)
+{
gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName);
if( dictEntry == NULL)
return false;
* @param element element number of the Dicom Element to modify
*/
bool gdcmDocument::SetEntryByNumber(std::string content,
- guint16 group,
- guint16 element)
+ uint16_t group,
+ uint16_t element)
{
gdcmValEntry* ValEntry = GetValEntryByNumber(group, element);
if (!ValEntry)
" ValEntry (try promotion first).");
return false;
}
-
// Non even content must be padded with a space (020H).
- if((content.length())%2)
+ if((content.length())%2) {
content = content + '\0';
-
+ }
ValEntry->SetValue(content);
// Integers have a special treatement for their length:
- VRKey vr = ValEntry->GetVR();
+ gdcmVRKey vr = ValEntry->GetVR();
if( (vr == "US") || (vr == "SS") )
ValEntry->SetLength(2);
else if( (vr == "UL") || (vr == "SL") )
* through it's (group, element) and modifies it's content with
* the given value.
* @param content new value (void *) to substitute with
+ * @param lgth new value length
* @param group group number of the Dicom Element to modify
* @param element element number of the Dicom Element to modify
*/
bool gdcmDocument::SetEntryByNumber(void *content,
- int lgth,
- guint16 group,
- guint16 element)
+ int lgth,
+ uint16_t group,
+ uint16_t element)
{
(void)lgth; //not used
- TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ gdcmTagKey key = gdcmDictEntry::TranslateToKey(group, element);
if ( ! tagHT.count(key))
return false;
-/* Hope Binray field length is never wrong
+/* Hope Binaray field length is *never* wrong
if(lgth%2) // Non even length are padded with a space (020H).
{
lgth++;
* @param element element number of the Entry to modify
* @return true on success, false otherwise.
*/
-bool gdcmDocument::SetEntryLengthByNumber(guint32 l,
- guint16 group,
- guint16 element)
+bool gdcmDocument::SetEntryLengthByNumber(uint32_t l,
+ uint16_t group,
+ uint16_t element)
{
- TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ /// \todo use map methods, instead of multimap JPR
+ gdcmTagKey key = gdcmDictEntry::TranslateToKey(group, element);
if ( ! tagHT.count(key))
return false;
if (l%2) l++; // length must be even
* @param Elem element number of the Entry
* @return File Offset of the Element Value
*/
-size_t gdcmDocument::GetEntryOffsetByNumber(guint16 Group, guint16 Elem)
+size_t gdcmDocument::GetEntryOffsetByNumber(uint16_t Group, uint16_t Elem)
{
gdcmDocEntry* Entry = GetDocEntryByNumber(Group, Elem);
if (!Entry)
* @param Elem element number of the Entry
* @return Pointer to the 'non string' area
*/
-void * gdcmDocument::GetEntryVoidAreaByNumber(guint16 Group, guint16 Elem)
+void * gdcmDocument::GetEntryVoidAreaByNumber(uint16_t Group, uint16_t Elem)
{
gdcmDocEntry* Entry = GetDocEntryByNumber(Group, Elem);
if (!Entry)
* @param Group group number of the Entry
* @param Elem element number of the Entry
*/
-void *gdcmDocument::LoadEntryVoidArea(guint16 Group, guint16 Elem)
+void *gdcmDocument::LoadEntryVoidArea(uint16_t Group, uint16_t Elem)
{
gdcmDocEntry * Element= GetDocEntryByNumber(Group, Elem);
if ( !Element )
dbg.Verbose(0, "gdcmDocument::LoadEntryVoidArea cannot allocate a");
return NULL;
}
- SetEntryVoidAreaByNumber(a, Group, Elem);
- /// \todo check the result
size_t l2 = fread(a, 1, l ,fp);
if(l != l2)
{
delete[] a;
return NULL;
}
+ /// \todo Drop any allready existing void area! JPR
+ SetEntryVoidAreaByNumber(a, Group, Elem);
return a;
}
/**
* @return
*/
bool gdcmDocument::SetEntryVoidAreaByNumber(void * area,
- guint16 group,
- guint16 element)
+ uint16_t group,
+ uint16_t element)
{
- TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ gdcmTagKey key = gdcmDictEntry::TranslateToKey(group, element);
if ( ! tagHT.count(key))
return false;
// This was for multimap ?
* \brief Update the entries with the shadow dictionary.
* Only non even entries are analyzed
*/
-void gdcmDocument::UpdateShaEntries(void) {
+void gdcmDocument::UpdateShaEntries() {
//gdcmDictEntry *entry;
std::string vr;
* @return Corresponding Dicom Element when it exists, and NULL
* otherwise.
*/
- gdcmDocEntry *gdcmDocument::GetDocEntryByName(std::string tagName) {
+gdcmDocEntry* gdcmDocument::GetDocEntryByName(std::string tagName)
+{
gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName);
if( dictEntry == NULL)
return NULL;
* @param element Element number of the searched Dicom Element
* @return
*/
-gdcmDocEntry* gdcmDocument::GetDocEntryByNumber(guint16 group, guint16 element)
+gdcmDocEntry* gdcmDocument::GetDocEntryByNumber(uint16_t group,
+ uint16_t element)
{
- TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ gdcmTagKey key = gdcmDictEntry::TranslateToKey(group, element);
if ( ! tagHT.count(key))
return NULL;
return tagHT.find(key)->second;
* ValEntry.
* @return When present, the corresponding ValEntry.
*/
-gdcmValEntry* gdcmDocument::GetValEntryByNumber(guint16 group, guint16 element)
+gdcmValEntry* gdcmDocument::GetValEntryByNumber(uint16_t group,
+ uint16_t element)
{
gdcmDocEntry* CurrentEntry = GetDocEntryByNumber(group, element);
if (! CurrentEntry)
* @param entry Header Entry whose value shall be loaded.
* @return
*/
-void gdcmDocument::LoadDocEntrySafe(gdcmDocEntry * entry) {
+void gdcmDocument::LoadDocEntrySafe(gdcmDocEntry * entry)
+{
long PositionOnEntry = ftell(fp);
LoadDocEntry(entry);
fseek(fp, PositionOnEntry, SEEK_SET);
* processor order.
* @return The properly swaped 32 bits integer.
*/
-guint32 gdcmDocument::SwapLong(guint32 a) {
+uint32_t gdcmDocument::SwapLong(uint32_t a)
+{
switch (sw) {
case 0 :
break;
* processor order.
* @return The properly unswaped 32 bits integer.
*/
-guint32 gdcmDocument::UnswapLong(guint32 a) {
+uint32_t gdcmDocument::UnswapLong(uint32_t a)
+{
return SwapLong(a);
}
* \brief Swaps the bytes so they agree with the processor order
* @return The properly swaped 16 bits integer.
*/
-guint16 gdcmDocument::SwapShort(guint16 a) {
+uint16_t gdcmDocument::SwapShort(uint16_t a)
+{
if ( (sw==4321) || (sw==2143) )
a =(((a<<8) & 0x0ff00) | ((a>>8)&0x00ff));
return a;
* \brief Unswaps the bytes so they agree with the processor order
* @return The properly unswaped 16 bits integer.
*/
-guint16 gdcmDocument::UnswapShort(guint16 a) {
+uint16_t gdcmDocument::UnswapShort(uint16_t a)
+{
return SwapShort(a);
}
* @return length of the parsed set.
*/
-long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode) {
-
+long gdcmDocument::ParseDES(gdcmDocEntrySet *set,
+ long offset,
+ long l_max,
+ bool delim_mode)
+{
gdcmDocEntry *NewDocEntry = (gdcmDocEntry *)0;
gdcmValEntry *NewValEntry = (gdcmValEntry *)0;
gdcmBinEntry *bn;
gdcmSeqEntry *sq;
- VRKey vr;
+ gdcmVRKey vr;
unsigned long l = 0;
int depth;
* the value specified with gdcmDocument::SetMaxSizeLoadEntry()
* @param Entry Header Entry (Dicom Element) to be dealt with
*/
-void gdcmDocument::LoadDocEntry(gdcmDocEntry *Entry)
+void gdcmDocument::LoadDocEntry(gdcmDocEntry* Entry)
{
size_t item_read;
- guint16 group = Entry->GetGroup();
- std::string vr= Entry->GetVR();
- guint32 length = Entry->GetLength();
+ uint16_t group = Entry->GetGroup();
+ std::string vr = Entry->GetVR();
+ uint32_t length = Entry->GetLength();
fseek(fp, (long)Entry->GetOffset(), SEEK_SET);
// (fffe e000) tells us an Element is beginning
// (fffe e00d) tells us an Element just ended
// (fffe e0dd) tells us the current SeQuence just ended
- if( group == 0xfffe ) {
+ if( group == 0xfffe )
+ {
// NO more value field for SQ !
return;
}
// When the length is zero things are easy:
- if ( length == 0 ) {
+ if ( length == 0 )
+ {
((gdcmValEntry *)Entry)->SetValue("");
return;
}
// the element content and it's length.
std::ostringstream s;
- if (length > MaxSizeLoadEntry) {
+ if (length > MaxSizeLoadEntry)
+ {
if (gdcmBinEntry* BinEntryPtr = dynamic_cast< gdcmBinEntry* >(Entry) )
{
s << "gdcm::NotLoaded (BinEntry)";
BinEntryPtr->SetValue(s.str());
}
// to be sure we are at the end of the value ...
- fseek(fp,(long)Entry->GetOffset()+(long)Entry->GetLength(),SEEK_SET);
+ fseek(fp, (long)Entry->GetOffset()+(long)Entry->GetLength(), SEEK_SET);
return;
// Be carefull : a BinEntry IS_A ValEntry ...
if (gdcmValEntry* ValEntryPtr = dynamic_cast< gdcmValEntry* >(Entry) )
}
// When we find a BinEntry not very much can be done :
- if (gdcmBinEntry* BinEntryPtr = dynamic_cast< gdcmBinEntry* >(Entry) ) {
+ if (gdcmBinEntry* BinEntryPtr = dynamic_cast< gdcmBinEntry* >(Entry) )
+ {
LoadEntryVoidArea(BinEntryPtr);
s << "gdcm::Loaded (BinEntry)";
BinEntryPtr->SetValue(s.str());
return;
}
-
- // Any compacter code suggested (?)
- if ( IsDocEntryAnInteger(Entry) ) {
- guint32 NewInt;
+ /// \todo Any compacter code suggested (?)
+ if ( IsDocEntryAnInteger(Entry) )
+ {
+ uint32_t NewInt;
std::ostringstream s;
int nbInt;
- // When short integer(s) are expected, read and convert the following
- // n *two characters properly i.e. as short integers as opposed to strings.
- // Elements with Value Multiplicity > 1
- // contain a set of integers (not a single one)
- if (vr == "US" || vr == "SS") {
+ // When short integer(s) are expected, read and convert the following
+ // n *two characters properly i.e. consider them as short integers as
+ // opposed to strings.
+ // Elements with Value Multiplicity > 1
+ // contain a set of integers (not a single one)
+ if (vr == "US" || vr == "SS")
+ {
nbInt = length / 2;
NewInt = ReadInt16();
s << NewInt;
- if (nbInt > 1){
- for (int i=1; i < nbInt; i++) {
+ if (nbInt > 1)
+ {
+ for (int i=1; i < nbInt; i++)
+ {
s << '\\';
NewInt = ReadInt16();
s << NewInt;
}
}
}
- // When integer(s) are expected, read and convert the following
- // n * four characters properly i.e. as integers as opposed to strings.
- // Elements with Value Multiplicity > 1
- // contain a set of integers (not a single one)
- else if (vr == "UL" || vr == "SL") {
+ // See above comment on multiple integers (mutatis mutandis).
+ else if (vr == "UL" || vr == "SL")
+ {
nbInt = length / 4;
NewInt = ReadInt32();
s << NewInt;
- if (nbInt > 1) {
- for (int i=1; i < nbInt; i++) {
+ if (nbInt > 1)
+ {
+ for (int i=1; i < nbInt; i++)
+ {
s << '\\';
NewInt = ReadInt32();
s << NewInt;
// We need an additional byte for storing \0 that is not on disk
std::string NewValue(length,0);
item_read = fread(&(NewValue[0]), (size_t)length, (size_t)1, fp);
- if (gdcmValEntry* ValEntry = dynamic_cast< gdcmValEntry* >(Entry) ) {
- if ( item_read != 1 ) {
- dbg.Verbose(1, "gdcmDocument::LoadElementValue","unread element value");
+ if (gdcmValEntry* ValEntry = dynamic_cast< gdcmValEntry* >(Entry) )
+ {
+ if ( item_read != 1 )
+ {
+ dbg.Verbose(1, "gdcmDocument::LoadDocEntry",
+ "unread element value");
ValEntry->SetValue("gdcm::UnRead");
return;
}
ValEntry->SetValue(NewValue.c_str());
else
ValEntry->SetValue(NewValue);
- } else {
- // fusible
- std::cout << "Should have a ValEntry, here !" << std::endl;
}
-
+ else
+ {
+ dbg.Error(true, "gdcmDocument::LoadDocEntry"
+ "Should have a ValEntry, here !");
+ }
}
* \brief Find the value Length of the passed Header Entry
* @param Entry Header Entry whose length of the value shall be loaded.
*/
- void gdcmDocument::FindDocEntryLength (gdcmDocEntry *Entry) {
- guint16 element = Entry->GetElement();
- //guint16 group = Entry->GetGroup(); //FIXME
+void gdcmDocument::FindDocEntryLength (gdcmDocEntry *Entry)
+{
+ uint16_t element = Entry->GetElement();
std::string vr = Entry->GetVR();
- guint16 length16;
+ uint16_t length16;
if ( (Filetype == gdcmExplicitVR) && (! Entry->IsImplicitVR()) )
// 7.1.2 Data element structure with explicit vr p27) must be
// skipped before proceeding on reading the length on 4 bytes.
fseek(fp, 2L, SEEK_CUR);
- guint32 length32 = ReadInt32();
+ uint32_t length32 = ReadInt32();
if ( (vr == "OB") && (length32 == 0xffffffff) )
{
- Entry->SetLength(FindDocEntryLengthOB());
+ uint32_t LengthOB = FindDocEntryLengthOB();
+ if ( errno == 1 )
+ {
+ // Computing the length failed (this happens with broken
+ // files like gdcm-JPEG-LossLess3a.dcm). We still have a
+ // chance to get the pixels by deciding the element goes
+ // until the end of the file. Hence we artificially fix the
+ // the length and proceed.
+ long CurrentPosition = ftell(fp);
+ fseek(fp,0L,SEEK_END);
+ long LengthUntilEOF = ftell(fp) - CurrentPosition;
+ fseek(fp, CurrentPosition, SEEK_SET);
+ Entry->SetLength(LengthUntilEOF);
+ errno = 0;
+ return;
+ }
+ Entry->SetLength(LengthOB);
return;
}
FixDocEntryFoundLength(Entry, length32);
SwitchSwapToBigEndian();
// Restore the unproperly loaded values i.e. the group, the element
// and the dictionary entry depending on them.
- guint16 CorrectGroup = SwapShort(Entry->GetGroup());
- guint16 CorrectElem = SwapShort(Entry->GetElement());
+ uint16_t CorrectGroup = SwapShort(Entry->GetGroup());
+ uint16_t CorrectElem = SwapShort(Entry->GetElement());
gdcmDictEntry * NewTag = GetDictEntryByNumber(CorrectGroup,
CorrectElem);
if (!NewTag)
// Length16= 0xffff means that we deal with
// 'Unknown Length' Sequence
}
- FixDocEntryFoundLength(Entry, (guint32)length16);
+ FixDocEntryFoundLength(Entry, (uint32_t)length16);
return;
}
else
* @return false if the VR is incorrect of if the VR isn't referenced
* otherwise, it returns true
*/
-bool gdcmDocument::CheckDocEntryVR(gdcmDocEntry *Entry, VRKey vr)
+bool gdcmDocument::CheckDocEntryVR(gdcmDocEntry *Entry, gdcmVRKey vr)
{
char msg[100]; // for sprintf
bool RealExplicit = true;
{
std::string val=((gdcmValEntry *)Entry)->GetValue();
std::string vr=Entry->GetVR();
- guint32 length = Entry->GetLength();
+ uint32_t length = Entry->GetLength();
std::ostringstream s;
int nbInt;
if (vr == "US" || vr == "SS")
{
- guint16 NewInt16;
+ uint16_t NewInt16;
nbInt = length / 2;
for (int i=0; i < nbInt; i++)
// contain a set of integers (not a single one)
else if (vr == "UL" || vr == "SL")
{
- guint32 NewInt32;
+ uint32_t NewInt32;
nbInt = length / 4;
for (int i=0; i < nbInt; i++)
if (vr == "US" || vr == "SS")
{
- guint16 NewInt16;
+ uint16_t NewInt16;
tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
Tokenize (((gdcmValEntry *)Entry)->GetValue(), tokens, "\\");
}
if (vr == "UL" || vr == "SL")
{
- guint32 NewInt32;
+ uint32_t NewInt32;
tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
Tokenize (((gdcmValEntry *)Entry)->GetValue(), tokens, "\\");
* applying some heuristics.
*/
void gdcmDocument::FixDocEntryFoundLength(gdcmDocEntry *Entry,
- guint32 FoundLength)
+ uint32_t FoundLength)
{
Entry->SetReadLength(FoundLength); // will be updated only if a bug is found
if ( FoundLength == 0xffffffff) {
FoundLength = 0;
}
- guint16 gr =Entry->GetGroup();
- guint16 el =Entry->GetElement();
+ uint16_t gr =Entry->GetGroup();
+ uint16_t el =Entry->GetElement();
if (FoundLength%2) {
std::ostringstream s;
* @return The result of the heuristical predicate.
*/
bool gdcmDocument::IsDocEntryAnInteger(gdcmDocEntry *Entry) {
- guint16 element = Entry->GetElement();
- guint16 group = Entry->GetGroup();
- std::string vr = Entry->GetVR();
- guint32 length = Entry->GetLength();
+ uint16_t element = Entry->GetElement();
+ uint16_t group = Entry->GetGroup();
+ std::string vr = Entry->GetVR();
+ uint32_t length = Entry->GetLength();
// When we have some semantics on the element we just read, and if we
// a priori know we are dealing with an integer, then we shall be
* @return
*/
- guint32 gdcmDocument::FindDocEntryLengthOB(void) {
+uint32_t gdcmDocument::FindDocEntryLengthOB() {
// See PS 3.5-2001, section A.4 p. 49 on encapsulation of encoded pixel data.
- guint16 g;
- guint16 n;
+ uint16_t g;
+ uint16_t n;
long PositionOnEntry = ftell(fp);
bool FoundSequenceDelimiter = false;
- guint32 TotalLength = 0;
- guint32 ItemLength;
+ uint32_t TotalLength = 0;
+ uint32_t ItemLength;
while ( ! FoundSequenceDelimiter)
{
n = ReadInt16();
if (errno == 1)
return 0;
- TotalLength += 4; // We even have to decount the group and element
+
+ // We have to decount the group and element we just read
+ TotalLength += 4;
- if ( g != 0xfffe && g!=0xb00c ) //for bogus header
+ if ( ( g != 0xfffe )
+ || ( ( n != 0xe0dd ) && ( n != 0xe000 ) ) )
{
- char msg[100]; // for sprintf. Sorry
- sprintf(msg,"wrong group (%04x) for an item sequence (%04x,%04x)\n",g, g,n);
- dbg.Verbose(1, "gdcmDocument::FindLengthOB: ",msg);
+ dbg.Verbose(1, "gdcmDocument::FindLengthOB: neither an Item tag "
+ "nor a Sequence delimiter tag.");
+ fseek(fp, PositionOnEntry, SEEK_SET);
errno = 1;
return 0;
}
- if ( n == 0xe0dd || ( g==0xb00c && n==0x0eb6 ) ) // for bogus header
+
+ if ( n == 0xe0dd )
FoundSequenceDelimiter = true;
- else if ( n != 0xe000 )
- {
- char msg[100]; // for sprintf. Sorry
- sprintf(msg,"wrong element (%04x) for an item sequence (%04x,%04x)\n",
- n, g,n);
- dbg.Verbose(1, "gdcmDocument::FindLengthOB: ",msg);
- errno = 1;
- return 0;
- }
+
ItemLength = ReadInt32();
- TotalLength += ItemLength + 4; // We add 4 bytes since we just read
- // the ItemLength with ReadInt32
+ // We add 4 bytes since we just read the ItemLength with ReadInt32
+ TotalLength += ItemLength + 4;
SkipBytes(ItemLength);
+
+ if ( FoundSequenceDelimiter )
+ break;
}
fseek(fp, PositionOnEntry, SEEK_SET);
return TotalLength;
* (swaps it depending on processor endianity)
* @return read value
*/
-guint16 gdcmDocument::ReadInt16() {
- guint16 g;
+uint16_t gdcmDocument::ReadInt16() {
+ uint16_t g;
size_t item_read;
item_read = fread (&g, (size_t)2,(size_t)1, fp);
if ( item_read != 1 ) {
* (swaps it depending on processor endianity)
* @return read value
*/
-guint32 gdcmDocument::ReadInt32() {
- guint32 g;
+uint32_t gdcmDocument::ReadInt32() {
+ uint32_t g;
size_t item_read;
item_read = fread (&g, (size_t)4,(size_t)1, fp);
if ( item_read != 1 ) {
* \warning NOT end user intended method !
* @return
*/
-void gdcmDocument::SkipBytes(guint32 NBytes) {
+void gdcmDocument::SkipBytes(uint32_t NBytes) {
//FIXME don't dump the returned value
(void)fseek(fp, (long)NBytes, SEEK_CUR);
}
* \brief Loads all the needed Dictionaries
* \warning NOT end user intended method !
*/
-void gdcmDocument::Initialise(void)
+void gdcmDocument::Initialise()
{
RefPubDict = gdcmGlobal::GetDicts()->GetDefaultPubDict();
RefShaDict = NULL;
// 0x00000004. Finding the swap code in then straigthforward. Trouble
// occurs when we can't find such group...
- guint32 x=4; // x : for ntohs
+ uint32_t x=4; // x : for ntohs
bool net2host; // true when HostByteOrder is the same as NetworkByteOrder
- guint32 s32;
- guint16 s16;
+ uint32_t s32;
+ uint16_t s16;
int lgrLue;
char *entCur;
// We assume the array of char we are considering contains the binary
// representation of a 32 bits integer. Hence the following dirty
// trick :
- s32 = *((guint32 *)(entCur));
+ s32 = *((uint32_t *)(entCur));
switch (s32) {
case 0x00040000 :
// the file IS NOT ACR-NEMA nor DICOM V3
// Find a trick to tell it the caller...
- s16 = *((guint16 *)(deb));
+ s16 = *((uint16_t *)(deb));
switch (s16) {
case 0x0002 :
* \brief Restore the unproperly loaded values i.e. the group, the element
* and the dictionary entry depending on them.
*/
-void gdcmDocument::SwitchSwapToBigEndian(void)
+void gdcmDocument::SwitchSwapToBigEndian()
{
dbg.Verbose(1, "gdcmDocument::SwitchSwapToBigEndian",
"Switching to BigEndian mode.");
{
if (NewSize < 0)
return;
- if ((guint32)NewSize >= (guint32)0xffffffff)
+ if ((uint32_t)NewSize >= (uint32_t)0xffffffff)
{
MaxSizeLoadEntry = 0xffffffff;
return;
{
if (NewSize < 0)
return;
- if ((guint32)NewSize >= (guint32)0xffffffff)
+ if ((uint32_t)NewSize >= (uint32_t)0xffffffff)
{
MaxSizePrintEntry = 0xffffffff;
return;
* gets the VR, gets the length, gets the offset value)
* @return On succes the newly created DocEntry, NULL on failure.
*/
-gdcmDocEntry *gdcmDocument::ReadNextDocEntry(void) {
- guint16 g,n;
+gdcmDocEntry *gdcmDocument::ReadNextDocEntry() {
+ uint16_t g = ReadInt16();
+ uint16_t n = ReadInt16();
gdcmDocEntry *NewEntry;
- g = ReadInt16();
- n = ReadInt16();
if (errno == 1)
// We reached the EOF (or an error occured) therefore
FindDocEntryVR(NewEntry);
FindDocEntryLength(NewEntry);
- if (errno == 1) {
+ if (errno == 1)
+ {
// Call it quits
delete NewEntry;
return NULL;
/**
- * \brief Generate a free TagKey i.e. a TagKey that is not present
+ * \brief Generate a free gdcmTagKey i.e. a gdcmTagKey that is not present
* in the TagHt dictionary.
* @param group The generated tag must belong to this group.
* @return The element of tag with given group which is fee.
*/
-guint32 gdcmDocument::GenerateFreeTagKeyInGroup(guint16 group)
+uint32_t gdcmDocument::GenerateFreeTagKeyInGroup(uint16_t group)
{
- for (guint32 elem = 0; elem < UINT32_MAX; elem++)
+ for (uint32_t elem = 0; elem < UINT32_MAX; elem++)
{
- TagKey key = gdcmDictEntry::TranslateToKey(group, elem);
+ gdcmTagKey key = gdcmDictEntry::TranslateToKey(group, elem);
if (tagHT.count(key) == 0)
return elem;
}
return UINT32_MAX;
}
-
/**
* \brief Assuming the internal file pointer \ref gdcmDocument::fp
- * is placed at the beginning of a tag (TestGroup, TestElement),
- * read the length associated to the Tag.
+ * is placed at the beginning of a tag check whether this
+ * tag is (TestGroup, TestElement).
* \warning On success the internal file pointer \ref gdcmDocument::fp
- * is modified to point after the tag and it's length.
+ * is modified to point after the tag.
* On failure (i.e. when the tag wasn't the expected tag
* (TestGroup, TestElement) the internal file pointer
* \ref gdcmDocument::fp is restored to it's original position.
* @param TestGroup The expected group of the tag.
* @param TestElement The expected Element of the tag.
- * @return On success returns the length associated to the tag. On failure
- * returns 0.
+ * @return True on success, false otherwise.
*/
-guint32 gdcmDocument::ReadTagLength(guint16 TestGroup, guint16 TestElement)
+bool gdcmDocument::ReadTag(uint16_t TestGroup, uint16_t TestElement)
{
- guint16 ItemTagGroup;
- guint16 ItemTagElement;
+ uint16_t ItemTagGroup;
+ uint16_t ItemTagElement;
long PositionOnEntry = ftell(fp);
long CurrentPosition = ftell(fp); // On debugging purposes
//// Read the Item Tag group and element, and make
- // sure they are respectively 0xfffe and 0xe000:
+ // sure they are what we expected:
ItemTagGroup = ReadInt16();
ItemTagElement = ReadInt16();
if ( (ItemTagGroup != TestGroup) || (ItemTagElement != TestElement ) )
dbg.Verbose(0, "gdcmDocument::ReadItemTagLength: wrong Item Tag found:");
dbg.Verbose(0, s.str().c_str());
fseek(fp, PositionOnEntry, SEEK_SET);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * \brief Assuming the internal file pointer \ref gdcmDocument::fp
+ * is placed at the beginning of a tag (TestGroup, TestElement),
+ * read the length associated to the Tag.
+ * \warning On success the internal file pointer \ref gdcmDocument::fp
+ * is modified to point after the tag and it's length.
+ * On failure (i.e. when the tag wasn't the expected tag
+ * (TestGroup, TestElement) the internal file pointer
+ * \ref gdcmDocument::fp is restored to it's original position.
+ * @param TestGroup The expected group of the tag.
+ * @param TestElement The expected Element of the tag.
+ * @return On success returns the length associated to the tag. On failure
+ * returns 0.
+ */
+uint32_t gdcmDocument::ReadTagLength(uint16_t TestGroup, uint16_t TestElement)
+{
+ long PositionOnEntry = ftell(fp);
+ (void)PositionOnEntry;
+
+ if ( !ReadTag(TestGroup, TestElement) )
+ {
return 0;
}
//// Then read the associated Item Length
- CurrentPosition=ftell(fp);
- guint32 ItemLength;
+ long CurrentPosition = ftell(fp);
+ uint32_t ItemLength;
ItemLength = ReadInt32();
{
std::ostringstream s;
return ItemLength;
}
-/**
- * \brief Read the length of an exptected Item tag i.e. (0xfffe, 0xe000).
- * \sa \ref gdcmDocument::ReadTagLength
- * \warning See warning of \ref gdcmDocument::ReadTagLength
- * @return On success returns the length associated to the item tag.
- * On failure returns 0.
- */
-guint32 gdcmDocument::ReadItemTagLength(void)
-{
- return ReadTagLength(0xfffe, 0xe000);
-}
-
-/**
- * \brief Read the length of an expected Sequence Delimiter tag i.e.
- * (0xfffe, 0xe0dd).
- * \sa \ref gdcmDocument::ReadTagLength
- * \warning See warning of \ref gdcmDocument::ReadTagLength
- * @return On success returns the length associated to the Sequence
- * Delimiter tag. On failure returns 0.
- */
-guint32 gdcmDocument::ReadSequenceDelimiterTagLength(void)
-{
- return ReadTagLength(0xfffe, 0xe0dd);
-}
-
-
/**
* \brief Parse pixel data from disk for multi-fragment Jpeg/Rle files
* No other way so 'skip' the Data
*
*/
-
-void gdcmDocument::Parse7FE0 (void)
+void gdcmDocument::Parse7FE0 ()
{
gdcmDocEntry* Element = GetDocEntryByNumber(0x0002, 0x0010);
if ( !Element )
|| IsExplicitVRBigEndianTransferSyntax() /// \todo 1.2.2 ??? A verifier !
|| IsDeflatedExplicitVRLittleEndianTransferSyntax() )
return;
-
+
// ---------------- for Parsing : Position on begining of Jpeg/RLE Pixels
//// Read the Basic Offset Table Item Tag length...
- guint32 ItemLength = ReadItemTagLength();
+ uint32_t ItemLength = ReadTagLength(0xfffe, 0xe000);
//// ... and then read length[s] itself[themselves]. We don't use
// the values read (BTW what is the purpous of those lengths ?)
char * BasicOffsetTableItemValue = new char[ItemLength + 1];
fread(BasicOffsetTableItemValue, ItemLength, 1, fp);
for (unsigned int i=0; i < ItemLength; i += 4){
- guint32 IndividualLength;
- IndividualLength = str2num(&BasicOffsetTableItemValue[i],guint32);
+ uint32_t IndividualLength;
+ IndividualLength = str2num(&BasicOffsetTableItemValue[i],uint32_t);
std::ostringstream s;
s << " Read one length: ";
s << std::hex << IndividualLength << std::endl;
// JPEG Image
//// We then skip (not reading them) all the fragments of images:
- while ( (ItemLength = ReadItemTagLength()) )
+ while ( (ItemLength = ReadTagLength(0xfffe, 0xe000)) )
{
SkipBytes(ItemLength);
}
-
}
else
{
long ftellRes;
long RleSegmentLength[15], fragmentLength;
- // while 'Sequence Delimiter Item' (fffe,e0dd) not found
- while ( (fragmentLength = ReadSequenceDelimiterTagLength()) )
+ // While we find some items:
+ while ( (fragmentLength = ReadTagLength(0xfffe, 0xe000)) )
{
// Parse fragments of the current Fragment (Frame)
//------------------ scanning (not reading) fragment pixels
- guint32 nbRleSegments = ReadInt32();
- printf(" Nb of RLE Segments : %d\n",nbRleSegments);
+ uint32_t nbRleSegments = ReadInt32();
//// Reading RLE Segments Offset Table
- guint32 RleSegmentOffsetTable[15];
+ uint32_t RleSegmentOffsetTable[15];
for(int k=1; k<=15; k++) {
ftellRes=ftell(fp);
RleSegmentOffsetTable[k] = ReadInt32();
- printf(" at : %x Offset Segment %d : %d (%x)\n",
- (unsigned)ftellRes,k,RleSegmentOffsetTable[k],
- RleSegmentOffsetTable[k]);
}
// skipping (not reading) RLE Segments
RleSegmentLength[k]= RleSegmentOffsetTable[k+1]
- RleSegmentOffsetTable[k];
ftellRes=ftell(fp);
- printf (" Segment %d : Length = %d x(%x) Start at %x\n",
- k,(unsigned)RleSegmentLength[k],
- (unsigned)RleSegmentLength[k], (unsigned)ftellRes);
SkipBytes(RleSegmentLength[k]);
}
}
RleSegmentLength[nbRleSegments]= fragmentLength
- RleSegmentOffsetTable[nbRleSegments];
ftellRes=ftell(fp);
- printf (" Segment %d : Length = %d x(%x) Start at %x\n",
- nbRleSegments,(unsigned)RleSegmentLength[nbRleSegments],
- (unsigned)RleSegmentLength[nbRleSegments],(unsigned)ftellRes);
SkipBytes(RleSegmentLength[nbRleSegments]);
}
+
+ // Make sure that at the end of the item we encounter a 'Sequence
+ // Delimiter Item':
+ if ( ! ReadTag(0xfffe, 0xe0dd) )
+ {
+ dbg.Verbose(0, "gdcmDocument::Parse7FE0: no sequence delimiter item");
+ dbg.Verbose(0, " at end of RLE item sequence");
+ }
}
}