gdcmException.cxx\r
gdcmUtil.cxx\r
gdcmHeader.cxx\r
+ gdcmHeader2.cxx\r
gdcmHeaderHelper.cxx\r
gdcmHeaderEntry.cxx\r
- gdcmHeaderEntrySet.cxx\r
gdcmDictEntry.cxx\r
gdcmDict.cxx\r
gdcmDictSet.cxx\r
$(top_builddir)/src/jpeg/libijg8/libgdcmijpeg8.la \
$(top_builddir)/src/jpeg/ljpg/libgdcmjpg.la
-libgdcm_la_SOURCES= \
- gdcmException.cxx \
- gdcmUtil.cxx \
- gdcmHeader.cxx \
- gdcmHeaderHelper.cxx \
- gdcmHeaderEntry.cxx \
- gdcmHeaderEntrySet.cxx \
- gdcmDictEntry.cxx \
- gdcmDict.cxx \
- gdcmDictSet.cxx \
- gdcmFile.cxx \
- gdcmVR.cxx \
- gdcmTS.cxx \
- gdcmJpeg.cxx \
- gdcmJpeg12.cxx \
- gdcmJpeg2000.cxx \
- gdcmRLE.cxx \
+libgdcm_la_SOURCES= \
+ gdcmException.cxx \
+ gdcmUtil.cxx \
+ gdcmHeader.cxx \
+ gdcmHeader2.cxx \
+ gdcmHeaderHelper.cxx \
+ gdcmHeaderEntry.cxx \
+ gdcmDictEntry.cxx \
+ gdcmDict.cxx \
+ gdcmDictSet.cxx \
+ gdcmFile.cxx \
+ gdcmVR.cxx \
+ gdcmTS.cxx \
+ gdcmJpeg.cxx \
+ gdcmJpeg12.cxx \
+ gdcmJpeg2000.cxx \
+ gdcmRLE.cxx \
gdcmParse.cxx
libgdcmincludedir = $(includedir)
-libgdcminclude_HEADERS = \
- gdcmException.h \
- gdcmHeader.h \
- gdcmHeaderHelper.h \
- gdcmCommon.h \
- gdcm.h \
- gdcmDictSet.h \
- gdcmDict.h \
- gdcmDictEntry.h \
- gdcmHeaderEntry.h \
- gdcmHeaderEntrySet.h \
- gdcmVR.h \
- gdcmTS.h \
+libgdcminclude_HEADERS = \
+ gdcmException.h \
+ gdcmHeader.h \
+ gdcmHeaderHelper.h \
+ gdcmCommon.h \
+ gdcm.h \
+ gdcmDictSet.h \
+ gdcmDict.h \
+ gdcmDictEntry.h \
+ gdcmHeaderEntry.h \
+ gdcmVR.h \
+ gdcmTS.h \
gdcmFile.h
EXTRA_DIST = \
#include "gdcmDictSet.h"
#include "gdcmHeaderEntry.h"
-#include "gdcmHeaderEntrySet.h"
#include "gdcmHeader.h"
#include "gdcmHeaderHelper.h"
* \brief Allocates necessary memory, copies the pixel data
* (image[s]/volume[s]) to newly allocated zone.
* Transforms YBR pixels into RGB pixels if any
- Transforms 3 planes R, G, B into a single RGB Plane
- Transforms single Grey plane + 3 Palettes into a RGB Plane
+ * Transforms 3 planes R, G, B into a single RGB Plane
+ * Transforms single Grey plane + 3 Palettes into a RGB Plane
* @return Pointer to newly allocated pixel data.
* \ NULL if alloc fails
*/
* \brief Allocates necessary memory, copies the pixel data
* (image[s]/volume[s]) to newly allocated zone.
* Transforms YBR pixels into RGB pixels if any
- Transforms 3 planes R, G, B into a single RGB Plane
- DOES NOT transform Grey plane + 3 Palettes into a RGB Plane
+ * Transforms 3 planes R, G, B into a single RGB Plane
+ * DOES NOT transform Grey plane + 3 Palettes into a RGB Plane
* @return Pointer to newly allocated pixel data.
* \ NULL if alloc fails
*/
* \ingroup gdcmFile
* \brief
* @param fileName name of the file to be created
- * (any already existing file is over written)
+ * (any already existing file is overwritten)
* @return false if write fails
*/
* qui ne prennent en entrée QUE des images ACR ...
* \warning if a DICOM_V3 header is supplied,
* groups < 0x0008 and shadow groups are ignored)
- * \warning NO TEST is performed on processor "Endiannerie".
+ * \warning NO TEST is performed on processor "Endiannity".
* Ca fonctionnera correctement (?) sur processeur Intel
* (Equivalent a IdDcmWrite)
*
* @param fileName name of the file to be created
- * (any already existing file is over written)
+ * (any already existing file is overwritten)
* @return false if write fails
*/
* \ingroup gdcmFile
*
* @param fileName name of the file to be created
- * (any already existing file is over written)
+ * (any already existing file is overwritten)
* @param type file type (ExplicitVR, ImplicitVR, ...)
* @return false if write fails
*/
-bool gdcmFile::WriteBase (std::string FileName, FileType type) {
+bool gdcmFile::WriteBase (std::string fileName, FileType type) {
FILE * fp1;
- fp1 = fopen(FileName.c_str(),"wb");
+ fp1 = fopen(fileName.c_str(),"wb");
if (fp1 == NULL) {
- printf("Echec ouverture (ecriture) Fichier [%s] \n",FileName.c_str());
+ printf("Echec ouverture (ecriture) Fichier [%s] \n",fileName.c_str());
return (false);
}
if ( !OpenFile(exception_on_error))
return;
ParseHeader();
- wasUpdated = 0; // will be set to 1 if user adds an entry
LoadHeaderEntries();
CloseFile();
+ wasUpdated = 0; // will be set to 1 if user adds an entry
+ printLevel = 1; // 'Heavy' header print by default
}
/**
* @return
*/
void gdcmHeader::PrintPubEntry(std::ostream & os) {
- PubEntrySet.Print(os);
+ Print(os);
}
/**
// http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
// if Photometric Interpretation # PALETTE COLOR, no LUT to be done
- if (gdcmHeader::GetEntryByNumber(0x0028,0x0004) != "PALETTE COLOR ") {
+ if (GetEntryByNumber(0x0028,0x0004) != "PALETTE COLOR ") {
return NULL;
}
int lengthR, debR, nbitsR;
return elem->GetVR();
}
-/**
- * \ingroup gdcmHeader
- * \brief Searches within the public dictionary for element value of
- * a given tag.
- * @param group Group of the researched tag.
- * @param element Element of the researched tag.
- * @return Corresponding element value when it exists, and the string
- * GDCM_UNFOUND ("gdcm::Unfound") otherwise.
- */
-std::string gdcmHeader::GetPubEntryByNumber(guint16 group, guint16 element) {
- return PubEntrySet.GetEntryByNumber(group, element);
-}
/**
* \ingroup gdcmHeader
gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName);
if( dictEntry == NULL)
return false;
- return(PubEntrySet.SetEntryByNumber(content,
- dictEntry->GetGroup(),
- dictEntry->GetElement()));
+ return(SetEntryByNumber(content,
+ dictEntry->GetGroup(),
+ dictEntry->GetElement()));
}
/**
* \ingroup gdcmHeader
* \brief Accesses an existing gdcmHeaderEntry (i.e. a Dicom Element)
- * in the PubHeaderEntrySet 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 Dicom Element to modify
* @param element element of the Dicom Element to modify
*/
-bool gdcmHeader::SetPubEntryByNumber(std::string content, guint16 group,
- guint16 element)
-
-//TODO : homogeneiser les noms : SetPubElValByNumber
-// qui appelle PubHeaderEntrySet.SetHeaderEntryByNumber
-// pourquoi pas SetPubHeaderEntryByNumber ??
-{
- return ( PubEntrySet.SetEntryByNumber (content, group, element) );
+bool gdcmHeader::SetPubEntryByNumber(std::string content,
+ guint16 group,
+ guint16 element) {
+ TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ if ( ! tagHT.count(key))
+ 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 the stuff
+ //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 = ((tagHT.equal_range(key)).first)->second;
+
+ a-> SetValue(content);
+
+ //std::string vr = tagHT[key]->GetVR();
+ 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;
+ //tagHT[key]->SetLength(lgr);
+ a->SetLength(lgr);
+ return true;
}
+/**
+ * \ingroup gdcmHeader
+ * \brief Accesses an existing gdcmHeaderEntry (i.e. a Dicom Element)
+ * through it's (group, element) and modifies it's content with
+ * the given value.
+ * \warning Don't use any longer : use SetPubEntryByNumber
+ * @param content new value to substitute with
+ * @param group group of the Dicom Element to modify
+ * @param element element of the Dicom Element to modify
+ */
+bool gdcmHeader::SetEntryByNumber(std::string content,
+ guint16 group,
+ guint16 element) {
+ return SetPubEntryByNumber(content, group, element);
+}
+
/**
* \ingroup gdcmHeader
* \brief Accesses an existing gdcmHeaderEntry (i.e. a Dicom Element)
* @return 1 on success, 0 otherwise.
*/
-bool gdcmHeader::SetPubEntryLengthByNumber(guint32 length, guint16 group,
- guint16 element) {
- return ( PubEntrySet.SetEntryLengthByNumber (length, group, element) );
+bool gdcmHeader::SetPubEntryLengthByNumber(guint32 length,
+ guint16 group, guint16 element) {
+ TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ if ( ! tagHT.count(key))
+ return false;
+ if (length%2) length++; // length must be even
+ //tagHT[key]->SetLength(length);
+ ( ((tagHT.equal_range(key)).first)->second )->SetLength(length);
+
+ return true ;
}
+/**
+ * \ingroup gdcmHeader
+ * \brief Accesses an existing gdcmHeaderEntry (i.e. a Dicom Element)
+ * in the PubHeaderEntrySet of this instance
+ * through it's (group, element) and modifies it's length with
+ * the given value.
+ * \warning Don't use any longer : use SetPubEntryLengthByNumber
+ * @param length new length to substitute with
+ * @param group group of the ElVal to modify
+ * @param element element of the ElVal to modify
+ * @return 1 on success, 0 otherwise.
+ */
+
+bool gdcmHeader::SetEntryLengthByNumber(guint32 length,
+ guint16 group, guint16 element) {
+ return SetPubEntryLengthByNumber( length, group,element);
+}
/**
* \ingroup gdcmHeader
* \brief Searches within Header Entries (Dicom Elements) parsed with
* the public and private dictionaries
* for the element value of a given tag.
+ * \warning Don't use any longer : use GetPubEntryByName
* @param tagName name of the searched element.
* @return Corresponding element value when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
std::string gdcmHeader::GetEntryByNumber(guint16 group, guint16 element) {
- return GetPubEntryByNumber(group, element);
+ TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ if ( ! tagHT.count(key))
+ return GDCM_UNFOUND;
+ return tagHT.find(key)->second->GetValue();
}
+/**
+ * \ingroup gdcmHeader
+ * \brief Searches within the public dictionary for element value of
+ * a given tag.
+ * @param group Group of the researched tag.
+ * @param element Element of the researched tag.
+ * @return Corresponding element value when it exists, and the string
+ * GDCM_UNFOUND ("gdcm::Unfound") otherwise.
+ */
+std::string gdcmHeader::GetPubEntryByNumber(guint16 group, guint16 element) {
+ return GetEntryByNumber(group, element);
+}
+
+
/**
* \ingroup gdcmHeader
* \brief Searches within Header Entries (Dicom Elements) parsed with
TagKey key = gdcmDictEntry::TranslateToKey(dictEntry->GetGroup(),
dictEntry->GetElement());
- if ( PubEntrySet.GetTagHT().count(key) == 0 )
+ if ( GetPubEntry().count(key) == 0 )
return false;
int l = content.length();
if(l%2) { // Odd length are padded with a space (020H).
//p2=p.first; // iterator on the first synonym
//a=p2->second; // H Table target column (2-nd col)
// or, easier :
- a = ((PubEntrySet.GetTagHT().equal_range(key)).first)->second;
+ a = ((GetPubEntry().equal_range(key)).first)->second;
a-> SetValue(content);
std::string vr = a->GetVR();
CheckSwap();
while ( (newHeaderEntry = ReadNextHeaderEntry()) ) {
SkipHeaderEntry(newHeaderEntry);
- PubEntrySet.Add(newHeaderEntry);
+ Add(newHeaderEntry);
}
}
+
+
/**
* \ingroup gdcmHeader
* \brief
* @param fp file pointer on an already open file
- * @param type file type ( ImplicitVR, ExplicitVR, ...)
- * @return Boolean
- */
+ * @param type type of the File to be written
+ * (ACR-NEMA, ExplicitVR, ImplicitVR)
+ * @return always "True" ?!
+ */
bool gdcmHeader::Write(FILE * fp, FileType type) {
+// ==============
+// TODO The stuff has been rewritten using the chained list instead
+// of the H table
+// so we could remove the GroupHT from the gdcmHeader
+// To be checked
+// =============
+
// TODO : move the following lines (and a lot of others, to be written)
// to a future function CheckAndCorrectHeader
+
+ // Question :
+ // Comment pourrait-on savoir si le DcmHeader vient d'un fichier DicomV3 ou non
+ // (FileType est un champ de gdcmHeader ...)
+ // WARNING : Si on veut ecrire du DICOM V3 a partir d'un DcmHeader ACR-NEMA
+ // no way
+ // a moins de se livrer a un tres complique ajout des champs manquants.
+ // faire un CheckAndCorrectHeader (?)
+
if (type == ImplicitVR) {
std::string implicitVRTransfertSyntax = "1.2.840.10008.1.2";
// 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
- PubEntrySet.SetEntryLengthByNumber(18, 0x0002, 0x0010);
+ SetEntryLengthByNumber(18, 0x0002, 0x0010);
}
if (type == ExplicitVR) {
// 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
- PubEntrySet.SetEntryLengthByNumber(20, 0x0002, 0x0010);
+ SetEntryLengthByNumber(20, 0x0002, 0x0010);
}
- return PubEntrySet.Write(fp, type);
-}
+
+ if ( (type == ImplicitVR) || (type == ExplicitVR) )
+ UpdateGroupLength(false,type);
+ if ( type == ACR)
+ UpdateGroupLength(true,ACR);
+
+ WriteEntries(type, fp);
+ return(true);
+ }
/**
* \ingroup gdcmFile
gdcmHeaderEntry* a =NewHeaderEntryByNumber(Group, Elem);
if (a == NULL)
return false;
- PubEntrySet.Add(a);
+ Add(a);
}
- PubEntrySet.SetEntryByNumber(Value, Group, Elem);
+ SetPubEntryByNumber(Value, Group, Elem);
return(true);
}
gdcmHeaderEntry* nvHeaderEntry=NewHeaderEntryByNumber(Group, Elem);
// TODO : check if fails
- PubEntrySet.Add(nvHeaderEntry);
+ Add(nvHeaderEntry);
std::string v = Value;
- PubEntrySet.SetEntryByNumber(v, Group, Elem);
+ SetEntryByNumber(v, Group, Elem);
return(true);
}
* @param Value
* @param Group
* @param Elem
- * \return integer acts as a boolean
+ * \return boolean
*/
bool gdcmHeader::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 Elem ) {
std::string v = Value;
- PubEntrySet.SetEntryByNumber(v, Group, Elem);
+ SetEntryByNumber(v, Group, Elem);
return true;
}
//-----------------------------------------------------------------------------
// Protected
+
/**
* \ingroup gdcmHeader
- * \brief
- *
- * @return
+ * \brief retrieves a Dicom Element (the first one) using (group, element)
+ * \ warning (group, element) IS NOT an identifier inside the Dicom Header
+ * if you think it's NOT UNIQUE, check the count number
+ * and use iterators to retrieve ALL the Dicoms Elements within
+ * a given couple (group, element)
+ * @param group Group number of the searched Dicom Element
+ * @param element Element number of the searched Dicom Element
+ * @return
*/
-gdcmHeaderEntry *gdcmHeader::GetHeaderEntryByNumber(guint16 Group, guint16 Elem) {
- gdcmHeaderEntry *HeaderEntry = PubEntrySet.GetHeaderEntryByNumber(Group, Elem);
- if (!HeaderEntry) {
- dbg.Verbose(1, "gdcmHeader::GetHeaderEntryByNumber",
- "failed to Locate gdcmHeaderEntry");
+gdcmHeaderEntry* gdcmHeader::GetHeaderEntryByNumber(guint16 group, guint16 element) {
+ TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ if ( ! tagHT.count(key))
return NULL;
- }
- return HeaderEntry;
+ return tagHT.find(key)->second;
}
+
/**
* \ingroup gdcmHeader
* \brief Searches within the Header Entries for a Dicom Element of
/**
* \ingroup gdcmHeader
- * \brief Checks if a given HeaderEntry (group,number)
- * \ exists in the Public HeaderEntrySet
- * @param Group
- * @param Elem
- * @return boolean
+ * \brief Checks if a given Dicom Element exists
+ * \ within the H table
+ * @param group Group number of the searched Dicom Element
+ * @param element Element number of the searched Dicom Element
+ * @return number of occurences
*/
-bool gdcmHeader::CheckIfExistByNumber(guint16 Group, guint16 Elem ) {
- return (PubEntrySet.CheckIfExistByNumber(Group, Elem)>0);
+int gdcmHeader::CheckIfExistByNumber(guint16 group, guint16 element ) {
+ std::string key = gdcmDictEntry::TranslateToKey(group, element );
+ return (tagHT.count(key));
}
/**
return NULL;
}
- PubEntrySet.SetVoidAreaByNumber(a, Group, Elem);
+ SetVoidAreaByNumber(a, Group, Elem);
// TODO check the result
size_t l2 = fread(a, 1, l ,fp);
if(l != l2) {
/**
* \ingroup gdcmHeader
* \brief
- * @param entry Header Entry whose value shall be loaded.
+ * @param ElVal Header Entry whose length of the value shall be loaded.
* @return
*/
/**
* \ingroup gdcmHeader
- * \brief
- * @param ElVal
+ * \brief Skip a given Header Entry
+ * \warning NOT end user intended method !
+ * @param entry
* @return
*/
void gdcmHeader::SkipHeaderEntry(gdcmHeaderEntry * entry) {
guint32 FreeElem = 0;
gdcmDictEntry* NewEntry = (gdcmDictEntry*)0;
- FreeElem = PubEntrySet.GenerateFreeTagKeyInGroup(StuffGroup);
+ FreeElem = GenerateFreeTagKeyInGroup(StuffGroup);
if (FreeElem == UINT32_MAX) {
dbg.Verbose(1, "gdcmHeader::NewManualElValToPubDict",
"Group 0xffff in Public Dict is full");
NewEntry = Dicts->NewVirtualDictEntry(StuffGroup, FreeElem,
VR, "GDCM", NewTagName);
NewElVal = new gdcmHeaderEntry(NewEntry);
- PubEntrySet.Add(NewElVal);
+ Add(NewElVal);
return NewElVal;
}
#include "gdcmException.h"
#include "gdcmDictSet.h"
#include "gdcmHeaderEntry.h"
-#include "gdcmHeaderEntrySet.h"
+
+#include <stdio.h>
#include <map>
+#include <list> // for linking together *all* the Dicom Elements
//-----------------------------------------------------------------------------
typedef std::string VRKey;
typedef std::string VRAtr;
typedef std::map<VRKey, VRAtr> VRHT; // Value Representation Hash Table
+typedef std::multimap<TagKey, gdcmHeaderEntry*> TagHeaderEntryHT;
+typedef std::pair<TagKey, gdcmHeaderEntry*> PairHT;
+typedef std::pair<TagHeaderEntryHT::iterator,TagHeaderEntryHT::iterator> IterHT;
+
+typedef std::list<gdcmHeaderEntry*> ListTag; // for linking together the Elements
+
+// TODO : to be removed after re-writting gdcmHeaderEntrySet::UpdateGroupLength
+// using the chained list instead of the H table
+typedef std::string GroupKey;
+typedef std::map<GroupKey, int> GroupHT;
+
//-----------------------------------------------------------------------------
/*
- * \defgroup gdcmHedaer
+ * \defgroup gdcmHeader
* \brief
* The purpose of an instance of gdcmHeader is to act as a container of
* all the DICOM elements and their corresponding values (and
* The typical usage of instances of class gdcmHeader is to classify a set of
* dicom files according to header information e.g. to create a file hierarchy
* reflecting the Patient/Study/Serie informations, or extracting a given
- * SerieId. Accesing the content (image[s] or volume[s]) is beyond the
+ * SerieId. Accessing the content (image[s] or volume[s]) is beyond the
* functionality of this class and belongs to gdmcFile.
* \note The various entries of the explicit value representation (VR) shall
* be managed within a dictionary which is shared by all gdcmHeader
bool SetPubEntryByName (std::string content, std::string tagName);
bool SetPubEntryByNumber(std::string content, guint16 group, guint16 element);
- bool SetPubEntryLengthByNumber(guint32 lgr, guint16 group, guint16 element);
-
- inline ListTag & GetPubListEntry(void) { return PubEntrySet.GetListEntry();};
- inline TagHeaderEntryHT & GetPubEntry(void) { return PubEntrySet.GetTagHT(); };
-
+ bool SetPubEntryLengthByNumber(guint32 lgr, guint16 group, guint16 element);
+
+ /**
+ * \ingroup gdcmHeader
+ * \brief returns a ref to the Dicom Header H table (multimap)
+ * return the Dicom Header H table
+ */
+ inline TagHeaderEntryHT & GetPubEntry(void) { return tagHT; };
+
+ /**
+ * \ingroup gdcmHeader
+ * \brief returns a ref to the Dicom Header chained list
+ * return the Dicom Header chained list
+ */
+ inline ListTag & GetPubListEntry(void) { return listEntries; };
+
+ /**
+ * \ingroup gdcmHeader
+ * \brief Sets the print level for the Dicom Header
+ * \note 0 for Light Print; 1 for 'heavy' Print
+ */
+ void SetPrintLevel(int level) { printLevel = level; };
+
void PrintPubEntry(std::ostream & os = std::cout);
void PrintPubDict (std::ostream & os = std::cout);
bool SetEntryByName(std::string content,std::string tagName);
// bool SetEntryByNumber(std::string content,guint16 group, guint16 element);
-// inline ListTag & GetListEntry(void) { return PubHeaderEntrySet.GetListElem();};
-// inline TagHeaderEntryHT & GetListEntry(void) { return PubHeaderEntrySet.GetTagHt(); };
// Read (used in gdcmFile)
FILE *OpenFile(bool exception_on_error = false) throw(gdcmFileError);
inline int GetSwapCode(void) { return sw; }
guint16 SwapShort(guint16); // needed by gdcmFile
guint32 SwapLong(guint32); // for JPEG Files
+
+
+
+// ================= Was in EntrySet =================
+ void Print(std::ostream &);
+ void Add(gdcmHeaderEntry*);
+ bool SetEntryByNumber(std::string content, guint16 group, guint16 element);
+ bool SetEntryLengthByNumber(guint32 l, guint16 group, guint16 element);
+ bool SetVoidAreaByNumber(void *a, guint16 Group, guint16 Elem );
+ guint32 GenerateFreeTagKeyInGroup(guint16 group);
+// ===================================================
+
protected:
- bool CheckIfExistByNumber(guint16 Group, guint16 Elem );
+ int CheckIfExistByNumber(guint16 Group, guint16 Elem ); // int !
gdcmHeaderEntry *GetHeaderEntryByName (std::string Name);
gdcmHeaderEntry *GetHeaderEntryByNumber(guint16 group, guint16 element);
void * LoadEntryVoidArea (guint16 Group, guint16 Element);
+// ================= Was in EntrySet =================
+ void UpdateGroupLength(bool SkipSequence = false, FileType type = ImplicitVR);
+ void WriteEntries(FileType type, FILE *);
+// ===================================================
+
// Variables
FILE * fp;
FileType filetype; // ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown
// header
gdcmDict *RefShaDict;
- /// ELement VALueS parsed with the PUBlic dictionary.
- gdcmHeaderEntrySet PubEntrySet;
+ // ================ Was in gdcmHeaderEntrySet =========
+ TagHeaderEntryHT tagHT; // H Table (multimap), to provide fast access
+ ListTag listEntries; // chained list, to keep the 'spacial' ordering
+ int wasUpdated; // true if a gdcmHeaderEntry was added post parsing
+ int printLevel; // for PrintHeader
+ // ====================================================
+
// Refering underlying filename.
std::string filename;
int enableSequences;
- int wasUpdated; // true if a gdcmHeaderEntry was added post parsing
// FIXME sw should be an enum e.g.
//enum EndianType {
-// gdcmHeaderEntrySet.cxx
+// gdcmHeader2.cxx
//-----------------------------------------------------------------------------
#include "gdcmUtil.h"
-#include "gdcmHeaderEntrySet.h"
+#include "gdcmHeader.h"
#include "gdcmTS.h"
#ifdef GDCM_NO_ANSI_STRING_STREAM
# include <strstream>
#include <iomanip> // for std::ios::left, ...
-//-----------------------------------------------------------------------------
-// Constructor / Destructor
-/**
- * \ingroup gdcmHeaderEntrySet
- * \brief Destructor
- */
-gdcmHeaderEntrySet::~gdcmHeaderEntrySet() {
- for (TagHeaderEntryHT::iterator tag = tagHT.begin(); tag != tagHT.end(); ++tag) {
- gdcmHeaderEntry* EntryToDelete = tag->second;
- if ( EntryToDelete )
- delete EntryToDelete;
- tag->second=NULL;
- }
- tagHT.clear();
-}
-
//-----------------------------------------------------------------------------
// Print
/**
- * \ingroup gdcmHeaderEntrySet
+ * \ingroup gdcmHeader
* \brief prints the Dicom Elements of the gdcmHeader
* using both H table and Chained List
* @param os The output stream to be written to.
*/
-void gdcmHeaderEntrySet::Print(std::ostream & os) {
+void gdcmHeader::Print(std::ostream & os) {
size_t o;
unsigned short int g, e;
TSKey v;
std::string d2;
gdcmTS * ts = gdcmGlobal::GetTS();
-
std::ostringstream s;
/*
// DO NOT remove this code right now.
}
s << std::endl;
}
-*/
+*/
+
// List element
guint32 lgth;
char greltag[10]; //group element tag
e = (*i)->GetElement();
v = (*i)->GetValue();
o = (*i)->GetOffset();
- sprintf(greltag,"%04x|%04x",g,e);
+ sprintf(greltag,"%04x|%04x ",g,e);
d2 = _CreateCleanString(v); // replace non printable characters by '.'
- s << greltag << " lg : ";
- //lgth = (*i)->GetLength();
- lgth = (*i)->GetReadLength();
- if (lgth == 0xffffffff) {
- sprintf(st,"x(%ff)");
- s.setf(std::ios::left);
- s << std::setw(10-strlen(st)) << " ";
- s << st << " ";
- s.setf(std::ios::left);
- s << std::setw(8) << "-1";
- } else {
- sprintf(st,"x(%x)",lgth);
- s.setf(std::ios::left);
- s << std::setw(10-strlen(st)) << " ";
+ s << greltag ;
+
+ if (printLevel>=2) {
+ s << "lg : ";
+ lgth = (*i)->GetReadLength();
+ if (lgth == 0xffffffff) {
+ sprintf(st,"x(%ff)");
+ s.setf(std::ios::left);
+ s << std::setw(10-strlen(st)) << " ";
+ s << st << " ";
+ s.setf(std::ios::left);
+ s << std::setw(8) << "-1";
+ } else {
+ sprintf(st,"x(%x)",lgth);
+ s.setf(std::ios::left);
+ s << std::setw(10-strlen(st)) << " ";
+ s << st << " ";
+ s.setf(std::ios::left);
+ s << std::setw(8) << lgth;
+ }
+ s << " Off.: ";
+ sprintf(st,"x(%x)",o);
+ s << std::setw(10-strlen(st)) << " ";
s << st << " ";
- s.setf(std::ios::left);
- s << std::setw(8) << lgth;
+ s << std::setw(8) << o;
}
- s << " Off.: ";
- sprintf(st,"x(%x)",o);
- s << std::setw(10-strlen(st)) << " ";
- s << st << " ";
- s << std::setw(8) << o;
- s << "[" << (*i)->GetVR() << "] ";
- s.setf(std::ios::left);
- s << std::setw(66-(*i)->GetName().length()) << " ";
- s << "[" << (*i)->GetName()<< "] ";
- s << "[" << d2 << "]";
+ if (printLevel>=1) {
+ s << "[" << (*i)->GetVR() << "] ";
+ s.setf(std::ios::left);
+ s << std::setw(66-(*i)->GetName().length()) << " ";
+ }
+
+ s << "[" << (*i)->GetName()<< "]";
+ s << " [" << d2 << "]";
// Display the UID value (instead of displaying the rough code)
if (g == 0x0002) { // Any more to be displayed ?
if ( (e == 0x0010) || (e == 0x0002) )
//-----------------------------------------------------------------------------
// Public
/**
- * \ingroup gdcmHeaderEntrySet
+ * \ingroup gdcmHeader
* \brief add a new Dicom Element pointer to
* the H Table and to the chained List
* \warning push_bash in listEntries ONLY during ParseHeader
* \ when position to be taken care of
* @param newHeaderEntry
*/
-void gdcmHeaderEntrySet::Add(gdcmHeaderEntry * newHeaderEntry) {
+void gdcmHeader::Add(gdcmHeaderEntry * newHeaderEntry) {
// tagHT [newHeaderEntry->GetKey()] = newHeaderEntry;
tagHT.insert( PairHT( newHeaderEntry->GetKey(),newHeaderEntry) );
listEntries.push_back(newHeaderEntry);
+ wasUpdated = 1;
}
-/**
- * \ingroup gdcmHeaderEntrySet
- * \brief retrieves a Dicom Element (the first one) using (group, element)
- * \ warning (group, element) IS NOT an identifier inside the Dicom Header
- * if you think it's NOT UNIQUE, check the count number
- * and use iterators to retrieve ALL the Dicoms Elements within
- * a given couple (group, element)
- * @param group Group number of the searched Dicom Element
- * @param element Element number of the searched Dicom Element
- * @return
- */
-gdcmHeaderEntry* gdcmHeaderEntrySet::GetHeaderEntryByNumber(guint16 group, guint16 element) {
- TagKey key = gdcmDictEntry::TranslateToKey(group, element);
- if ( ! tagHT.count(key))
- return NULL;
- return tagHT.find(key)->second;
-}
-
-/**
- * \ingroup gdcmHeaderEntrySet
- * \brief Gets the value (string) of the target Dicom Element
- * @param group Group number of the searched Dicom Element
- * @param element Element number of the searched Dicom Element
- * @return
- */
-std::string gdcmHeaderEntrySet::GetEntryByNumber(guint16 group, guint16 element) {
- TagKey key = gdcmDictEntry::TranslateToKey(group, element);
- if ( ! tagHT.count(key))
- return GDCM_UNFOUND;
- return tagHT.find(key)->second->GetValue();
-}
/**
- * \ingroup gdcmHeaderEntrySet
- * \brief Sets the value (string) of the target Dicom Element
- * @param content string value of the Dicom Element
- * @param group Group number of the searched Dicom Element
- * @param element Element number of the searched Dicom Element
- * @return
- */
-bool gdcmHeaderEntrySet::SetEntryByNumber(std::string content,
- guint16 group, guint16 element) {
- TagKey key = gdcmDictEntry::TranslateToKey(group, element);
- if ( ! tagHT.count(key))
- 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 the stuff
- //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 = ((tagHT.equal_range(key)).first)->second;
-
- a-> SetValue(content);
-
- //std::string vr = tagHT[key]->GetVR();
- 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;
- //tagHT[key]->SetLength(lgr);
- a->SetLength(lgr);
- return true;
-}
-
-/**
- * \ingroup gdcmHeaderEntrySet
- * \brief Sets the value length of the Dicom Element
- * \warning : use with caution !
- * @param length
- * @param group Group number of the searched Dicom Element
- * @param element Element number of the searched Dicom Element
- * @return boolean
- */
-bool gdcmHeaderEntrySet::SetEntryLengthByNumber(guint32 length,
- guint16 group, guint16 element) {
- TagKey key = gdcmDictEntry::TranslateToKey(group, element);
- if ( ! tagHT.count(key))
- return false;
- if (length%2) length++; // length must be even
- //tagHT[key]->SetLength(length);
- ( ((tagHT.equal_range(key)).first)->second )->SetLength(length);
-
- return true ;
-}
-/**
- * \ingroup gdcmHeaderEntrySet
+ * \ingroup gdcmHeader
* \brief Sets a 'non string' value to a given Dicom Element
* @param area
* @param group Group number of the searched Dicom Element
* @param element Element number of the searched Dicom Element
* @return
*/
-bool gdcmHeaderEntrySet::SetVoidAreaByNumber(void * area,
+bool gdcmHeader::SetVoidAreaByNumber(void * area,
guint16 group, guint16 element) {
TagKey key = gdcmDictEntry::TranslateToKey(group, element);
if ( ! tagHT.count(key))
}
/**
- * \ingroup gdcmHeaderEntrySet
+ * \ingroup gdcmHeader
* \brief Generate a free TagKey i.e. a TagKey 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 gdcmHeaderEntrySet::GenerateFreeTagKeyInGroup(guint16 group) {
+guint32 gdcmHeader::GenerateFreeTagKeyInGroup(guint16 group) {
for (guint32 elem = 0; elem < UINT32_MAX; elem++) {
TagKey key = gdcmDictEntry::TranslateToKey(group, elem);
if (tagHT.count(key) == 0)
return UINT32_MAX;
}
-/**
- * \ingroup gdcmHeaderEntrySet
- * \brief Checks if a given Dicom Element exists
- * \ within the H table
- * @param group Group number of the searched Dicom Element
- * @param element Element number of the searched Dicom Element
- * @return number of occurences
- */
-int gdcmHeaderEntrySet::CheckIfExistByNumber(guint16 group, guint16 element ) {
- std::string key = gdcmDictEntry::TranslateToKey(group, element );
- return (tagHT.count(key));
-}
-
-// ==============
-// TODO to be re-written using the chained list instead of the H table
-// so we can remove the GroupHT from the gdcmHeader
-// =============
-/**
- * \ingroup gdcmHeaderEntrySet
- * \brief
- * @param _fp already open file pointer
- * @param type type of the File to be written
- * (ACR-NEMA, ExplicitVR, ImplicitVR)
- * @return always "True" ?!
- */
-bool gdcmHeaderEntrySet::Write(FILE * _fp, FileType type) {
-
- // Question :
- // Comment pourrait-on savoir si le DcmHeader vient d'un fichier DicomV3 ou non
- // (FileType est un champ de gdcmHeader ...)
- // WARNING : Si on veut ecrire du DICOM V3 a partir d'un DcmHeader ACR-NEMA
- // no way
- // a moins de se livrer a un tres complique ajout des champs manquants.
- // faire un CheckAndCorrectHeader (?)
-
- if ( (type == ImplicitVR) || (type == ExplicitVR) )
- UpdateGroupLength(false,type);
- if ( type == ACR)
- UpdateGroupLength(true,ACR);
-
- WriteEntries(type, _fp);
- return(true);
-}
-
//-----------------------------------------------------------------------------
// Protected
//-----------------------------------------------------------------------------
// Private
/**
- * \ingroup gdcmHeaderEntrySet
+ * \ingroup gdcmHeader
* \brief Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader
* \warning : to be re-written using the chained list instead of the H table.
* \warning : DO NOT use (doesn't work any longer because of the multimap)
* @param SkipSequence TRUE if we don't want to write Sequences (ACR-NEMA Files)
* @param type Type of the File (ExplicitVR,ImplicitVR, ACR, ...)
*/
-void gdcmHeaderEntrySet::UpdateGroupLength(bool SkipSequence, FileType type) {
+void gdcmHeader::UpdateGroupLength(bool SkipSequence, FileType type) {
guint16 gr, el;
std::string vr;
tk = g->first + "|0000"; // generate the element full tag
if ( tagHT.count(tk) == 0) { // if element 0x0000 not found
- gdcmDictEntry * tagZ = gdcmGlobal::GetDicts()->NewVirtualDictEntry(gr_bid, 0x0000, "UL");
+ gdcmDictEntry * tagZ = new gdcmDictEntry(gr_bid, 0x0000, "UL");
elemZ = new gdcmHeaderEntry(tagZ);
elemZ->SetLength(4);
Add(elemZ); // create it
}
/**
- * \ingroup gdcmHeaderEntrySet
+ * \ingroup gdcmHeader
* \brief writes on disc according to the requested format
* \ (ACR-NEMA, ExplicitVR, ImplicitVR) the image
* \ warning does NOT add the missing elements in the header :
* (ACR-NEMA, ExplicitVR, ImplicitVR)
* @param _fp already open file pointer
*/
-void gdcmHeaderEntrySet::WriteEntries(FileType type, FILE * _fp) {
+void gdcmHeader::WriteEntries(FileType type, FILE * _fp) {
guint16 gr, el;
guint32 lgr;
const char * val;
// uses now listEntries to iterate, not TagHt!
//
- // pb : gdcmHeaderEntrySet.Add does NOT update listEntries
+ // pb : gdcmHeader.Add does NOT update listEntries
// TODO : find a trick (in STL?) to do it, at low cost !
void *ptr;
+++ /dev/null
-// gdcmHeaderEntrySet.h
-//-----------------------------------------------------------------------------
-#ifndef GDCMHeaderEntrySet_H
-#define GDCMHeaderEntrySet_H
-
-#include "gdcmCommon.h"
-#include "gdcmHeaderEntry.h"
-
-#include <stdio.h>
-#include <map>
-#include <list> // for linking together *all* the Dicom Elements
-
-//-----------------------------------------------------------------------------
-typedef std::multimap<TagKey, gdcmHeaderEntry*> TagHeaderEntryHT;
-typedef std::pair<TagKey, gdcmHeaderEntry*> PairHT;
-typedef std::pair<TagHeaderEntryHT::iterator,TagHeaderEntryHT::iterator> IterHT;
-
-typedef std::list<gdcmHeaderEntry*> ListTag; // for linking together the Elements
-
-// TODO : to be removed after re-writting gdcmHeaderEntrySet::UpdateGroupLength
-// using the chained list instead of the H table
-typedef std::string GroupKey;
-typedef std::map<GroupKey, int> GroupHT;
-
-//-----------------------------------------------------------------------------
-/*
- * \defgroup gdcmHeaderEntrySet
- * \brief Container for a set of successfully parsed HeaderEntries
- * (i.e. Dicom Elements).
- */
-class GDCM_EXPORT gdcmHeaderEntrySet {
-public:
- ~gdcmHeaderEntrySet();
-
- void Print(std::ostream &);
-
- void Add(gdcmHeaderEntry*);
-
- gdcmHeaderEntry* GetHeaderEntryByNumber(guint16 group, guint16 element);
- std::string GetEntryByNumber(guint16 group, guint16 element);
-
- bool SetEntryByNumber(std::string content, guint16 group, guint16 element);
- bool SetEntryLengthByNumber(guint32 l, guint16 group, guint16 element);
- bool SetVoidAreaByNumber(void *a, guint16 Group, guint16 Elem );
-
- guint32 GenerateFreeTagKeyInGroup(guint16 group);
- int CheckIfExistByNumber(guint16 Group, guint16 Elem ); // int !
-
- /**
- * \ingroup gdcmHeaderEntrySet
- * \brief returns a ref to the Dicom Header H table (multimap)
- * return the Dicom Header H table
- */
- inline TagHeaderEntryHT & gdcmHeaderEntrySet::GetTagHT(void) { return tagHT; };
-
- /**
- * \ingroup gdcmHeaderEntrySet
- * \brief returns a ref to the Dicom Header chained list
- * return the Dicom Header chained list
- */
- inline ListTag & gdcmHeaderEntrySet::GetListEntry(void) { return listEntries; };
-
- bool Write(FILE *fp, FileType type);
-
-private:
- void UpdateGroupLength(bool SkipSequence = false, FileType type = ImplicitVR);
- void WriteEntries(FileType type, FILE *);
-
-// Variables
- TagHeaderEntryHT tagHT; // H Table (multimap), to provide fast access
- ListTag listEntries; // chained list, to keep the 'spacial' ordering
-};
-
-//-----------------------------------------------------------------------------
-#endif