//-----------------------------------------------------------------------------
#include "gdcmParser.h"
#include "gdcmUtil.h"
+#include <errno.h>
// For nthos:
#ifdef _MSC_VER
# else
# include <sstream>
#endif
+# include <iomanip>
+
+#define UI1_2_840_10008_1_2 "1.2.840.10008.1.2"
+#define UI1_2_840_10008_1_2_1 "1.2.840.10008.1.2.1"
+#define UI1_2_840_10008_1_2_2 "1.2.840.10008.1.2.2"
+#define UI1_2_840_10008_1_2_1_99 "1.2.840.10008.1.2.1.99"
//-----------------------------------------------------------------------------
// Refer to gdcmParser::CheckSwap()
*/
gdcmParser::~gdcmParser (void)
{
- dicom_vr = (gdcmVR*)0;
- Dicts = (gdcmDictSet*)0;
- RefPubDict = (gdcmDict*)0;
- RefShaDict = (gdcmDict*)0;
+ RefPubDict = NULL;
+ RefShaDict = NULL;
}
//-----------------------------------------------------------------------------
* both from the H Table and the chained list
* @return
*/
-void gdcmParser::PrintPubEntry(std::ostream & os)
+void gdcmParser::PrintEntry(std::ostream & os)
{
std::ostringstream s;
-// guint32 lgth;
-// char greltag[10]; //group element tag
-
s << "------------ using listEntries ----------------" << std::endl;
-
-// char st[20];
for (ListTag::iterator i = listEntries.begin();
i != listEntries.end();
++i)
//-----------------------------------------------------------------------------
// Public
+/**
+ * \ingroup gdcmParser
+ * \brief Get the public dictionary used
+ */
+gdcmDict *gdcmParser::GetPubDict(void)
+{
+ return(RefPubDict);
+}
+
+/**
+ * \ingroup gdcmParser
+ * \brief Get the shadow dictionary used
+ */
+gdcmDict *gdcmParser::GetShaDict(void)
+{
+ return(RefShaDict);
+}
+
+/**
+ * \ingroup gdcmParser
+ * \brief Set the shadow dictionary used
+ * \param dict dictionary to use in shadow
+ */
+bool gdcmParser::SetShaDict(gdcmDict *dict)
+{
+ RefShaDict=dict;
+ return(!RefShaDict);
+}
+
+/**
+ * \ingroup gdcmParser
+ * \brief Set the shadow dictionary used
+ * \param dictName name of the dictionary to use in shadow
+ */
+bool gdcmParser::SetShaDict(DictKey dictName)
+{
+ RefShaDict=gdcmGlobal::GetDicts()->GetDict(dictName);
+ return(!RefShaDict);
+}
+
/**
* \ingroup gdcmParser
* \brief This predicate, based on hopefully reasonable heuristics,
*/
bool gdcmParser::IsReadable(void)
{
- std::string res = GetEntryByNumber(0x0028, 0x0005);
- if ( res != GDCM_UNFOUND && atoi(res.c_str()) > 4 )
- {
- return false; // Image Dimensions
- }
+ if(filetype==Unknown)
+ return(false);
- if ( !GetHeaderEntryByNumber(0x0028, 0x0100) )
- return false; // "Bits Allocated"
- if ( !GetHeaderEntryByNumber(0x0028, 0x0101) )
- return false; // "Bits Stored"
- if ( !GetHeaderEntryByNumber(0x0028, 0x0102) )
- return false; // "High Bit"
- if ( !GetHeaderEntryByNumber(0x0028, 0x0103) )
- return false; // "Pixel Representation"
- return true;
+ if(listEntries.size()<=0)
+ return(false);
+
+ return(true);
}
/**
LoadHeaderEntrySafe(Element);
std::string Transfer = Element->GetValue();
- if ( Transfer == "1.2.840.10008.1.2" )
+ if ( Transfer == UI1_2_840_10008_1_2 )
return true;
return false;
}
LoadHeaderEntrySafe(Element);
std::string Transfer = Element->GetValue();
- if ( Transfer == "1.2.840.10008.1.2.1" )
+ if ( Transfer == UI1_2_840_10008_1_2_1 )
return true;
return false;
}
LoadHeaderEntrySafe(Element);
std::string Transfer = Element->GetValue();
- if ( Transfer == "1.2.840.10008.1.2.1.99" )
+ if ( Transfer == UI1_2_840_10008_1_2_1_99 )
return true;
return false;
}
LoadHeaderEntrySafe(Element);
std::string Transfer = Element->GetValue();
- if ( Transfer == "1.2.840.10008.1.2.2" ) //1.2.2 ??? A verifier !
+ if ( Transfer == UI1_2_840_10008_1_2_2 ) //1.2.2 ??? A verifier !
return true;
return false;
}
dbg.Verbose(0, "gdcmParser::gdcmParser not DICOM/ACR", filename.c_str());
}
else {
- std::cerr<<filename.c_str()<<std::endl;
dbg.Verbose(0, "gdcmParser::gdcmParser cannot open file", filename.c_str());
}
return(NULL);
return true;
}
-/**
- * \ingroup gdcmParser
- * \brief Parses the header of the file but WITHOUT loading element values.
- */
-void gdcmParser::Parse(bool exception_on_error) throw(gdcmFormatError)
-{
- gdcmHeaderEntry *newHeaderEntry = (gdcmHeaderEntry *)0;
-
- rewind(fp);
- CheckSwap();
- while ( (newHeaderEntry = ReadNextHeaderEntry()) )
- {
- SkipHeaderEntry(newHeaderEntry);
- AddHeaderEntry(newHeaderEntry);
- }
-}
-
/**
* \ingroup gdcmParser
* \brief
if (type == ImplicitVR)
{
- std::string implicitVRTransfertSyntax = "1.2.840.10008.1.2";
+ std::string implicitVRTransfertSyntax = UI1_2_840_10008_1_2;
ReplaceOrCreateByNumber(implicitVRTransfertSyntax,0x0002, 0x0010);
//FIXME Refer to standards on page 21, chapter 6.2 "Value representation":
if (type == ExplicitVR)
{
- std::string explicitVRTransfertSyntax = "1.2.840.10008.1.2.1";
+ std::string explicitVRTransfertSyntax = UI1_2_840_10008_1_2_1;
ReplaceOrCreateByNumber(explicitVRTransfertSyntax,0x0002, 0x0010);
//FIXME Refer to standards on page 21, chapter 6.2 "Value representation":
*/
std::string gdcmParser::GetEntryByName(std::string tagName)
{
- gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName);
+ gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName);
if( dictEntry == NULL)
return GDCM_UNFOUND;
*/
std::string gdcmParser::GetEntryVRByName(std::string tagName)
{
- gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName);
+ gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName);
if( dictEntry == NULL)
return GDCM_UNFOUND;
*/
bool gdcmParser::SetEntryByName(std::string content,std::string tagName)
{
- gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName);
+ gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName);
if( dictEntry == NULL)
return false;
return(SetEntryByNumber(content,dictEntry->GetGroup(),
dictEntry->GetElement()));
-/* TagKey key = gdcmDictEntry::TranslateToKey(dictEntry->GetGroup(),
- dictEntry->GetElement());
- if ( GetPubEntry().count(key) == 0 )
- return false;
-
- int l = content.length();
- if(l%2) // Odd length are padded with a space (020H).
- {
- l++;
- content = content + '\0';
- }
-
- //tagHt[key]->SetValue(content);
- gdcmHeaderEntry * a;
- IterHT p;
- TagHeaderEntryHT::iterator p2;
- // DO NOT remove the following lines : they explain how the stuff works
- //p= tagHt.equal_range(key); // get a pair of iterators first-last synonym
- //p2=p.first; // iterator on the first synonym
- //a=p2->second; // H Table target column (2-nd col)
- // or, easier :
- a = ((GetPubEntry().equal_range(key)).first)->second;
- a-> SetValue(content);
- std::string vr = a->GetVR();
-
- guint32 lgr;
- if( (vr == "US") || (vr == "SS") )
- lgr = 2;
- else if( (vr == "UL") || (vr == "SL") )
- lgr = 4;
- else
- lgr = l;
- a->SetLength(lgr);
- return true;*/
}
/**
* the given value.
* \warning Use with extreme caution.
* @param length new length to substitute with
- * @param group group of the ElVal to modify
- * @param element element of the ElVal to modify
+ * @param group group of the entry to modify
+ * @param element element of the Entry to modify
* @return 1 on success, 0 otherwise.
*/
bool gdcmParser::SetEntryLengthByNumber(guint32 length,
- guint16 group, guint16 element)
+ guint16 group, guint16 element)
{
TagKey key = gdcmDictEntry::TranslateToKey(group, element);
if ( ! tagHT.count(key))
return true;
}
+/**
+ * \ingroup gdcmParser
+ * \brief Update the entries with the shadow dictionary. Only odd entries are
+ * analized
+ */
+void gdcmParser::UpdateShaEntries(void)
+{
+ gdcmDictEntry *entry;
+ std::string vr;
+
+ for(ListTag::iterator it=listEntries.begin();
+ it!=listEntries.end();
+ ++it)
+ {
+ // Odd group => from public dictionary
+ if((*it)->GetGroup()%2==0)
+ continue;
+
+ // Peer group => search the corresponding dict entry
+ if(RefShaDict)
+ entry=RefShaDict->GetDictEntryByNumber((*it)->GetGroup(),(*it)->GetElement());
+ else
+ entry=NULL;
+
+ if((*it)->IsImplicitVR())
+ vr="Implicit";
+ else
+ vr=(*it)->GetVR();
+
+ (*it)->SetValue(GetHeaderEntryUnvalue(*it));
+ if(entry)
+ {
+ // Set the new entry and the new value
+ (*it)->SetDictEntry(entry);
+ CheckHeaderEntryVR(*it,vr);
+
+ (*it)->SetValue(GetHeaderEntryValue(*it));
+ }
+ else
+ {
+ // Remove precedent value transformation
+ (*it)->SetDictEntry(NewVirtualDictEntry((*it)->GetGroup(),(*it)->GetElement(),vr));
+ }
+ }
+}
+
/**
* \ingroup gdcmParser
* \brief Searches within the Header Entries for a Dicom Element of
*/
gdcmHeaderEntry *gdcmParser::GetHeaderEntryByName(std::string tagName)
{
- gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName);
+ gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName);
if( dictEntry == NULL)
return NULL;
return(a);
}
+/**
+ * \ingroup gdcmParser
+ * \brief Unswaps back the bytes of 4-byte long integer accordingly to
+ * processor order.
+ * @return The properly unswaped 32 bits integer.
+ */
+guint32 gdcmParser::UnswapLong(guint32 a)
+{
+ return (SwapLong(a));
+}
+
/**
* \ingroup gdcmParser
* \brief Swaps the bytes so they agree with the processor order
return (a);
}
+/**
+ * \ingroup gdcmParser
+ * \brief Unswaps the bytes so they agree with the processor order
+ * @return The properly unswaped 16 bits integer.
+ */
+guint16 gdcmParser::UnswapShort(guint16 a)
+{
+ return (SwapShort(a));
+}
+
//-----------------------------------------------------------------------------
// Private
+/**
+ * \ingroup gdcmParser
+ * \brief Parses the header of the file but WITHOUT loading element values.
+ */
+void gdcmParser::Parse(bool exception_on_error) throw(gdcmFormatError)
+{
+ gdcmHeaderEntry *newHeaderEntry = (gdcmHeaderEntry *)0;
+
+ rewind(fp);
+ CheckSwap();
+ while ( (newHeaderEntry = ReadNextHeaderEntry()) )
+ {
+ SkipHeaderEntry(newHeaderEntry);
+ AddHeaderEntry(newHeaderEntry);
+ }
+}
+
/**
* \ingroup gdcmParser
* \brief Loads the element values of all the Header Entries pointed in the
void gdcmParser::LoadHeaderEntries(void)
{
rewind(fp);
- for (ListTag::iterator i = GetPubListEntry().begin();
- i != GetPubListEntry().end();
+ for (ListTag::iterator i = GetListEntry().begin();
+ i != GetListEntry().end();
++i)
{
- LoadHeaderEntry(*i);
- }
+ LoadHeaderEntry(*i);
+ }
rewind(fp);
* \brief Loads the element content if it's length is not bigger
* than the value specified with
* gdcmParser::SetMaxSizeLoadEntry()
- * @param ElVal Header Entry (Dicom Element) to be dealt with
+ * @param Entry Header Entry (Dicom Element) to be dealt with
*/
-void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry * ElVal)
+void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry *Entry)
{
size_t item_read;
- guint16 group = ElVal->GetGroup();
- std::string vr= ElVal->GetVR();
- guint32 length = ElVal->GetLength();
+ guint16 group = Entry->GetGroup();
+ std::string vr= Entry->GetVR();
+ guint32 length = Entry->GetLength();
bool SkipLoad = false;
- fseek(fp, (long)ElVal->GetOffset(), SEEK_SET);
+ fseek(fp, (long)Entry->GetOffset(), SEEK_SET);
// the test was commented out to 'go inside' the SeQuences
// we don't any longer skip them !
if ( SkipLoad )
{
- ElVal->SetLength(0);
- ElVal->SetValue("gdcm::Skipped");
+ Entry->SetLength(0);
+ Entry->SetValue("gdcm::Skipped");
return;
}
// When the length is zero things are easy:
if ( length == 0 )
{
- ElVal->SetValue("");
+ Entry->SetValue("");
return;
}
{
std::ostringstream s;
s << "gdcm::NotLoaded.";
- s << " Address:" << (long)ElVal->GetOffset();
- s << " Length:" << ElVal->GetLength();
- s << " x(" << std::hex << ElVal->GetLength() << ")";
- ElVal->SetValue(s.str());
+ s << " Address:" << (long)Entry->GetOffset();
+ s << " Length:" << Entry->GetLength();
+ s << " x(" << std::hex << Entry->GetLength() << ")";
+ Entry->SetValue(s.str());
return;
}
// contain a set of integers (not a single one)
// Any compacter code suggested (?)
- if ( IsHeaderEntryAnInteger(ElVal) )
+ if ( IsHeaderEntryAnInteger(Entry) )
{
guint32 NewInt;
std::ostringstream s;
int nbInt;
- if (vr == "US" || vr == "SS")
+ if (vr == "US" || vr == "SS")
{
nbInt = length / 2;
NewInt = ReadInt16();
}
}
- }
+ }
else if (vr == "UL" || vr == "SL")
{
nbInt = length / 4;
s << NewInt;
}
}
- }
+ }
#ifdef GDCM_NO_ANSI_STRING_STREAM
s << std::ends; // to avoid oddities on Solaris
#endif //GDCM_NO_ANSI_STRING_STREAM
- ElVal->SetValue(s.str());
+ Entry->SetValue(s.str());
return;
}
// We need an additional byte for storing \0 that is not on disk
- char* NewValue = (char*)malloc(length+1);
- if( !NewValue)
- {
- dbg.Verbose(1, "LoadElementValue: Failed to allocate NewValue");
- return;
- }
- NewValue[length]= 0;
-
- item_read = fread(NewValue, (size_t)length, (size_t)1, fp);
+ std::string NewValue(length,0);
+ item_read = fread(&(NewValue[0]), (size_t)length, (size_t)1, fp);
if ( item_read != 1 )
{
- free(NewValue);
dbg.Verbose(1, "gdcmParser::LoadElementValue","unread element value");
- ElVal->SetValue("gdcm::UnRead");
+ Entry->SetValue("gdcm::UnRead");
return;
}
- ElVal->SetValue(NewValue);
- free(NewValue);
+
+ if( (vr == "UI") ) // Because of correspondance with the VR dic
+ Entry->SetValue(NewValue.c_str());
+ else
+ Entry->SetValue(NewValue);
}
/**
* \ when position to be taken care of
* @param newHeaderEntry
*/
-void gdcmParser::AddHeaderEntry(gdcmHeaderEntry * newHeaderEntry)
+void gdcmParser::AddHeaderEntry(gdcmHeaderEntry *newHeaderEntry)
{
tagHT.insert( PairHT( newHeaderEntry->GetKey(),newHeaderEntry) );
listEntries.push_back(newHeaderEntry);
/**
* \ingroup gdcmParser
* \brief
- * @param ElVal : Header Entry whose length of the value shall be loaded.
+ * @param Entry Header Entry whose length of the value shall be loaded.
* @return
*/
- void gdcmParser::FindHeaderEntryLength (gdcmHeaderEntry * ElVal)
+ void gdcmParser::FindHeaderEntryLength (gdcmHeaderEntry *Entry)
{
- guint16 element = ElVal->GetElement();
- guint16 group = ElVal->GetGroup();
- std::string vr = ElVal->GetVR();
+ guint16 element = Entry->GetElement();
+ guint16 group = Entry->GetGroup();
+ std::string vr = Entry->GetVR();
guint16 length16;
if( (element == 0x0010) && (group == 0x7fe0) )
{
"we reached 7fe0 0010");
}
- if ( (filetype == ExplicitVR) && ! ElVal->IsImplicitVr() )
+ if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) )
{
if ( (vr=="OB") || (vr=="OW") || (vr=="SQ") || (vr=="UN") )
{
if ( (vr == "OB") && (length32 == 0xffffffff) )
{
- ElVal->SetLength(FindHeaderEntryLengthOB());
+ Entry->SetLength(FindHeaderEntryLengthOB());
return;
}
- FixHeaderEntryFoundLength(ElVal, length32);
+ FixHeaderEntryFoundLength(Entry, length32);
return;
}
SwitchSwapToBigEndian();
// Restore the unproperly loaded values i.e. the group, the element
// and the dictionary entry depending on them.
- guint16 CorrectGroup = SwapShort(ElVal->GetGroup());
- guint16 CorrectElem = SwapShort(ElVal->GetElement());
+ guint16 CorrectGroup = SwapShort(Entry->GetGroup());
+ guint16 CorrectElem = SwapShort(Entry->GetElement());
gdcmDictEntry * NewTag = GetDictEntryByNumber(CorrectGroup,
CorrectElem);
if (!NewTag)
{
// This correct tag is not in the dictionary. Create a new one.
- NewTag = Dicts->NewVirtualDictEntry(CorrectGroup, CorrectElem);
+ NewTag = NewVirtualDictEntry(CorrectGroup, CorrectElem);
}
// FIXME this can create a memory leaks on the old entry that be
// left unreferenced.
- ElVal->SetDictEntry(NewTag);
+ Entry->SetDictEntry(NewTag);
}
// Heuristic: well some files are really ill-formed.
// Unknown Sequence Length
}
- FixHeaderEntryFoundLength(ElVal, (guint32)length16);
+ FixHeaderEntryFoundLength(Entry, (guint32)length16);
+ return;
+ }
+ else
+ {
+ // Either implicit VR or a non DICOM conformal (see not below) explicit
+ // VR that ommited the VR of (at least) this element. Farts happen.
+ // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25
+ // on Data elements "Implicit and Explicit VR Data Elements shall
+ // not coexist in a Data Set and Data Sets nested within it".]
+ // Length is on 4 bytes.
+ FixHeaderEntryFoundLength(Entry, ReadInt32());
return;
}
-
- // Either implicit VR or a non DICOM conformal (see not below) explicit
- // VR that ommited the VR of (at least) this element. Farts happen.
- // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25
- // on Data elements "Implicit and Explicit VR Data Elements shall
- // not coexist in a Data Set and Data Sets nested within it".]
- // Length is on 4 bytes.
- FixHeaderEntryFoundLength(ElVal, ReadInt32());
- return;
}
/**
* \ingroup gdcmParser
* \brief Find the Value Representation of the current Dicom Element.
- * @param ElVal
+ * @param Entry
*/
-void gdcmParser::FindHeaderEntryVR( gdcmHeaderEntry *ElVal)
+void gdcmParser::FindHeaderEntryVR( gdcmHeaderEntry *Entry)
{
if (filetype != ExplicitVR)
return;
char VR[3];
- std::string vr;
int lgrLue;
- char msg[100]; // for sprintf. Sorry
long PositionOnEntry = ftell(fp);
// Warning: we believe this is explicit VR (Value Representation) because
// within an explicit VR file. Hence we make sure the present tag
// is in explicit VR and try to fix things if it happens not to be
// the case.
- bool RealExplicit = true;
lgrLue=fread (&VR, (size_t)2,(size_t)1, fp);
VR[2]=0;
- vr = std::string(VR);
-
+ if(!CheckHeaderEntryVR(Entry,VR))
+ {
+ fseek(fp, PositionOnEntry, SEEK_SET);
+ // When this element is known in the dictionary we shall use, e.g. for
+ // the semantics (see the usage of IsAnInteger), the VR proposed by the
+ // dictionary entry. Still we have to flag the element as implicit since
+ // we know now our assumption on expliciteness is not furfilled.
+ // avoid .
+ if ( Entry->IsVRUnknown() )
+ Entry->SetVR("Implicit");
+ Entry->SetImplicitVR();
+ }
+}
+
+/**
+ * \ingroup gdcmParser
+ * \brief Check the correspondance between the VR of the header entry
+ * and the taken VR. If they are different, the header entry is
+ * updated with the new VR.
+ * @param Entry
+ * @param VR
+ * @return false if the VR is incorrect of if the VR isn't referenced
+ * otherwise, it returns true
+*/
+bool gdcmParser::CheckHeaderEntryVR(gdcmHeaderEntry *Entry, VRKey vr)
+{
+ char msg[100]; // for sprintf
+ bool RealExplicit = true;
+
// Assume we are reading a falsely explicit VR file i.e. we reached
// a tag where we expect reading a VR but are in fact we read the
// first to bytes of the length. Then we will interogate (through find)
// expected VR read happens to be non-ascii characters we consider
// we hit falsely explicit VR tag.
- if ( (!isalpha(VR[0])) && (!isalpha(VR[1])) )
+ if ( (!isalpha(vr[0])) && (!isalpha(vr[1])) )
RealExplicit = false;
// CLEANME searching the dicom_vr at each occurence is expensive.
// PostPone this test in an optional integrity check at the end
// of parsing or only in debug mode.
- if ( RealExplicit && !dicom_vr->Count(vr) )
+ if ( RealExplicit && !gdcmGlobal::GetVR()->Count(vr) )
RealExplicit= false;
- if ( RealExplicit )
+ if ( !RealExplicit )
+ {
+ // We thought this was explicit VR, but we end up with an
+ // implicit VR tag. Let's backtrack.
+ sprintf(msg,"Falsely explicit vr file (%04x,%04x)\n",
+ Entry->GetGroup(),Entry->GetElement());
+ dbg.Verbose(1, "gdcmParser::FindVR: ",msg);
+
+ return(false);
+ }
+
+ if ( Entry->IsVRUnknown() )
+ {
+ // When not a dictionary entry, we can safely overwrite the VR.
+ Entry->SetVR(vr);
+ }
+ else if ( Entry->GetVR() != vr )
{
- if ( ElVal->IsVRUnknown() )
- {
- // When not a dictionary entry, we can safely overwrite the VR.
- ElVal->SetVR(vr);
- return;
- }
- if ( ElVal->GetVR() == vr )
- {
- // The VR we just read and the dictionary agree. Nothing to do.
- return;
- }
// The VR present in the file and the dictionary disagree. We assume
// the file writer knew best and use the VR of the file. Since it would
// be unwise to overwrite the VR of a dictionary (since it would
// compromise it's next user), we need to clone the actual DictEntry
// and change the VR for the read one.
- gdcmDictEntry* NewTag = Dicts->NewVirtualDictEntry(ElVal->GetGroup(),
- ElVal->GetElement(),
- vr,
- "FIXME",
- ElVal->GetName());
- ElVal->SetDictEntry(NewTag);
- return;
+ gdcmDictEntry* NewEntry = NewVirtualDictEntry(
+ Entry->GetGroup(),Entry->GetElement(),
+ vr,"FIXME",Entry->GetName());
+ Entry->SetDictEntry(NewEntry);
}
-
- // We thought this was explicit VR, but we end up with an
- // implicit VR tag. Let's backtrack.
-
- sprintf(msg,"Falsely explicit vr file (%04x,%04x)\n",
- ElVal->GetGroup(),ElVal->GetElement());
- dbg.Verbose(1, "gdcmParser::FindVR: ",msg);
-
- fseek(fp, PositionOnEntry, SEEK_SET);
- // When this element is known in the dictionary we shall use, e.g. for
- // the semantics (see the usage of IsAnInteger), the VR proposed by the
- // dictionary entry. Still we have to flag the element as implicit since
- // we know now our assumption on expliciteness is not furfilled.
- // avoid .
- if ( ElVal->IsVRUnknown() )
- ElVal->SetVR("Implicit");
- ElVal->SetImplicitVr();
+ return(true);
}
/**
* \ingroup gdcmParser
- * \brief Skip a given Header Entry
+ * \brief Get the transformed value of the header entry. The VR value
+ * is used to define the transformation to operate on the value
* \warning NOT end user intended method !
- * @param entry
- * @return
+ * @param Entry
+ * @return Transformed entry value
+ */
+std::string gdcmParser::GetHeaderEntryValue(gdcmHeaderEntry *Entry)
+{
+ if ( (IsHeaderEntryAnInteger(Entry)) && (Entry->IsImplicitVR()) )
+ {
+ std::string val=Entry->GetValue();
+ std::string vr=Entry->GetVR();
+ guint32 length = Entry->GetLength();
+ std::ostringstream s;
+ int nbInt;
+
+ if (vr == "US" || vr == "SS")
+ {
+ guint16 NewInt16;
+
+ nbInt = length / 2;
+ for (int i=0; i < nbInt; i++)
+ {
+ if(i!=0)
+ s << '\\';
+ NewInt16 = (val[2*i+0]&0xFF)+((val[2*i+1]&0xFF)<<8);
+ NewInt16 = SwapShort(NewInt16);
+ s << NewInt16;
+ }
+ }
+
+ else if (vr == "UL" || vr == "SL")
+ {
+ guint32 NewInt32;
+
+ nbInt = length / 4;
+ for (int i=0; i < nbInt; i++)
+ {
+ if(i!=0)
+ s << '\\';
+ NewInt32= (val[4*i+0]&0xFF)+((val[4*i+1]&0xFF)<<8)+
+ ((val[4*i+2]&0xFF)<<16)+((val[4*i+3]&0xFF)<<24);
+ NewInt32=SwapLong(NewInt32);
+ s << NewInt32;
+ }
+ }
+
+#ifdef GDCM_NO_ANSI_STRING_STREAM
+ s << std::ends; // to avoid oddities on Solaris
+#endif //GDCM_NO_ANSI_STRING_STREAM
+ return(s.str());
+ }
+
+ return(Entry->GetValue());
+}
+
+/**
+ * \ingroup gdcmParser
+ * \brief Get the reverse transformed value of the header entry. The VR
+ * value is used to define the reverse transformation to operate on
+ * the value
+ * \warning NOT end user intended method !
+ * @param Entry
+ * @return Reverse transformed entry value
+ */
+std::string gdcmParser::GetHeaderEntryUnvalue(gdcmHeaderEntry *Entry)
+{
+ if ( (IsHeaderEntryAnInteger(Entry)) && (Entry->IsImplicitVR()) )
+ {
+ std::string vr=Entry->GetVR();
+ std::ostringstream s;
+ std::vector<std::string> tokens;
+
+ if (vr == "US" || vr == "SS")
+ {
+ guint16 NewInt16;
+
+ tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
+ Tokenize (Entry->GetValue(), tokens, "\\");
+ for (unsigned int i=0; i<tokens.size();i++)
+ {
+ NewInt16 = atoi(tokens[i].c_str());
+ s<<(NewInt16&0xFF)<<((NewInt16>>8)&0xFF);
+ }
+ tokens.clear();
+ }
+ if (vr == "UL" || vr == "SL")
+ {
+ guint32 NewInt32;
+
+ tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
+ Tokenize (Entry->GetValue(), tokens, "\\");
+ for (unsigned int i=0; i<tokens.size();i++)
+ {
+ NewInt32 = atoi(tokens[i].c_str());
+ s<<(char)(NewInt32&0xFF)<<(char)((NewInt32>>8)&0xFF)
+ <<(char)((NewInt32>>16)&0xFF)<<(char)((NewInt32>>24)&0xFF);
+ }
+ tokens.clear();
+ }
+
+#ifdef GDCM_NO_ANSI_STRING_STREAM
+ s << std::ends; // to avoid oddities on Solaris
+#endif //GDCM_NO_ANSI_STRING_STREAM
+ return(s.str());
+ }
+
+ return(Entry->GetValue());
+}
+
+/**
+ * \ingroup gdcmParser
+ * \brief Skip a given Header Entry
+ * \warning NOT end user intended method !
+ * @param entry
*/
-void gdcmParser::SkipHeaderEntry(gdcmHeaderEntry * entry)
+void gdcmParser::SkipHeaderEntry(gdcmHeaderEntry *entry)
{
SkipBytes(entry->GetLength());
}
* the parser went Jabberwocky) one can hope improving things by
* applying this heuristic.
*/
-void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry * ElVal, guint32 FoundLength)
+void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry *Entry, guint32 FoundLength)
{
- ElVal->SetReadLength(FoundLength); // will be updated only if a bug is found
+ Entry->SetReadLength(FoundLength); // will be updated only if a bug is found
if ( FoundLength == 0xffffffff)
{
{
// The following 'if' will be removed when there is no more
// images on Creatis HDs with a 13 length for Manufacturer...
- if ( (ElVal->GetGroup() != 0x0008) ||
- ( (ElVal->GetElement() != 0x0070) && (ElVal->GetElement() != 0x0080) ) ) {
+ if ( (Entry->GetGroup() != 0x0008) ||
+ ( (Entry->GetElement() != 0x0070) && (Entry->GetElement() != 0x0080) ) ) {
// end of remove area
FoundLength =10;
- ElVal->SetReadLength(10); // a bug is to be fixed
+ Entry->SetReadLength(10); // a bug is to be fixed
}
}
// to fix some garbage 'Leonardo' Siemens images
// May be commented out to avoid overhead
- else if ( (ElVal->GetGroup() == 0x0009) &&
- ( (ElVal->GetElement() == 0x1113) || (ElVal->GetElement() == 0x1114) ) )
+ else if ( (Entry->GetGroup() == 0x0009) &&
+ ( (Entry->GetElement() == 0x1113) || (Entry->GetElement() == 0x1114) ) )
{
FoundLength =4;
- ElVal->SetReadLength(4); // a bug is to be fixed
+ Entry->SetReadLength(4); // a bug is to be fixed
}
// end of fix
// to try to 'go inside' SeQuences (with length), and not to skip them
- else if ( ElVal->GetVR() == "SQ")
+ else if ( Entry->GetVR() == "SQ")
{
if (enableSequences) // only if the user does want to !
FoundLength =0;
// if we set the length to zero IsHeaderEntryAnInteger() breaks...
// if we don't, we lost 28800 characters from the Header :-(
- else if(ElVal->GetGroup() == 0xfffe)
+ else if(Entry->GetGroup() == 0xfffe)
{
// sometimes, length seems to be wrong
FoundLength =0; // some more clever checking to be done !
// causes troubles :-(
}
- ElVal->SetUsableLength(FoundLength);
+ Entry->SetUsableLength(FoundLength);
}
/**
* \ingroup gdcmParser
* \brief Apply some heuristics to predict wether the considered
* element value contains/represents an integer or not.
- * @param ElVal The element value on which to apply the predicate.
+ * @param Entry The element value on which to apply the predicate.
* @return The result of the heuristical predicate.
*/
-bool gdcmParser::IsHeaderEntryAnInteger(gdcmHeaderEntry * ElVal)
+bool gdcmParser::IsHeaderEntryAnInteger(gdcmHeaderEntry *Entry)
{
- guint16 element = ElVal->GetElement();
- guint16 group = ElVal->GetGroup();
- std::string vr = ElVal->GetVR();
- guint32 length = ElVal->GetLength();
+ guint16 element = Entry->GetElement();
+ guint16 group = Entry->GetGroup();
+ std::string vr = Entry->GetVR();
+ guint32 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
*/
void gdcmParser::Initialise(void)
{
- dicom_vr = gdcmGlobal::GetVR();
- dicom_ts = gdcmGlobal::GetTS();
- Dicts = gdcmGlobal::GetDicts();
- RefPubDict = Dicts->GetDefaultPubDict();
+ RefPubDict = gdcmGlobal::GetDicts()->GetDefaultPubDict();
RefShaDict = (gdcmDict*)0;
}
}
if (RefPubDict)
{
- found = RefPubDict->GetTagByName(Name);
+ found = RefPubDict->GetDictEntryByName(Name);
if (found)
return found;
}
if (RefShaDict)
{
- found = RefShaDict->GetTagByName(Name);
+ found = RefShaDict->GetDictEntryByName(Name);
if (found)
return found;
}
}
if (RefPubDict)
{
- found = RefPubDict->GetTagByNumber(group, element);
+ found = RefPubDict->GetDictEntryByNumber(group, element);
if (found)
return found;
}
if (RefShaDict)
{
- found = RefShaDict->GetTagByNumber(group, element);
+ found = RefShaDict->GetDictEntryByNumber(group, element);
if (found)
return found;
}
gdcmHeaderEntry *gdcmParser::ReadNextHeaderEntry(void)
{
guint16 g,n;
- gdcmHeaderEntry *NewElVal;
+ gdcmHeaderEntry *NewEntry;
g = ReadInt16();
n = ReadInt16();
// has to be considered as finished.
return (gdcmHeaderEntry *)0;
- NewElVal = NewHeaderEntryByNumber(g, n);
- FindHeaderEntryVR(NewElVal);
- FindHeaderEntryLength(NewElVal);
+ NewEntry = NewHeaderEntryByNumber(g, n);
+ FindHeaderEntryVR(NewEntry);
+ FindHeaderEntryLength(NewEntry);
if (errno == 1)
{
// Call it quits
return NULL;
}
- NewElVal->SetOffset(ftell(fp));
+ NewEntry->SetOffset(ftell(fp));
//if ( (g==0x7fe0) && (n==0x0010) )
- return NewElVal;
+ return NewEntry;
}
/**
{
gdcmDictEntry *NewTag = GetDictEntryByName(Name);
if (!NewTag)
- NewTag = Dicts->NewVirtualDictEntry(0xffff, 0xffff, "LO", "Unknown", Name);
+ NewTag = NewVirtualDictEntry(0xffff, 0xffff, "LO", "Unknown", Name);
- gdcmHeaderEntry* NewElVal = new gdcmHeaderEntry(NewTag);
- if (!NewElVal)
+ gdcmHeaderEntry* NewEntry = new gdcmHeaderEntry(NewTag);
+ if (!NewEntry)
{
dbg.Verbose(1, "gdcmParser::ObtainHeaderEntryByName",
"failed to allocate gdcmHeaderEntry");
return (gdcmHeaderEntry *)0;
}
- return NewElVal;
+ return NewEntry;
}
+/**
+ * \ingroup gdcmParser
+ * \brief Request a new virtual dict entry to the dict set
+ * @param group group of the underlying DictEntry
+ * @param elem element of the underlying DictEntry
+ * @param vr VR of the underlying DictEntry
+ * @param fourth owner group
+ * @param name english name
+ */
+gdcmDictEntry *gdcmParser::NewVirtualDictEntry(guint16 group, guint16 element,
+ std::string vr,
+ std::string fourth,
+ std::string name)
+{
+ return gdcmGlobal::GetDicts()->NewVirtualDictEntry(group,element,vr,fourth,name);
+}
+
/**
* \ingroup gdcmParser
* \brief Build a new Element Value from all the low level arguments.
gdcmHeaderEntry *gdcmParser::NewHeaderEntryByNumber(guint16 Group, guint16 Elem)
{
// Find out if the tag we encountered is in the dictionaries:
- gdcmDictEntry *NewTag = GetDictEntryByNumber(Group, Elem);
- if (!NewTag)
- NewTag = Dicts->NewVirtualDictEntry(Group, Elem);
+ gdcmDictEntry *DictEntry = GetDictEntryByNumber(Group, Elem);
+ if (!DictEntry)
+ DictEntry = NewVirtualDictEntry(Group, Elem);
- gdcmHeaderEntry* NewElVal = new gdcmHeaderEntry(NewTag);
- if (!NewElVal)
+ gdcmHeaderEntry *NewEntry = new gdcmHeaderEntry(DictEntry);
+ if (!NewEntry)
{
dbg.Verbose(1, "gdcmParser::NewHeaderEntryByNumber",
"failed to allocate gdcmHeaderEntry");
return NULL;
}
- return NewElVal;
+ return NewEntry;
}
/**
gdcmHeaderEntry *gdcmParser::NewManualHeaderEntryToPubDict(std::string NewTagName,
std::string VR)
{
- gdcmHeaderEntry *NewElVal = (gdcmHeaderEntry *)0;
+ gdcmHeaderEntry *NewEntry = NULL;
guint32 StuffGroup = 0xffff; // Group to be stuffed with additional info
guint32 FreeElem = 0;
- gdcmDictEntry *NewEntry = (gdcmDictEntry *)0;
+ gdcmDictEntry *DictEntry = NULL;
FreeElem = GenerateFreeTagKeyInGroup(StuffGroup);
if (FreeElem == UINT32_MAX)
{
- dbg.Verbose(1, "gdcmHeader::NewManualElValToPubDict",
+ dbg.Verbose(1, "gdcmHeader::NewManualHeaderEntryToPubDict",
"Group 0xffff in Public Dict is full");
return NULL;
}
- NewEntry = Dicts->NewVirtualDictEntry(StuffGroup, FreeElem,
+ DictEntry = NewVirtualDictEntry(StuffGroup, FreeElem,
VR, "GDCM", NewTagName);
- NewElVal = new gdcmHeaderEntry(NewEntry);
- AddHeaderEntry(NewElVal);
- return NewElVal;
+ NewEntry = new gdcmHeaderEntry(DictEntry);
+ AddHeaderEntry(NewEntry);
+ return NewEntry;
}
/**