+// gdcmHeader.cxx
+
#include "gdcm.h"
#include <stdio.h>
+#include <cerrno>
// For nthos:
#ifdef _MSC_VER
#include <winsock.h>
#include <sstream>
#include "gdcmUtil.h"
-#define HEADER_LENGHT_TO_READ 256 // on ne lit plus que le debut
-
-namespace Error {
- struct FileReadError {
- FileReadError(FILE* fp, const char* Mesg) {
- if (feof(fp))
- dbg.Verbose(1, "EOF encountered :", Mesg);
- if (ferror(fp))
- dbg.Verbose(1, "Error on reading :", Mesg);
- }
- };
-}
+#define HEADER_LENGTH_TO_READ 256 // on ne lit plus que le debut
+#define _MaxSizeLoadElementValue_ 1024 // longueur au dela de laquelle on ne charge plus les valeurs
//FIXME: this looks dirty to me...
+
#define str2num(str, typeNum) *((typeNum *)(str))
+// str est un pointeur dans un tableau de caractères, qui doit contenir,
+// à cet endroit la, la représentation binaire d'un entier (16 ou 32 bits)
+// je veux récupérer ça ... dans un entier.
+// s'il y a une autre solution, évitant des cast et les indirections,
+// je suis preneur
+
VRHT * gdcmHeader::dicom_vr = (VRHT*)0;
-gdcmDictSet* gdcmHeader::Dicts = new gdcmDictSet();
void gdcmHeader::Initialise(void) {
if (!gdcmHeader::dicom_vr)
InitVRDict();
- RefPubDict = gdcmHeader::Dicts->GetDefaultPublicDict();
+ Dicts = new gdcmDictSet();
+ RefPubDict = Dicts->GetDefaultPubDict();
RefShaDict = (gdcmDict*)0;
}
-gdcmHeader::gdcmHeader (const char* InFilename) {
- SetMaxSizeLoadElementValue(1024);
- filename = InFilename;
- Initialise();
- fp=fopen(InFilename,"rw");
- dbg.Error(!fp, "gdcmHeader::gdcmHeader cannot open file", InFilename);
- ParseHeader();
+
+gdcmHeader::gdcmHeader(const char *InFilename, bool exception_on_error)
+ throw(gdcmFileError) {
+ SetMaxSizeLoadElementValue(_MaxSizeLoadElementValue_);
+ filename = InFilename;
+ Initialise();
+ fp=fopen(InFilename,"rb");
+ if(exception_on_error) {
+ if(!fp)
+ throw gdcmFileError("gdcmHeader::gdcmHeader(const char *, bool)");
+ }
+ else
+ dbg.Error(!fp, "gdcmHeader::gdcmHeader cannot open file", InFilename);
+ ParseHeader();
+ AddAndDefaultElements();
}
+
gdcmHeader::~gdcmHeader (void) {
fclose(fp);
return;
/**
* \ingroup gdcmHeader
- * \brief Discover what the swap code is (among little endian, big endian,
+ * \brief Discover what the swap code is (among little endian, big endian,
* bad little endian, bad big endian).
+ *
*/
void gdcmHeader::CheckSwap()
{
int lgrLue;
char * entCur;
- char deb[HEADER_LENGHT_TO_READ];
+ char deb[HEADER_LENGTH_TO_READ];
// First, compare HostByteOrder and NetworkByteOrder in order to
// determine if we shall need to swap bytes (i.e. the Endian type).
net2host = false;
// The easiest case is the one of a DICOM header, since it possesses a
- // file preamble where it suffice to look for the sting "DICM".
- lgrLue = fread(deb, 1, HEADER_LENGHT_TO_READ, fp);
+ // file preamble where it suffice to look for the string "DICM".
+ lgrLue = fread(deb, 1, HEADER_LENGTH_TO_READ, fp);
entCur = deb + 128;
if(memcmp(entCur, "DICM", (size_t)4) == 0) {
return;
default :
dbg.Verbose(0, "gdcmHeader::CheckSwap:",
- "ACE/NEMA unfound swap info (time to raise bets)");
+ "ACR/NEMA unfound swap info (time to raise bets)");
}
// We are out of luck. It is not a DicomV3 nor a 'clean' ACR/NEMA file.
sw = 3412;
}
+void gdcmHeader::GetPixels(size_t lgrTotale, void* _Pixels) {
+ size_t pixelsOffset;
+ pixelsOffset = GetPixelOffset();
+ fseek(fp, pixelsOffset, SEEK_SET);
+ fread(_Pixels, 1, lgrTotale, fp);
+}
+
+
+
/**
* \ingroup gdcmHeader
* \brief Find the value representation of the current tag.
- *
- * @param sw code swap
- * @param skippedLength pointeur sur nombre d'octets que l'on a saute qd
- * la lecture est finie
- * @param longueurLue pointeur sur longueur (en nombre d'octets)
- * effectivement lue
- * @return longueur retenue pour le champ
*/
-
void gdcmHeader::FindVR( ElValue *ElVal) {
if (filetype != ExplicitVR)
return;
// 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)
// the dicom_vr dictionary with oddities like "\004\0" which crashes
- // both GCC and VC++ implentations of the STL map. Hence when the
+ // both GCC and VC++ implementations of the STL map. Hence when the
// expected VR read happens to be non-ascii characters we consider
// we hit falsely explicit VR tag.
/**
* \ingroup gdcmHeader
* \brief Determines if the Transfer Syntax was allready encountered
- * and if it corresponds to a Big Endian one.
+ * and if it corresponds to a ImplicitVRLittleEndian one.
+ *
+ * @return True when ImplicitVRLittleEndian found. False in all other cases.
+ */
+bool gdcmHeader::IsImplicitVRLittleEndianTransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2" )
+ return true;
+ return false;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a ExplicitVRLittleEndian one.
+ *
+ * @return True when ExplicitVRLittleEndian found. False in all other cases.
+ */
+bool gdcmHeader::IsExplicitVRLittleEndianTransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.1" )
+ return true;
+ return false;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a DeflatedExplicitVRLittleEndian one.
+ *
+ * @return True when DeflatedExplicitVRLittleEndian found. False in all other cases.
+ */
+bool gdcmHeader::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.1.99" )
+ return true;
+ return false;
+}
+
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a Explicit VR Big Endian one.
*
* @return True when big endian found. False in all other cases.
*/
-bool gdcmHeader::IsBigEndianTransferSyntax(void) {
+bool gdcmHeader::IsExplicitVRBigEndianTransferSyntax(void) {
ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
if ( !Element )
return false;
return false;
}
-void gdcmHeader::FixFoundLength(ElValue * ElVal, guint32 FoudLength) {
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a JPEGBaseLineProcess1 one.
+ *
+ * @return True when JPEGBaseLineProcess1found. False in all other cases.
+ */
+bool gdcmHeader::IsJPEGBaseLineProcess1TransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.4.50" )
+ return true;
+ return false;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a JPEGExtendedProcess2-4 one.
+ *
+ * @return True when JPEGExtendedProcess2-4 found. False in all other cases.
+ */
+bool gdcmHeader::IsJPEGExtendedProcess2_4TransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.4.51" )
+ return true;
+ return false;
+}
+
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a JPEGExtendeProcess3-5 one.
+ *
+ * @return True when JPEGExtendedProcess3-5 found. False in all other cases.
+ */
+bool gdcmHeader::IsJPEGExtendedProcess3_5TransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.4.52" )
+ return true;
+ return false;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a JPEGSpectralSelectionProcess6-8 one.
+ *
+ * @return True when JPEGSpectralSelectionProcess6-8 found. False in all other cases.
+ */
+bool gdcmHeader::IsJPEGSpectralSelectionProcess6_8TransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.4.53" )
+ return true;
+ return false;
+}
+
+//
+// Euhhhhhhh
+// Il y en a encore DIX-SEPT, comme ça.
+// Il faudrait trouver qq chose + rusé ...
+//
+// --> probablement TOUS les supprimer (Eric dixit)
+//
+
+
+void gdcmHeader::FixFoundLength(ElValue * ElVal, guint32 FoundLength) {
// Heuristic: a final fix.
- if ( FoudLength == 0xffffffff)
- FoudLength = 0;
- ElVal->SetLength(FoudLength);
+ if ( FoundLength == 0xffffffff)
+ FoundLength = 0;
+ ElVal->SetLength(FoundLength);
}
guint32 gdcmHeader::FindLengthOB(void) {
while ( ! FoundSequenceDelimiter) {
g = ReadInt16();
n = ReadInt16();
+ if (errno == 1)
+ return 0;
TotalLength += 4; // We even have to decount the group and element
if ( g != 0xfffe ) {
dbg.Verbose(1, "gdcmHeader::FindLengthOB: ",
"wrong group for an item sequence.");
- throw Error::FileReadError(fp, "gdcmHeader::FindLengthOB");
+ errno = 1;
+ return 0;
}
if ( n == 0xe0dd )
FoundSequenceDelimiter = true;
else if ( n != 0xe000) {
dbg.Verbose(1, "gdcmHeader::FindLengthOB: ",
"wrong element for an item sequence.");
- throw Error::FileReadError(fp, "gdcmHeader::FindLengthOB");
+ errno = 1;
+ return 0;
}
ItemLength = ReadInt32();
TotalLength += ItemLength + 4; // We add 4 bytes since we just read
// in little endian, and big endian coding only starts at the next
// group. The corresponding code can be hard to analyse and adds
// many additional unnecessary tests for regular tags.
- // * the second strategy consist in waiting for trouble, that shall appear
+ // * the second strategy consists in waiting for trouble, that shall appear
// when we find the first group with big endian encoding. This is
// easy to detect since the length of a "Group Length" tag (the
// ones with zero as element number) has to be of 4 (0x0004). When we
// endian encoding". When this is the case, chances are we got our
// hands on a big endian encoded file: we switch the swap code to
// big endian and proceed...
- if ( (element == 0) && (length16 == 1024) ) {
- if ( ! IsBigEndianTransferSyntax() )
- throw Error::FileReadError(fp, "gdcmHeader::FindLength");
+ if ( (element == 0x000) && (length16 == 0x0400) ) {
+ if ( ! IsExplicitVRBigEndianTransferSyntax() ) {
+ dbg.Verbose(0, "gdcmHeader::FindLength", "not explicit VR");
+ errno = 1;
+ return;
+ }
length16 = 4;
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());
- gdcmDictEntry * NewTag = IsInDicts(CorrectGroup, CorrectElem);
+ gdcmDictEntry * NewTag = GetDictEntryByKey(CorrectGroup, CorrectElem);
if (!NewTag) {
// This correct tag is not in the dictionary. Create a new one.
NewTag = new gdcmDictEntry(CorrectGroup, CorrectElem);
/**
* \ingroup gdcmHeader
- * \brief Loads the element if it's size is not to big.
- * @param ElVal Element whose value shall be loaded.
- * @param MaxSize Size treshold above which the element value is not
- * loaded in memory. The element value is allways loaded
- * when MaxSize is equal to UINT32_MAX.
- * @return
+ * \brief Loads the element content if it's length is not bigger
+ * than the value specified with
+ * gdcmHeader::SetMaxSizeLoadElementValue()
*/
void gdcmHeader::LoadElementValue(ElValue * ElVal) {
size_t item_read;
fseek(fp, (long)ElVal->GetOffset(), SEEK_SET);
// Sequences not treated yet !
+ //
+ // Ne faudrait-il pas au contraire trouver immediatement
+ // une maniere 'propre' de traiter les sequences (vr = SQ)
+ // car commencer par les ignorer risque de conduire a qq chose
+ // qui pourrait ne pas etre generalisable
+ //
if( vr == "SQ" )
SkipLoad = true;
// The group length doesn't represent data to be loaded in memory, since
// each element of the group shall be loaded individualy.
if( elem == 0 )
- SkipLoad = true;
+ //SkipLoad = true; // modif sauvage JPR
+ // On charge la longueur du groupe
+ // quand l'element 0x0000 est présent !
if ( SkipLoad ) {
// FIXME the following skip is not necessary
return;
}
- // Values bigger than specified are not loaded.
+ // The elements whose length is bigger than the specified upper bound
+ // are not loaded. Instead we leave a short notice of the offset of
+ // the element content and it's length.
if (length > MaxSizeLoadElementValue) {
ostringstream s;
s << "gdcm::NotLoaded.";
s << " Address:" << (long)ElVal->GetOffset();
s << " Length:" << ElVal->GetLength();
- //mesg += " Length:" + ElVal->GetLength();
ElVal->SetValue(s.str());
return;
}
item_read = fread(NewValue, (size_t)length, (size_t)1, fp);
if ( item_read != 1 ) {
free(NewValue);
- Error::FileReadError(fp, "gdcmHeader::LoadElementValue");
+ dbg.Verbose(1, "gdcmHeader::LoadElementValue","unread element value");
ElVal->SetValue("gdcm::UnRead");
return;
}
guint16 g;
size_t item_read;
item_read = fread (&g, (size_t)2,(size_t)1, fp);
- if ( item_read != 1 )
- throw Error::FileReadError(fp, "gdcmHeader::ReadInt16");
+ errno = 0;
+ if ( item_read != 1 ) {
+ dbg.Verbose(1, "gdcmHeader::ReadInt16", " File read error");
+ errno = 1;
+ return 0;
+ }
g = SwapShort(g);
return g;
}
guint32 g;
size_t item_read;
item_read = fread (&g, (size_t)4,(size_t)1, fp);
- if ( item_read != 1 )
- throw Error::FileReadError(fp, "gdcmHeader::ReadInt32");
+ errno = 0;
+ if ( item_read != 1 ) {
+ dbg.Verbose(1, "gdcmHeader::ReadInt32", " File read error");
+ errno = 1;
+ return 0;
+ }
g = SwapLong(g);
return g;
}
+/**
+ * \ingroup gdcmHeader
+ * \brief Build a new Element Value from all the low level arguments.
+ * Check for existence of dictionary entry, and build
+ * a default one when absent.
+ * @param Group group of the underlying DictEntry
+ * @param Elem element of the underlying DictEntry
+ */
+ElValue* gdcmHeader::NewElValueByKey(guint16 Group, guint16 Elem) {
+ // Find out if the tag we encountered is in the dictionaries:
+ gdcmDictEntry * NewTag = GetDictEntryByKey(Group, Elem);
+ if (!NewTag)
+ NewTag = new gdcmDictEntry(Group, Elem);
+
+ ElValue* NewElVal = new ElValue(NewTag);
+ if (!NewElVal) {
+ dbg.Verbose(1, "gdcmHeader::NewElValueByKey",
+ "failed to allocate ElValue");
+ return (ElValue*)0;
+ }
+ return NewElVal;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Build a new Element Value from all the low level arguments.
+ * Check for existence of dictionary entry, and build
+ * a default one when absent.
+ * @param Name Name of the underlying DictEntry
+ */
+ElValue* gdcmHeader::NewElValueByName(string Name) {
+
+ gdcmDictEntry * NewTag = GetDictEntryByName(Name);
+ if (!NewTag)
+ NewTag = new gdcmDictEntry(0xffff, 0xffff, "LO", "Unknown", Name);
+
+ ElValue* NewElVal = new ElValue(NewTag);
+ if (!NewElVal) {
+ dbg.Verbose(1, "gdcmHeader::ObtainElValueByName",
+ "failed to allocate ElValue");
+ return (ElValue*)0;
+ }
+ return NewElVal;
+}
+
+
/**
* \ingroup gdcmHeader
* \brief Read the next tag without loading it's value
guint16 n;
ElValue * NewElVal;
- try {
- g = ReadInt16();
- n = ReadInt16();
- }
- catch ( Error::FileReadError ) {
+ g = ReadInt16();
+ n = ReadInt16();
+ if (errno == 1)
// We reached the EOF (or an error occured) and header parsing
// has to be considered as finished.
return (ElValue *)0;
- }
-
- // Find out if the tag we encountered is in the dictionaries:
- gdcmDictEntry * NewTag = IsInDicts(g, n);
- if (!NewTag)
- NewTag = new gdcmDictEntry(g, n);
-
- NewElVal = new ElValue(NewTag);
- if (!NewElVal) {
- dbg.Verbose(1, "ReadNextElement: failed to allocate ElValue");
- return (ElValue*)0;
- }
-
+
+ NewElVal = NewElValueByKey(g, n);
FindVR(NewElVal);
- try { FindLength(NewElVal); }
- catch ( Error::FileReadError ) { // Call it quits
+ FindLength(NewElVal);
+ if (errno == 1)
+ // Call it quits
return (ElValue *)0;
- }
NewElVal->SetOffset(ftell(fp));
return NewElVal;
}
return true;
if ( (group == 0x0028) && (element == 0x0005) )
- // This tag is retained from ACR/NEMA
- // CHECKME Why should "Image Dimensions" be a single integer ?
+ // The "Image Dimensions" tag is retained from ACR/NEMA and contains
+ // the number of dimensions of the contained object (1 for Signal,
+ // 2 for Image, 3 for Volume, 4 for Sequence).
return true;
if ( (group == 0x0028) && (element == 0x0200) )
guint16 grPixel;
guint16 numPixel;
string ImageLocation = GetPubElValByName("Image Location");
- if ( ImageLocation == "UNFOUND" ) {
+ if ( ImageLocation == "gdcm::Unfound" ) {
grPixel = 0x7fe0;
} else {
grPixel = (guint16) atoi( ImageLocation.c_str() );
return 0;
}
-gdcmDictEntry * gdcmHeader::IsInDicts(guint32 group, guint32 element) {
+/**
+ * \ingroup gdcmHeader
+ * \brief Searches both the public and the shadow dictionary (when they
+ * exist) for the presence of the DictEntry with given
+ * group and element. The public dictionary has precedence on the
+ * shadow one.
+ * @param group group of the searched DictEntry
+ * @param element element of the searched DictEntry
+ * @return Corresponding DictEntry when it exists, NULL otherwise.
+ */
+gdcmDictEntry * gdcmHeader::GetDictEntryByKey(guint16 group, guint16 element) {
gdcmDictEntry * found = (gdcmDictEntry*)0;
if (!RefPubDict && !RefShaDict) {
- //FIXME build a default dictionary !
- printf("FIXME in gdcmHeader::IsInDicts\n");
+ dbg.Verbose(0, "FIXME in gdcmHeader::GetDictEntry",
+ "we SHOULD have a default dictionary");
}
if (RefPubDict) {
- found = RefPubDict->GetTag(group, element);
+ found = RefPubDict->GetTagByKey(group, element);
if (found)
return found;
}
if (RefShaDict) {
- found = RefShaDict->GetTag(group, element);
+ found = RefShaDict->GetTagByKey(group, element);
if (found)
return found;
}
return found;
}
-list<string> * gdcmHeader::GetPubTagNames(void) {
- list<string> * Result = new list<string>;
- TagHT entries = RefPubDict->GetEntries();
-
- for (TagHT::iterator tag = entries.begin(); tag != entries.end(); ++tag){
- Result->push_back( tag->second->GetName() );
+/**
+ * \ingroup gdcmHeader
+ * \brief Searches both the public and the shadow dictionary (when they
+ * exist) for the presence of the DictEntry with given name.
+ * The public dictionary has precedence on the shadow one.
+ * @earam Name name of the searched DictEntry
+ * @return Corresponding DictEntry when it exists, NULL otherwise.
+ */
+gdcmDictEntry * gdcmHeader::GetDictEntryByName(string Name) {
+ gdcmDictEntry * found = (gdcmDictEntry*)0;
+ if (!RefPubDict && !RefShaDict) {
+ dbg.Verbose(0, "FIXME in gdcmHeader::GetDictEntry",
+ "we SHOULD have a default dictionary");
}
- return Result;
-}
-
-map<string, list<string> > * gdcmHeader::GetPubTagNamesByCategory(void) {
- map<string, list<string> > * Result = new map<string, list<string> >;
- TagHT entries = RefPubDict->GetEntries();
-
- for (TagHT::iterator tag = entries.begin(); tag != entries.end(); ++tag){
- (*Result)[tag->second->GetFourth()].push_back(tag->second->GetName());
+ if (RefPubDict) {
+ found = RefPubDict->GetTagByName(Name);
+ if (found)
+ return found;
}
- return Result;
+ if (RefShaDict) {
+ found = RefShaDict->GetTagByName(Name);
+ if (found)
+ return found;
+ }
+ return found;
}
string gdcmHeader::GetPubElValByNumber(guint16 group, guint16 element) {
return elem->GetVR();
}
-
string gdcmHeader::GetElValByNumber(guint16 group, guint16 element) {
string pub = GetPubElValByNumber(group, element);
if (pub.length())
/**
* \ingroup gdcmHeader
- * \brief Parses the header of the file but does NOT load element values.
+ * \brief Accesses an existing ElValue in the PubElVals of this instance
+ * through it's (group, element) and modifies it's content with
+ * the given value.
+ * @param content new value to substitute with
+ * @param group group of the ElVal to modify
+ * @param element element of the ElVal to modify
*/
-void gdcmHeader::ParseHeader(void) {
+int gdcmHeader::SetPubElValByNumber(string content, guint16 group,
+ guint16 element)
+{
+ //CLEANME TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ //CLEANME PubElVals.tagHt[key]->SetValue(content);
+ return ( PubElVals.SetElValueByNumber (content, group, element) );
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Accesses an existing ElValue in the PubElVals of this instance
+ * through tag name and modifies it's content with the given value.
+ * @param content new value to substitute with
+ * @param TagName name of the tag to be modified
+ */
+int gdcmHeader::SetPubElValByName(string content, string TagName) {
+ //CLEANME TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ //CLEANME PubElVals.tagHt[key]->SetValue(content);
+ return ( PubElVals.SetElValueByName (content, TagName) );
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Accesses an existing ElValue in the ShaElVals of this instance
+ * through it's (group, element) and modifies it's content with
+ * the given value.
+ * @param content new value to substitute with
+ * @param group group of the ElVal to modify
+ * @param element element of the ElVal to modify
+ */
+int gdcmHeader::SetShaElValByNumber(string content,
+ guint16 group, guint16 element)
+{
+ return ( ShaElVals.SetElValueByNumber (content, group, element) );
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Accesses an existing ElValue in the ShaElVals of this instance
+ * through tag name and modifies it's content with the given value.
+ * @param content new value to substitute with
+ * @param TagName name of the tag to be modified
+ */
+int gdcmHeader::SetShaElValByName(string content, string TagName) {
+ return ( ShaElVals.SetElValueByName (content, TagName) );
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Parses the header of the file but WITHOUT loading element values.
+ */
+void gdcmHeader::ParseHeader(bool exception_on_error) throw(gdcmFormatError) {
ElValue * newElValue = (ElValue *)0;
rewind(fp);
}
}
+/**
+ * \ingroup gdcmHeader
+ * \brief Once the header is parsed add some gdcm convenience/helper elements
+ * in the ElValSet. For example add:
+ * - gdcmImageType which is an entry containing a short for the
+ * type of image and whose value ranges in
+ * I8 (unsigned 8 bit image)
+ * I16 (unsigned 8 bit image)
+ * IS16 (signed 8 bit image)
+ * - gdcmXsize, gdcmYsize, gdcmZsize whose values are respectively
+ * the ones of the official DICOM fields Rows, Columns and Planes.
+ */
+void gdcmHeader::AddAndDefaultElements(void) {
+ ElValue* NewEntry = (ElValue*)0;
+
+ NewEntry = NewElValueByName("gdcmXSize");
+ NewEntry->SetValue(GetElValByName("Rows"));
+ PubElVals.Add(NewEntry);
+
+ NewEntry = NewElValueByName("gdcmYSize");
+ NewEntry->SetValue(GetElValByName("Columns"));
+ PubElVals.Add(NewEntry);
+
+ NewEntry = NewElValueByName("gdcmZSize");
+ NewEntry->SetValue(GetElValByName("Planes"));
+ PubElVals.Add(NewEntry);
+}
+
/**
* \ingroup gdcmHeader
* \brief Loads the element values of all the elements present in the
* public tag based hash table.
*/
void gdcmHeader::LoadElements(void) {
- rewind(fp);
+ rewind(fp);
TagElValueHT ht = PubElVals.GetTagHt();
- for (TagElValueHT::iterator tag = ht.begin(); tag != ht.end(); ++tag)
+ for (TagElValueHT::iterator tag = ht.begin(); tag != ht.end(); ++tag) {
LoadElementValue(tag->second);
+ }
}
void gdcmHeader::PrintPubElVal(ostream & os) {