// 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(_MaxSizeLoadElementValue_);
- 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 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
*/
-
-// -->
-// --> Oops
-// --> C'etait la description de quoi, ca?
-// -->
-
void gdcmHeader::FindVR( ElValue *ElVal) {
if (filetype != ExplicitVR)
return;
// 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;
return;
}
- // Values bigger than specified are not loaded.
- //
- // En fait, c'est les elements dont la longueur est superieure
- // a celle fixee qui ne sont pas charges
- //
+ // 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;
}
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
// 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);
FindLength(NewElVal);
if (errno == 1)
return true;
if ( (group == 0x0028) && (element == 0x0005) )
- // This tag is retained from ACR/NEMA
- // CHECKME Why should "Image Dimensions" be a single integer ?
- //
- // "Image Dimensions", c'est en fait le 'nombre de dimensions'
- // de l'objet ACR-NEMA stocké
- // 1 : Signal
- // 2 : Image
- // 3 : Volume
- // 4 : Sequence
- //
- // DICOM V3 ne retient pas cette information
- // Par defaut, tout est 'Image',
- // C'est a l'utilisateur d'explorer l'ensemble des entetes
- // pour savoir à quoi il a a faire
- //
- // Le Dicom Multiframe peut etre utilise pour stocker,
- // dans un seul fichier, une serie temporelle (cardio vasculaire GE, p.ex)
- // ou un volume (medecine Nucleaire, p.ex)
- //
+ // 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) )
return 0;
}
-gdcmDictEntry * gdcmHeader::IsInDicts(guint32 group, guint32 element) {
- //
- // Y a-t-il une raison de lui passer des guint32
- // alors que group et element sont des guint16?
- //
+/**
+ * \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;
+ }
+ if (RefShaDict) {
+ found = RefShaDict->GetTagByName(Name);
+ if (found)
+ return found;
}
- return Result;
+ 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 Modifie la valeur d'un ElValue déja existant
- * \ dans le PubElVals du gdcmHeader,
- * \ accédé par ses numero de groupe et d'element.
+ * \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
*/
-int gdcmHeader::SetPubElValByNumber(string content, guint16 group, guint16 element) {
- //TagKey key = gdcmDictEntry::TranslateToKey(group, element);
- //PubElVals.tagHt[key]->SetValue(content);
-
+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 Modifie la valeur d'un ElValue déja existant
- * \ dans le PubElVals du gdcmHeader,
- * \ accédé par son nom
+ * \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) {
- //TagKey key = gdcmDictEntry::TranslateToKey(group, element);
- //PubElVals.tagHt[key]->SetValue(content);
-
+ //CLEANME TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ //CLEANME PubElVals.tagHt[key]->SetValue(content);
return ( PubElVals.SetElValueByName (content, TagName) );
}
-
/**
* \ingroup gdcmHeader
- * \brief Modifie la valeur d'un ElValue déja existant
- * \ dans le ShaElVals du gdcmHeader,
- * \ accédé par ses numero de groupe et d'element.
+ * \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) {
-
+int gdcmHeader::SetShaElValByNumber(string content,
+ guint16 group, guint16 element)
+{
return ( ShaElVals.SetElValueByNumber (content, group, element) );
}
-
/**
* \ingroup gdcmHeader
- * \brief Modifie la valeur d'un ElValue déja existant
- * \ dans le ShaElVals du gdcmHeader,
- * \ accédé par son nom
+ * \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 does NOT load element values.
+ * \brief Parses the header of the file but WITHOUT loading element values.
*/
-void gdcmHeader::ParseHeader(void) {
+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);
-
TagElValueHT ht = PubElVals.GetTagHt();
-
for (TagElValueHT::iterator tag = ht.begin(); tag != ht.end(); ++tag) {
LoadElementValue(tag->second);
}