* \ or uses an already built DICOMDIR, depending on 'parseDir' value
* @param Name name of the root directory (parseDir = true)
* name of the DICOMDIR (parseDir = false)
- * @param parseDir true if user wants to explore the directories
- * @param exception_on_error
+ * @param parseDir - true if user passed an entry point
+ * and wants to explore recursively the directories
+ * - false if user passed an already built DICOMDIR file
+ * and wants to use it
+ * @param exception_on_error whether we want to throw an exception or not
*/
gdcmDicomDir::gdcmDicomDir(const char *Name, bool parseDir,
bool exception_on_error):
- gdcmParser(Name,exception_on_error,true)
+ gdcmParser(Name,exception_on_error,true) // true : enable SeQuences
{
+ // que l'on ai passe un root directory ou un DICOMDIR
+ // et quelle que soit la valeur de parseDir,
+ // on a lance gdcmParser
+
startMethod= NULL;
progressMethod= NULL;
endMethod= NULL;
metaElems=NULL;
+// Si on passe un root directory, on est assuré de n'avoir rien ramené
+
if( GetListEntry().begin()==GetListEntry().end() )
{
+ // Si, en plus, parseDir == false, ca devrait etre une erreur
dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
if(parseDir)
CreateDicomDir();
}
+/*
+ * \ingroup gdcmDicomDir
+ * \brief Constructor : creates an empty gdcmDicomDir
+ * @param exception_on_error whether we want to throw an exception or not
+ */
+gdcmDicomDir::gdcmDicomDir(bool exception_on_error):
+ gdcmParser(exception_on_error)
+{
+ startMethod= NULL;
+ progressMethod= NULL;
+ endMethod= NULL;
+ startMethodArgDelete= NULL;
+ progressMethodArgDelete=NULL;
+ endMethodArgDelete= NULL;
+ startArg= NULL;
+ progressArg= NULL;
+ endArg= NULL;
+
+ progress=0.0;
+ abort=false;
+ string pathBidon = ""; // Sorry, NULL not allowed ...
+ SetElement(pathBidon, GDCM_DICOMDIR_META, NULL); // Set the META elements
+
+ AddDicomDirMetaToEnd(listEntries.begin(),--listEntries.end());
+}
+
+
/*
* \ingroup gdcmDicomDir
* \brief Canonical destructor
{
metaElems->SetPrintLevel(printLevel);
metaElems->Print(os);
- }
-
+ }
for(ListDicomDirPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
{
(*cc)->SetPrintLevel(printLevel);
- (*cc)->Print(os);
+ (*cc)->Print(os);
}
}
*/
void gdcmDicomDir::ParseDirectory(void)
{
- NewDicomDir(GetPath());
+ CreateDicomDirChainedList(GetPath());
CreateDicomDir();
}
* \brief writes on disc a DICOMDIR
* \ warning does NOT add the missing elements in the header :
* it's up to the user doing it !
+ * \todo : to be re-written using the DICOMDIR tree-like structure
+ * *not* the chained list
+ * (does NOT exist if the DICOMDIR is user-forged !)
* @param fileName file to be written to
* @return false only when fail to open
*/
+
bool gdcmDicomDir::Write(std::string fileName)
{
FILE * fp1;
fwrite(filePreamble,128,1,fp1);
fwrite("DICM",4,1,fp1);
free(filePreamble);
- UpdateDirectoryRecordSequenceLength();
- WriteEntries(fp1,DICOMDIR);
+ //UpdateDirectoryRecordSequenceLength(); // a reecrire en utilisant
+ // la structure arborescente JPR
+ WriteDicomDirEntries(fp1);
fclose(fp1);
return true;
}
+/**
+ * \ingroup gdcmParser
+ * \brief writes on disc according to the DICOMDIR format
+ * using the Chained List
+ * \todo a reecrire en utilisant la structure arborescente
+ * @param _fp already open file pointer
+ */
+
+void gdcmDicomDir::WriteDicomDirEntries(FILE *_fp)
+{
+ // TODO (?) tester les echecs en ecriture
+ // (apres chaque fwrite, dans le WriteEntry)
+
+ gdcmDicomDirMeta *ptrMeta;
+ ListDicomDirPatient::iterator itPatient;
+ ListDicomDirStudy::iterator itStudy;
+ ListDicomDirSerie::iterator itSerie;
+ ListDicomDirImage::iterator itImage;
+ ListTag::iterator i;
+
+ ptrMeta= GetDicomDirMeta();
+ for(i=ptrMeta->debut();i!=ptrMeta->fin();++i) {
+ WriteEntry(*i,_fp,DICOMDIR);
+ }
+
+ itPatient = GetDicomDirPatients().begin();
+ while ( itPatient != GetDicomDirPatients().end() ) {
+ for(i=(*itPatient)->debut();i!=(*itPatient)->fin();++i) {
+ WriteEntry(*i,_fp,DICOMDIR);
+ }
+ itStudy = ((*itPatient)->GetDicomDirStudies()).begin();
+ while (itStudy != (*itPatient)->GetDicomDirStudies().end() ) {
+ for(i=(*itStudy)->debut();i!=(*itStudy)->fin();++i) {
+ WriteEntry(*i,_fp,DICOMDIR);
+ }
+ itSerie = ((*itStudy)->GetDicomDirSeries()).begin();
+ while (itSerie != (*itStudy)->GetDicomDirSeries().end() ) {
+ for(i=(*itSerie)->debut();i!=(*itSerie)->fin();++i) {
+ WriteEntry(*i,_fp,DICOMDIR);
+ }
+ itImage = ((*itSerie)->GetDicomDirImages()).begin();
+ while (itImage != (*itSerie)->GetDicomDirImages().end() ) {
+ for(i=(*itImage)->debut();i!=(*itImage)->fin();++i) {
+ WriteEntry(*i,_fp,DICOMDIR);
+ }
+ ++itImage;
+ }
+ ++itSerie;
+ }
+ ++itStudy;
+ }
+ ++itPatient;
+ }
+}
+
//-----------------------------------------------------------------------------
// Protected
+
/*
* \ingroup gdcmDicomDir
- * \brief create a gdcmDicomDir from a root Directory
- * @param path entry point of the stree-like structure
+ * \brief create a gdcmHeader-like chained list from a root Directory
+ * @param path entry point of the tree-like structure
*/
-void gdcmDicomDir::NewDicomDir(std::string path)
+void gdcmDicomDir::CreateDicomDirChainedList(std::string path)
{
CallStartMethod();
- gdcmDirList fileList(path,1);
+ gdcmDirList fileList(path,1); // gets recursively the file list
unsigned int count=0;
ListHeader list;
gdcmHeader *header;
header=new gdcmHeader(it->c_str());
if(header->IsReadable())
- list.push_back(header);
+ list.push_back(header); // adds the file header to the chained list
else
delete header;
count++;
}
-
+ // sorts Patient/Study/Serie/
std::sort(list.begin(),list.end(),gdcmDicomDir::HeaderLessThan);
std::string tmp=fileList.GetDirName();
+ //for each Header of the chained list, add/update the Patient/Study/Serie/Image info
SetElements(tmp,list);
CallEndMethod();
}
+/*
+ * \ingroup gdcmDicomDir
+ * \brief adds a new Patient to a partially created DICOMDIR
+ */
+gdcmDicomDirPatient * gdcmDicomDir::NewPatient(void) {
+ std::list<gdcmElement> elemList;
+ std::list<gdcmElement>::iterator it;
+ guint16 tmpGr,tmpEl;
+ gdcmDictEntry *dictEntry;
+ gdcmHeaderEntry *entry;
+
+ elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirPatientElements();
+ std::list<gdcmHeaderEntry *>::iterator debInsertion, finInsertion, i,j;
+
+
+ debInsertion = metaElems->fin();
+ ++debInsertion;
+ finInsertion=debInsertion;
+
+ // for all the DicomDirPatient Elements
+ for(it=elemList.begin();it!=elemList.end();++it)
+ {
+ tmpGr=it->group;
+ tmpEl=it->elem;
+ dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
+ entry=new gdcmHeaderEntry(dictEntry);
+ entry->SetOffset(0); // just to avoid missprinting
+ entry->SetValue(it->value);
+
+ if(dictEntry->GetGroup()==0xfffe)
+ {
+ entry->SetLength(entry->GetValue().length());
+ }
+ else if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
+ {
+ entry->SetLength(4);
+ }
+ else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
+ {
+ entry->SetLength(2);
+ }
+ else if(dictEntry->GetVR()=="SQ")
+ {
+ entry->SetLength(0xffffffff);
+ }
+ else
+ {
+ entry->SetLength(entry->GetValue().length());
+ }
+
+ tagHT.insert( PairHT(entry->GetKey(),entry) ); // add in the (multimap) H Table
+ listEntries.insert(debInsertion ,entry); // en tete de liste des Patients
+ ++finInsertion;
+ }
+
+ i=metaElems->fin();
+ i++;
+
+ gdcmDicomDirPatient *p = new gdcmDicomDirPatient(i, --debInsertion,
+ &tagHT, &listEntries);
+ patients.push_front(p);
+ return p;
+}
+
/*
* \ingroup gdcmDicomDir
* \brief Get the DicomDir path
- * @param
*/
std::string gdcmDicomDir::GetPath(void)
{
return(path);
}
-
+/*
+ * \ingroup gdcmDicomDir
+ * \brief CallStartMethod
+ */
void gdcmDicomDir::CallStartMethod(void)
{
progress=0.0f;
if(startMethod)
startMethod(startArg);
}
-
+/*
+ * \ingroup gdcmDicomDir
+ * \brief CallProgressMethod
+ */
void gdcmDicomDir::CallProgressMethod(void)
{
if(progressMethod)
progressMethod(progressArg);
}
-
+/*
+ * \ingroup gdcmDicomDir
+ * \brief CallEndMethod
+ */
void gdcmDicomDir::CallEndMethod(void)
{
progress=1.0f;
*/
void gdcmDicomDir::CreateDicomDir()
{
- // The list is parsed. When a tag is found :
+ // The list is parsed.
+ // When a DicomDir tag ("PATIENT", "STUDY", "SERIE", "IMAGE") is found :
// 1 - we save the beginning iterator
// 2 - we continue to parse
// 3 - we find an other tag
gdcmDicomDirType type=gdcmDicomDir::GDCM_DICOMDIR_META;
ListTag::iterator begin;
- ListTag::iterator end;
+ ListTag::iterator end, end2;
begin=listEntries.begin();
end=begin;
std::string v=(*i)->GetValue();
if(v=="PATIENT ")
{
- end=i;
- AddObjectToEnd(type,begin,end);
-
+ end=end2=i;
+ AddObjectToEnd(type,begin,--end2);
type=gdcmDicomDir::GDCM_DICOMDIR_PATIENT;
begin=end;
}
if(v=="STUDY ")
{
- end=i;
- AddObjectToEnd(type,begin,end);
-
+ end=end2=i;
+ AddObjectToEnd(type,begin,--end2);
type=gdcmDicomDir::GDCM_DICOMDIR_STUDY;
begin=end;
}
if(v=="SERIES")
{
- end=i;
- AddObjectToEnd(type,begin,end);
-
+ end=end2=i;
+ AddObjectToEnd(type,begin,--end2);
type=gdcmDicomDir::GDCM_DICOMDIR_SERIE;
begin=end;
}
if(v=="IMAGE ")
{
- end=i;
- AddObjectToEnd(type,begin,end);
-
+ end=end2=i;
+ AddObjectToEnd(type,begin,--end2);
type=gdcmDicomDir::GDCM_DICOMDIR_IMAGE;
begin=end;
}
}
- end=GetListEntry().end();
+ end=end2=listEntries.end();
if(begin!=end)
- AddObjectToEnd(type,begin,end);
+ AddObjectToEnd(type,begin,--end2);
}
/*
* \ingroup gdcmDicomDir
- * \brief
+ * \brief AddObjectToEnd
* @param type
* @param begin
* @param end
{
if(metaElems)
delete metaElems;
- metaElems = new gdcmDicomDirMeta(begin,end);
+ metaElems = new gdcmDicomDirMeta(begin,end,&tagHT,&listEntries);
}
/*
* \ingroup gdcmDicomDir
- * \brief
+ * \brief AddDicomDirPatientToEnd
* @param begin
* @param end
*/
void gdcmDicomDir::AddDicomDirPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
{
- patients.push_back(new gdcmDicomDirPatient(begin,end));
+ patients.push_back(new gdcmDicomDirPatient(begin,end,&tagHT, &listEntries));
}
/*
* \ingroup gdcmDicomDir
- * \brief
+ * \brief AddDicomDirStudyToEnd
* @param begin
* @param end
*/
{
ListDicomDirPatient::iterator itp=patients.end();
itp--;
- (*itp)->AddDicomDirStudy(new gdcmDicomDirStudy(begin,end));
+ (*itp)->AddDicomDirStudy(new gdcmDicomDirStudy(begin,end,&tagHT, &listEntries));
}
}
/*
* \ingroup gdcmDicomDir
- * \brief
+ * \brief AddDicomDirSerieToEnd
* @param begin
* @param end
*/
{
ListDicomDirStudy::iterator itst=(*itp)->GetDicomDirStudies().end();
itst--;
- (*itst)->AddDicomDirSerie(new gdcmDicomDirSerie(begin,end));
+ (*itst)->AddDicomDirSerie(new gdcmDicomDirSerie(begin,end,&tagHT, &listEntries));
}
}
}
/*
* \ingroup gdcmDicomDir
+ * \brief AddDicomDirImageToEnd
* @param begin
* @param end
- * @param
*/
void gdcmDicomDir::AddDicomDirImageToEnd(ListTag::iterator begin,ListTag::iterator end)
{
{
ListDicomDirSerie::iterator its=(*itst)->GetDicomDirSeries().end();
its--;
- (*its)->AddDicomDirImage(new gdcmDicomDirImage(begin,end));
+ (*its)->AddDicomDirImage(new gdcmDicomDirImage(begin,end,&tagHT, &listEntries));
}
}
}
/*
* \ingroup gdcmDicomDir
- * \brief
+ * \brief for each Header of the chained list, add/update the Patient/Study/Serie/Image info
* @param path
* @param list
*/
-void gdcmDicomDir::SetElements(std::string &path,ListHeader &list)
+void gdcmDicomDir::SetElements(std::string &path, ListHeader &list)
{
std::string patPrevName="", patPrevID="";
std::string studPrevInstanceUID="", studPrevID="";
std::string studCurInstanceUID, studCurID;
std::string serCurInstanceUID, serCurID;
- SetElement(path,GDCM_DICOMDIR_NONE,NULL);
+ SetElement(path,GDCM_DICOMDIR_META,NULL);
ListTag::iterator debPat=listEntries.begin();
for(ListHeader::iterator it=list.begin();it!=list.end();++it)
/*
* \ingroup gdcmDicomDir
- * \brief
- * @param path
- * @param type
- * @param header
+ * \brief adds to the HTable and at the end of the Chained List
+ * the gdcmEntries (Dicom Elements) corresponding to the given type
+ * @param path file Path (only used when type = GDCM_DICOMDIR_IMAGE
+ * @param type gdcmObject type to create (GDCM_DICOMDIR_PATIENT, GDCM_DICOMDIR_STUDY, GDCM_DICOMDIR_SERIE ...)
+ * @param header gdcmHeader of the current file
*/
void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
{
case GDCM_DICOMDIR_IMAGE:
elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirImageElements();
break;
- case GDCM_DICOMDIR_NONE:
+ case GDCM_DICOMDIR_META:
elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirMetaElements();
break;
default:
else
{
if (header->GetEntryLengthByNumber(tmpGr,tmpEl)== 0)
- val=val=it->value;
+ val=it->value;
}
entry->SetValue(val);
entry->SetLength(entry->GetValue().length());
}
}
- //listEntries.push_back(entry);
- AddHeaderEntry(entry);
+ //AddHeaderEntry(entry); // both in H Table and in chained list
+ tagHT.insert( PairHT( entry->GetKey(),entry) );
+ listEntries.push_back(entry);
+ //wasUpdated = 1; // is private
}
}
gdcmDicomDir(const char *FileName,
bool parseDir = false,
bool exception_on_error = false);
-
+ gdcmDicomDir(bool exception_on_error = false);
+
~gdcmDicomDir(void);
void SetPrintLevel(int level) { printLevel = level; };
// Informations contained in the parser
virtual bool IsReadable(void);
- inline gdcmDicomDirMeta *GetDicomDirMeta() {return metaElems;};
- inline ListDicomDirPatient &GetDicomDirPatients() {return patients;};
+/**
+ * \ingroup gdcmDicomDir
+ * \brief returns a pointer to the gdcmDicomDirMeta for this DICOMDIR.
+ */
+ inline gdcmDicomDirMeta *GetDicomDirMeta()
+ {return metaElems;};
+/**
+ * \ingroup gdcmDicomDir
+ * \brief returns the PATIENT chained List for this DICOMDIR.
+ */
+ inline ListDicomDirPatient &GetDicomDirPatients()
+ {return patients;};
// Parsing
void ParseDirectory(void);
void SetEndMethodArgDelete(gdcmMethod *);
inline float GetProgress(void) {return(progress);};
-
- inline void AbortProgress(void) {abort=true;};
- inline bool IsAborted(void) {return(abort);};
+ inline void AbortProgress(void){abort=true; };
+ inline bool IsAborted(void) {return(abort); };
+
+// Adding
+ gdcmDicomDirPatient * NewPatient(void);
// Write
bool Write(std::string fileName);
} gdcmDicomDirType;
protected:
- void NewDicomDir(std::string path);
+ void CreateDicomDirChainedList(std::string path);
std::string GetPath(void);
void CallStartMethod(void);
private:
void CreateDicomDir(void);
void AddObjectToEnd(gdcmDicomDirType type,
- ListTag::iterator begin,ListTag::iterator end);
+ ListTag::iterator begin,ListTag::iterator end);
void AddDicomDirMetaToEnd (ListTag::iterator begin,ListTag::iterator end);
void AddDicomDirPatientToEnd(ListTag::iterator begin,ListTag::iterator end);
void AddDicomDirStudyToEnd (ListTag::iterator begin,ListTag::iterator end);
void UpdateDirectoryRecordSequenceLength(void);
static bool HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2);
-
+ void WriteDicomDirEntries(FILE *_fp);
+
+// Variables
+/**
+* \brief pointer on *the* gdcmObject 'DicomDirMeta Elements'
+*/
gdcmDicomDirMeta *metaElems;
+/**
+* \brief chained list of DicomDirPatient (to be exploited recursively)
+*/
ListDicomDirPatient patients;
gdcmMethod *startMethod;
/**
* \ingroup gdcmDicomDirElement
- * \brief constructor
+ * \brief constructor : populates the chained lists
+ * from the file 'Dicts/DicomDir.dic'
*/
gdcmDicomDirElement::gdcmDicomDirElement(void) {
std::string filename=gdcmDictSet::BuildDictPath() + std::string(DICT_ELEM);
//-----------------------------------------------------------------------------
typedef struct
{
- unsigned short int group;
+ /// DicomGroup number
+ unsigned short int group;
+ /// DicomElement number
unsigned short int elem;
+ /// value (coded as a std::string) of the Element
std::string value;
} gdcmElement;
void Print(std::ostream &os);
+
+/**
+ * \ingroup gdcmDicomDirElement
+ * \brief returns a reference to the chained List
+ * related to the META Elements of a DICOMDIR.
+ */
ListDicomDirMetaElem &GetDicomDirMetaElements(void)
{return(DicomDirMetaList);};
+/**
+ * \ingroup gdcmDicomDirElement
+ * \brief returns a reference to the chained List
+ * related to the PATIENT Elements of a DICOMDIR.
+ */
ListDicomDirPatientElem &GetDicomDirPatientElements(void)
{return(DicomDirPatientList);};
+/**
+ * \ingroup gdcmDicomDirElement
+ * \brief returns a reference to the chained List
+ * related to the STUDY Elements of a DICOMDIR.
+ */
ListDicomDirStudyElem &GetDicomDirStudyElements(void)
{return(DicomDirStudyList);};
+/**
+ * \ingroup gdcmDicomDirElement
+ * \brief returns a reference to the chained List
+ * related to the SERIE Elements of a DICOMDIR.
+ */
ListDicomDirSerieElem &GetDicomDirSerieElements(void)
{return(DicomDirSerieList);};
+/**
+ * \ingroup gdcmDicomDirElement
+ * \brief returns a reference to the chained List
+ * related to the IMAGE Elements of a DICOMDIR.
+ */
ListDicomDirImageElem &GetDicomDirImageElements(void)
{return(DicomDirImageList);};
//-----------------------------------------------------------------------------
// Constructor / Destructor
+
/**
* \ingroup gdcmDicomDirImage
* \brief
- * @param begin iterator of begin for the object
- * @param end iterator of end for the object
+ * @param begin iterator (inside the gdcmParser chained list)
+ * on the first Header Entry (i.e Dicom Element)
+ * related to this "IMAGE" part
+ * @param end iterator (inside the gdcmParser chained list)
+ * on the last Header Entry (i.e Dicom Element)
+ * related to this 'IMAGE' part
+ * @param ptagHT pointer to the HTable (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
+ * @param plistEntries pointer to the chained List (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
*/
-gdcmDicomDirImage::gdcmDicomDirImage(ListTag::iterator begin,ListTag::iterator end):
- gdcmObject(begin,end)
+gdcmDicomDirImage::gdcmDicomDirImage(ListTag::iterator begin,
+ ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT,
+ ListTag *plistEntries):
+ gdcmObject(begin,end,ptagHT,plistEntries)
{
}
/**
- * \ingroup gdcmImage
+ * \ingroup gdcmDicomDirImage
* \brief Canonical destructor.
*/
gdcmDicomDirImage::~gdcmDicomDirImage()
#include "gdcmObject.h"
//-----------------------------------------------------------------------------
-class GDCM_EXPORT gdcmDicomDirImage : public gdcmObject
-{
+class GDCM_EXPORT gdcmDicomDirImage : public gdcmObject {
public:
- gdcmDicomDirImage(ListTag::iterator begin,ListTag::iterator end);
+ gdcmDicomDirImage(ListTag::iterator begin,ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT, ListTag *plistEntries);
+
~gdcmDicomDirImage(void);
virtual void Print(std::ostream &os = std::cout);
+
+/**
+ * \ingroup gdcmDicomDirImage
+ * \brief TODO
+ */
+ gdcmDicomDirImage* NewImage(void);
+
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Constructor / Destructor
+
/**
- * \ingroup gdcmDicomDirMeta
- * \brief
- * @param begin iterator of begin for the object
- * @param end iterator of end for the object
- */
-gdcmDicomDirMeta::gdcmDicomDirMeta(ListTag::iterator begin,ListTag::iterator end):
- gdcmObject(begin,end)
+ * \ingroup gdcmMeta
+ * \brief Constructor
+ * @param begin iterator (inside the gdcmParser chained list)
+ * on the first Header Entry (i.e Dicom Element)
+ * related to the "META" part
+ * @param end iterator (inside the gdcmParser chained list)
+ * on the last Header Entry (i.e Dicom Element)
+ * related to the 'META' part
+ * @param ptagHT pointer to the HTable (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
+ * @param plistEntries pointer to the chained List (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
+ */
+gdcmDicomDirMeta::gdcmDicomDirMeta(ListTag::iterator begin,
+ ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT,
+ ListTag *plistEntries):
+ gdcmObject(begin,end,ptagHT,plistEntries)
{
}
class GDCM_EXPORT gdcmDicomDirMeta : public gdcmObject
{
public:
- gdcmDicomDirMeta(ListTag::iterator begin,ListTag::iterator end);
+ gdcmDicomDirMeta(ListTag::iterator begin,ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT, ListTag *plistEntries);
+
~gdcmDicomDirMeta(void);
virtual void Print(std::ostream &os = std::cout);
// gdcmDicomDirPatient.cxx
//-----------------------------------------------------------------------------
#include "gdcmDicomDirPatient.h"
-
+#include "gdcmDicomDirElement.h"
+#include "gdcmUtil.h"
//-----------------------------------------------------------------------------
// Constructor / Destructor
/**
* \ingroup gdcmDicomDirPatient
- * \brief
- * @param begin iterator of begin for the object
- * @param end iterator of end for the object
+ * \brief Constructor
+ * @param begin iterator (inside the gdcmParser chained list)
+ * on the first Header Entry (i.e Dicom Element)
+ * related to this "PATIENT" part
+ * @param end iterator (inside the gdcmParser chained list)
+ * on the last Header Entry (i.e Dicom Element)
+ * related to this 'PATIENT' part
+ * @param ptagHT pointer to the HTable (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
+ * @param plistEntries pointer to the chained List (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
*/
-gdcmDicomDirPatient::gdcmDicomDirPatient(ListTag::iterator begin,ListTag::iterator end):
- gdcmObject(begin,end)
+gdcmDicomDirPatient::gdcmDicomDirPatient(ListTag::iterator begin,
+ ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT,
+ ListTag *plistEntries):
+ gdcmObject(begin,end,ptagHT,plistEntries)
{
}
//-----------------------------------------------------------------------------
// Public
+/*
+ * \ingroup gdcmDicomDir
+ * \brief adds a new Patient at the begining of the PatientList
+ * of a partially created DICOMDIR
+ */
+gdcmDicomDirStudy * gdcmDicomDirPatient::NewStudy(void) {
+ std::list<gdcmElement> elemList;
+ elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirStudyElements();
+
+ FillObject(elemList);
+ gdcmDicomDirStudy *st = new gdcmDicomDirStudy(i, j, ptagHT, plistEntries);
+ studies.push_front(st);
+ return st;
+
+
+}
+
//-----------------------------------------------------------------------------
// Protected
class GDCM_EXPORT gdcmDicomDirPatient : public gdcmObject
{
public:
- gdcmDicomDirPatient(ListTag::iterator begin,ListTag::iterator end);
+ gdcmDicomDirPatient(ListTag::iterator begin,ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT, ListTag *plistEntries);
~gdcmDicomDirPatient(void);
virtual void Print(std::ostream &os = std::cout);
-
- inline ListDicomDirStudy &GetDicomDirStudies() {return studies;};
- inline void AddDicomDirStudy(gdcmDicomDirStudy *obj) {studies.push_back(obj);};
-
+/**
+ * \ingroup gdcmDicomDirPatient
+ * \brief returns the STUDY chained List for this PATIENT.
+ */
+ inline ListDicomDirStudy &GetDicomDirStudies()
+ {return studies;};
+/**
+ * \ingroup gdcmDicomDirPatient
+ * \brief adds the passed STUDY to the STUDY chained List for this PATIENT.
+ */
+ inline void AddDicomDirStudy(gdcmDicomDirStudy *obj)
+ {studies.push_back(obj);};
+/**
+ * \ingroup gdcmDicomDirPatient
+ * \brief TODO
+ */
+ gdcmDicomDirStudy* NewStudy(void);
+
private:
+
+/**
+* \brief chained list of DicomDirStudy
+*/
ListDicomDirStudy studies;
};
// gdcmDicomDirSerie.cxx
//-----------------------------------------------------------------------------
#include "gdcmDicomDirSerie.h"
-
+#include "gdcmDicomDirElement.h"
+#include "gdcmUtil.h"
//-----------------------------------------------------------------------------
// Constructor / Destructor
/**
* \ingroup gdcmDicomDirSerie
* \brief
- * @param begin iterator of begin for the object
- * @param end iterator of end for the object
+ * @param begin iterator (inside the gdcmParser chained list)
+ * on the first Header Entry (i.e Dicom Element)
+ * related to this "SERIE" part
+ * @param end iterator (inside the gdcmParser chained list)
+ * on the last Header Entry (i.e Dicom Element)
+ * related to this 'SERIE' part
+ * @param ptagHT pointer to the HTable (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
+ * @param plistEntries pointer to the chained List (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
*/
-gdcmDicomDirSerie::gdcmDicomDirSerie(ListTag::iterator begin,ListTag::iterator end):
- gdcmObject(begin,end)
+gdcmDicomDirSerie::gdcmDicomDirSerie(ListTag::iterator begin,
+ ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT,
+ ListTag *plistEntries ):
+ gdcmObject(begin,end,ptagHT,plistEntries)
{
}
//-----------------------------------------------------------------------------
// Public
+/*
+ * \ingroup gdcmDicomSerie
+ * \brief adds a new Image to a partially created DICOMDIR
+ */
+gdcmDicomDirImage * gdcmDicomDirSerie::NewImage(void) {
+ std::list<gdcmElement> elemList;
+ elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirImageElements();
+
+ FillObject(elemList);
+ gdcmDicomDirImage *st = new gdcmDicomDirImage(i, j, ptagHT, plistEntries);
+ images.push_front(st);
+ return st;
+
+}
//-----------------------------------------------------------------------------
// Protected
class GDCM_EXPORT gdcmDicomDirSerie : public gdcmObject
{
public:
- gdcmDicomDirSerie(ListTag::iterator begin,ListTag::iterator end);
+ gdcmDicomDirSerie(ListTag::iterator begin,ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT, ListTag *plistEntries);
~gdcmDicomDirSerie(void);
virtual void Print(std::ostream &os = std::cout);
+/**
+ * \ingroup gdcmDicomDirSerie
+ * \brief returns the IMAGE chained List for this SERIE.
+ */
+ inline ListDicomDirImage &GetDicomDirImages()
+ {return images;};
+/**
+ * \ingroup gdcmDicomDirSerie
+ * \brief adds the passed IMAGE to the IMAGE chained List for this SERIE.
+ */
+ inline void AddDicomDirImage(gdcmDicomDirImage *obj)
+ {images.push_back(obj);};
- inline ListDicomDirImage &GetDicomDirImages() {return images;};
- inline void AddDicomDirImage(gdcmDicomDirImage *obj) {images.push_back(obj);};
-
+/**
+ * \ingroup gdcmDicomDirSerie
+ * \brief TODO
+ */
+ gdcmDicomDirImage* NewImage(void);
+
private:
+/**
+* \brief chained list of DicomDirImages
+*/
ListDicomDirImage images;
};
// gdcmDicomDirStudy.cxx
//-----------------------------------------------------------------------------
#include "gdcmDicomDirStudy.h"
-
+#include "gdcmDicomDirElement.h"
+#include "gdcmUtil.h"
//-----------------------------------------------------------------------------
// Constructor / Destructor
+
/**
* \ingroup gdcmDicomDirStudy
- * \brief
- * @param begin iterator of begin for the object
- * @param end iterator of end for the object
+ * \brief constructor
+ * @param begin iterator (inside the gdcmParser chained list)
+ * on the first Header Entry (i.e Dicom Element)
+ * related to this "STUDY" part
+ * @param end iterator (inside the gdcmParser chained list)
+ * on the last Header Entry (i.e Dicom Element)
+ * related to this 'STUDY' part
+ * @param ptagHT pointer to the HTable (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
+ * @param plistEntries pointer to the chained List (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
*/
-gdcmDicomDirStudy::gdcmDicomDirStudy(ListTag::iterator begin,ListTag::iterator end):
- gdcmObject(begin,end)
+gdcmDicomDirStudy::gdcmDicomDirStudy(ListTag::iterator begin,
+ ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT,
+ ListTag *plistEntries):
+ gdcmObject(begin,end,ptagHT,plistEntries)
{
}
//-----------------------------------------------------------------------------
// Public
+/*
+ * \ingroup gdcmDicomStudy
+ * \brief adds a new Serie at the begining of the SerieList
+ * of a partially created DICOMDIR
+ */
+gdcmDicomDirSerie * gdcmDicomDirStudy::NewSerie(void) {
+
+ std::list<gdcmElement> elemList;
+ elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirSerieElements();
+
+ FillObject(elemList);
+ gdcmDicomDirSerie *st = new gdcmDicomDirSerie(i, j, ptagHT, plistEntries);
+ series.push_front(st);
+ return st;
+}
//-----------------------------------------------------------------------------
// Protected
//-----------------------------------------------------------------------------
class GDCM_EXPORT gdcmDicomDirStudy : public gdcmObject {
public:
- gdcmDicomDirStudy(ListTag::iterator begin,ListTag::iterator end);
+ gdcmDicomDirStudy(ListTag::iterator begin,ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT, ListTag *plistEntries);
+
~gdcmDicomDirStudy(void);
virtual void Print(std::ostream &os = std::cout);
+/**
+ * \ingroup gdcmDicomDirStudy
+ * \brief returns the SERIE chained List for this STUDY.
+ */
+ inline ListDicomDirSerie &GetDicomDirSeries()
+ {return series;};
+/**
+ * \ingroup gdcmDicomDirStudy
+ * \brief adds the passed SERIE to the SERIE chained List for this STUDY.
+ */
+ inline void AddDicomDirSerie(gdcmDicomDirSerie *obj)
+ {series.push_back(obj);};
- inline ListDicomDirSerie &GetDicomDirSeries() {return series;};
- inline void AddDicomDirSerie(gdcmDicomDirSerie *obj) {series.push_back(obj);};
-
+/**
+ * \ingroup gdcmDicomDirStudy
+ * \brief TODO
+ */
+ gdcmDicomDirSerie* NewSerie(void);
+
private:
+/**
+* \brief chained list of DicomDirSeries (to be exploited recursively)
+*/
ListDicomDirSerie series;
};
inline TagKeyHT & gdcmDict::GetEntries(void) { return KeyHt; }
private:
+ /// ASCII file holding the Dictionnary
std::string filename;
-
/// Access through TagKey (see alternate access with NameHt)
TagKeyHT KeyHt;
/// Access through TagName (see alternate access with KeyHt)
inline std::string GetKey(void) { return key; }
private:
- // FIXME : were are the group and element used except from building up
+ // FIXME : where are the group and element used except from building up
// a TagKey. If the answer is nowhere then there is no need
// to store the group and element independently.
+ //
+ // --> EVERYWHERE ! The alternate question would be :
+ // What's TagKey used for ?
+
+ /// DicomGroup number
guint16 group; // e.g. 0x0010
+ /// DicomElement number
guint16 element; // e.g. 0x0103
- std::string vr; // Value Representation i.e. some clue about the nature
- // of the data represented e.g. "FD" short for
- // "Floating Point Double"
+ /// Value Representation i.e. some clue about the nature
+ /// of the data represented e.g. "FD" short for
+ /// "Floating Point Double"
+ std::string vr;
+
// CLEANME: find the official dicom name for this field !
- std::string fourth; // Fourth field containing some semantics.
- //(Group Name abbr.)
- std::string name; // e.g. "Patient_Name"
- TagKey key; // Redundant with (group, element) but we add it
- // on efficiency purposes.
-
+
+ ///Fourth field containing some semantics.
+ ///(Group Name abbr.)
+ /// DON'T USER ANY LONGER !
+ std::string fourth;
+ /// e.g. "Patient_Name"
+ std::string name;
+ /// Redundant with (group, element) but we add it
+ /// on efficiency purposes.
+ TagKey key;
+
// DCMTK has many fields for handling a DictEntry (see below). What are the
// relevant ones for gdcmlib ?
// struct DBI_SimpleEntry {
/*
* \ingroup gdcmDirList
* \brief Constructor
- * @param
+ * @param dirName
+ * @param recursive
*/
gdcmDirList::gdcmDirList(std::string dirName,bool recursive)
{
bool gdcm_read_RLE_file (FILE *fp,void * image_buffer);
// Variables
- gdcmHeader *Header; // Header to use to load the file
+ /// Header to use to load the file
+ gdcmHeader *Header;
bool SelfHeader;
void* PixelData;
- size_t lgrTotaleRaw; // Area length to receive the pixels
- size_t lgrTotale; // Area length to receive the RGB pixels
- // from Grey Plane + Palette Color
- int PixelRead; // ==1 if GetImageDataRaw was used
- // ==0 if GetImageData was used
- // ==-1 if ImageData never read.
-
- int Parsed; // weather already parsed
- std::string OrigFileName; // To avoid file overwrite
+
+ /// Area length to receive the pixels
+ size_t lgrTotaleRaw;
+
+ /// Area length to receive the RGB pixels
+ /// from Grey Plane + Palette Color
+ size_t lgrTotale;
+
+ /// ==1 if GetImageDataRaw was used
+ /// ==0 if GetImageData was used
+ /// ==-1 if ImageData never read
+ int PixelRead;
+ .
+ /// weather already parsed
+ int Parsed;
+
+ /// To avoid file overwrite
+ std::string OrigFileName;
};
//-----------------------------------------------------------------------------
// Variables
gdcmDictEntry *entry;
- guint32 UsableLength; // Updated from ReadLength, by FixFoungLentgh()
- // for fixing a bug in the header
- // or helping the parser going on
-
- guint32 ReadLength; // Length actually read on disk
- // (before FixFoundLength)
- // ReadLength will be updated only when
- // FixFoundLength actually fixes a bug in the header,
- // not when it performs a trick to help the Parser
- // going on.
- // *for internal* use only
-
- bool ImplicitVR; // Even when reading explicit vr files, some
- // elements happen to be implicit. Flag them here
- // since we can't use the entry->vr without breaking
- // the underlying dictionary.
+ /// Updated from ReadLength, by FixFoungLentgh()
+ /// for fixing a bug in the header
+ /// or helping the parser going on
+ guint32 UsableLength;
+ /// Length actually read on disk
+ /// (before FixFoundLength)
+ /// ReadLength will be updated only when
+ /// FixFoundLength actually fixes a bug in the header,
+ /// not when it performs a trick to help the Parser
+ /// going on.
+ /// *for internal* use only
+ guint32 ReadLength;
+ /// Even when reading explicit vr files, some
+ /// elements happen to be implicit. Flag them here
+ /// since we can't use the entry->vr without breaking
+ /// the underlying dictionary.
+ bool ImplicitVR;
+
std::string value;
- void *voidArea; // unsecure memory area to hold 'non string' values
- // (ie : Lookup Tables, overlays)
- size_t Offset; // Offset from the begining of file for direct user access
+
+ /// unsecure memory area to hold 'non string' values
+ /// (ie : Lookup Tables, overlays)
+ void *voidArea;
+ /// Offset from the begining of file for direct user access
+ size_t Offset;
+
int printLevel;
};
// Constructor / Destructor
/**
* \ingroup gdcmObject
- * \brief
- * @param begin iterator of begin for the object
- * @param end iterator of end for the object
+ * \brief Constructor
+ * @param begin iterator on the first Header Entry (i.e Dicom Element)
+ * related to this 'Object'
+ * @param end iterator on the last Header Entry
+ * (i.e Dicom Element) related to this 'Object'
+ * @param ptagHT pointer to the HTable (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
+ * @param plistEntries pointer to the chained List (gdcmObject needs it
+ * to build the gdcmHeaderEntries)
*/
-gdcmObject::gdcmObject(ListTag::iterator begin,ListTag::iterator end)
-{
- beginObj=begin;
- endObj=end;
-
- if(beginObj==endObj)
+gdcmObject::gdcmObject(ListTag::iterator begin, ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT, ListTag *plistEntries) {
+ beginObj = begin;
+ endObj = end;
+ this->ptagHT = ptagHT;
+ this->plistEntries = plistEntries;
+ if(begin==end)
dbg.Verbose(0, "gdcmObject::gdcmObject empty list");
}
* \ingroup gdcmObject
* \brief Canonical destructor.
*/
-gdcmObject::~gdcmObject(void)
-{
+gdcmObject::~gdcmObject(void) {
}
//-----------------------------------------------------------------------------
* \brief Prints the Object
* @return
*/
-void gdcmObject::Print(std::ostream &os)
-{
- if(printLevel>=0)
- {
- for(ListTag::iterator i=beginObj;i!=endObj;++i)
- {
+void gdcmObject::Print(std::ostream &os) {
+ if(printLevel>=0) {
+ ListTag::iterator i;
+ //for(ListTag::iterator i=beginObj;i!=endObj;++i) // JPR
+ for(i=beginObj;;++i) {
(*i)->SetPrintLevel(printLevel);
(*i)->Print(os);
+ if (i == endObj) break;
}
}
}
// Public
/**
* \ingroup gdcmObject
- * \brief Get an entry by number
+ * \brief Get the value of an Header Entries (i.e Dicom Element) by number
* @return
*/
-std::string gdcmObject::GetEntryByNumber(guint16 group, guint16 element)
-{
- for(ListTag::iterator i=beginObj;i!=endObj;++i)
- {
+std::string gdcmObject::GetEntryByNumber(guint16 group, guint16 element) {
+ //for(ListTag::iterator i=beginObj;i!=endObj;++i) // JPR
+ for(ListTag::iterator i=beginObj;;++i) {
if ( (*i)->GetGroup()==group && (*i)->GetElement()==element)
return (*i)->GetValue();
- }
-
+ if (i == endObj) break;
+ }
return GDCM_UNFOUND;
}
/**
* \ingroup gdcmObject
- * \brief Get an entry by name
- * @param name name of the searched element.
+ * \brief Get the value of an Header Entries (i.e Dicom Element) by name
+ * @param name : name of the searched element.
* @return
*/
-std::string gdcmObject::GetEntryByName(TagName name)
-{
+std::string gdcmObject::GetEntryByName(TagName name) {
gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict();
gdcmDictEntry *dictEntry = (*PubDict).GetDictEntryByName(name);
return GetEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement());
}
+/**
+ * \ingroup gdcmParser
+ * \brief Sets Entry (Dicom Element) value of an element,
+ * specified by it's tag (Group, Number)
+ * and the length, too ...
+ * @param val string value to set
+ * @param group Group of the searched tag.
+ * @param element Element of the searched tag.
+ * @return true if element was found, else false
+ */
+ bool gdcmObject::SetEntryByNumber(std::string val,guint16 group,
+ guint16 element) {
+
+ //for(ListTag::iterator i=beginObj;i!=endObj;++i) // JPR
+ for(ListTag::iterator i=beginObj;;++i) {
+ if ( (*i)->GetGroup()==group && (*i)->GetElement()==element) {
+ (*i)->SetValue(val);
+ (*i)->SetLength(val.length()+1);
+ return true;
+ }
+ if (i == endObj) break;
+ }
+ return false;
+}
/**
* \ingroup gdcmObject
- * \brief Get all entries in a hash table
+ * \brief Builds a hash table (multimap) containing
+ * pointers to all Header Entries (i.e Dicom Element)
+ * related to this 'object'
* @return
*/
-TagHeaderEntryHT gdcmObject::GetEntry(void)
-{
+TagHeaderEntryHT gdcmObject::GetEntry(void) {
TagHeaderEntryHT HT;
-
- for(ListTag::iterator it=beginObj;it!=endObj;++it)
- {
- HT.insert( PairHT( (*it)->GetKey(),(*it)) );
+ //for(ListTag::iterator i=beginObj;i!=endObj;++i) // JPR
+ for(ListTag::iterator i=beginObj;;++i) {
+ HT.insert( PairHT( (*i)->GetKey(),(*i)) );
+ if (i == endObj) break;
}
-
return(HT);
}
/**
* \ingroup gdcmObject
- * \brief Get all entries in a list
+ * \brief Builds a Chained List containing
+ * pointers to all Header Entries (i.e Dicom Element)
+ * related to this 'object'
* @return
*/
-ListTag gdcmObject::GetListEntry(void)
-{
+ListTag gdcmObject::GetListEntry(void) {
ListTag list;
-
- for(ListTag::iterator it=beginObj;it!=endObj;++it)
- {
- list.push_back(*it);
+ //for(ListTag::iterator i=beginObj;i!=endObj;++i) // JPR
+ for(ListTag::iterator i=beginObj;;++i) {
+ list.push_back(*i);
+ if (i == endObj) break;
}
-
return(list);
}
+
//-----------------------------------------------------------------------------
// Protected
-
+/*
+ * \ingroup gdcmObject
+ * \brief add the 'Object' related Dicom Elements to the listEntries
+ * of a partially created DICOMDIR
+ */
+void gdcmObject::FillObject(std::list<gdcmElement> elemList) {
+ std::list<gdcmElement>::iterator it;
+ guint16 tmpGr,tmpEl;
+ gdcmDictEntry *dictEntry;
+ gdcmHeaderEntry *entry;
+
+ debInsertion = this->fin();
+ ++debInsertion;
+ finInsertion=debInsertion;
+
+ for(it=elemList.begin();it!=elemList.end();++it)
+ {
+ tmpGr=it->group;
+ tmpEl=it->elem;
+ dictEntry=gdcmGlobal::GetDicts()->GetDefaultPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
+ entry=new gdcmHeaderEntry(dictEntry);
+ entry->SetOffset(0); // just to avoid missprinting //JPR
+ entry->SetValue(it->value);
+
+ if(dictEntry->GetGroup()==0xfffe)
+ {
+ entry->SetLength(entry->GetValue().length());
+ }
+ else if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
+ {
+ entry->SetLength(4);
+ }
+ else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
+ {
+ entry->SetLength(2);
+ }
+ else if(dictEntry->GetVR()=="SQ")
+ {
+ entry->SetLength(0xffffffff);
+ }
+ else
+ {
+ entry->SetLength(entry->GetValue().length());
+ }
+ ptagHT->insert( PairHT(entry->GetKey(),entry) ); // add in the (multimap) H Table
+ plistEntries->insert(debInsertion ,entry); // en tete de liste des Patients
+ ++finInsertion;
+ }
+
+ i=fin();
+ i++;
+ j=debInsertion;
+ j--;
+}
//-----------------------------------------------------------------------------
// Private
#include "gdcmCommon.h"
#include "gdcmHeaderEntry.h"
#include "gdcmParser.h"
-
+#include "gdcmDicomDirElement.h"
//-----------------------------------------------------------------------------
class gdcmObject;
typedef std::list<gdcmObject *> ListContent;
class GDCM_EXPORT gdcmObject
{
public:
- gdcmObject(ListTag::iterator begin,ListTag::iterator end);
+ gdcmObject(ListTag::iterator begin,ListTag::iterator end,
+ TagHeaderEntryHT *ptagHT, ListTag *plistEntries);
~gdcmObject(void);
void SetPrintLevel(int level) { printLevel = level; };
std::string GetEntryByNumber(guint16 group, guint16 element);
std::string GetEntryByName(TagName name);
-
+ bool SetEntryByNumber(std::string val,guint16 group,guint16 element);
+
TagHeaderEntryHT GetEntry(void);
ListTag GetListEntry(void);
- ListTag::iterator debut(void) { return(beginObj);}
- ListTag::iterator fin (void) { return(endObj); }
+/**
+ * \ingroup gdcmObject
+ * \brief returns an iterator on the first Header Entry (i.e Dicom Element),
+ * inside the DICOMDIR chained list,
+ * related to this 'Object'
+ * @return
+ */
+ ListTag::iterator debut(void)
+ { return(beginObj);}
+/**
+ * \ingroup gdcmObject
+ * \brief returns an iterator on the last Header Entry (i.e Dicom Element),
+ * inside the DICOMDIR chained list,
+ * related to this 'Object'
+ * @return
+ */
+ ListTag::iterator fin (void)
+ { return(endObj); }
protected:
-
+
+void FillObject(std::list<gdcmElement> elemList);
+
+/**
+* \brief iterator on the first Header Entry (i.e Dicom Element),
+* inside the DICOMDIR chained list,
+* related to this 'Object'
+*/
ListTag::iterator beginObj;
+/**
+* \brief iterator on the last Header Entry (i.e Dicom Element),
+* inside the DICOMDIR chained list,
+* related to this 'Object'
+*/
ListTag::iterator endObj;
+/**
+* \brief pointer to the HTable of the gdcmParser,
+* (because we don't know it within any gdcmObject)
+*/
+ TagHeaderEntryHT *ptagHT;
+/**
+* \brief pointer to the Chained List of the gdcmParser,
+* (because we don't know it within any gdcmObject)
+*/
+ ListTag *plistEntries;
+/**
+* \brief
+*/
int printLevel;
+
+/// used to pass variables to FillObject function
+/// Work as 'global' variables
+ std::list<gdcmHeaderEntry *>::iterator debInsertion, finInsertion, i,j;
private:
+
};
//-----------------------------------------------------------------------------
//
// Other usefull abreviations :
- //Radiographic view associated with Patient Position (0018,5100).
- // Defined Terms:
+ // Radiographic view associated with Patient Position (0018,5100).
+ // Defined Terms:
//
// AP = Anterior/Posterior
// PA = Posterior/Anterior
* \ingroup gdcmParser
* \brief constructor
* @param inFilename
- * @param exception_on_error
+ * @param exception_on_error whether we throw an exception or not
* @param enable_sequences = true to allow the header
* to be parsed *inside* the SeQuences,
* when they have an actual length
/**
* \ingroup gdcmParser
* \brief writes on disc according to the requested format
- * (ACR-NEMA, ExplicitVR, ImplicitVR) the image
- * using the Chained List
- * \warning does NOT add the missing elements in the header :
- * it's up to the user doing it !
- * (function CheckHeaderCoherence to be written)
- * \warning DON'T try, right now, to write a DICOM image
- * from an ACR Header (meta elements will be missing!)
- * \sa WriteEntriesDeprecated (Special temporay method for Theralys)
+ * (ACR-NEMA, ExplicitVR, ImplicitVR) ONE
+ * gdcmHeaderEntry
+ * @param tag pointer on the gdcmHeaderEntry to be written
* @param type type of the File to be written
* (ACR-NEMA, ExplicitVR, ImplicitVR)
* @param _fp already open file pointer
*/
-void gdcmParser::WriteEntries(FILE *_fp,FileType type)
+void gdcmParser::WriteEntry(gdcmHeaderEntry *tag, FILE *_fp,FileType type)
{
guint16 gr, el;
guint32 lgr;
guint16 valZero =0;
void *voidArea;
std::vector<std::string> tokens;
-
- // TODO : function CheckHeaderCoherence to be written
-
- // uses now listEntries to iterate, not TagHt!
- //
- // pb : gdcmParser.Add does NOT update listEntries
- // TODO : find a trick (in STL?) to do it, at low cost !
void *ptr;
int ff=0xffffffff;
// TODO (?) tester les echecs en ecriture (apres chaque fwrite)
int compte =0;
-
- for (ListTag::iterator tag2=listEntries.begin();
- tag2 != listEntries.end();
- ++tag2)
- {
+ itsTimeToWritePixels = false;
+
// === Deal with the length
// --------------------
- if(((*tag2)->GetLength())%2==1)
+ if((tag->GetLength())%2==1)
{
- (*tag2)->SetValue((*tag2)->GetValue()+"\0");
- (*tag2)->SetLength((*tag2)->GetReadLength()+1);
+ tag->SetValue(tag->GetValue()+"\0");
+ tag->SetLength(tag->GetReadLength()+1);
}
- gr = (*tag2)->GetGroup();
- el = (*tag2)->GetElement();
- lgr = (*tag2)->GetReadLength();
- val = (*tag2)->GetValue().c_str();
- vr = (*tag2)->GetVR();
- voidArea = (*tag2)->GetVoidArea();
+ gr = tag->GetGroup();
+ el = tag->GetElement();
+ lgr = tag->GetReadLength();
+ val = tag->GetValue().c_str();
+ vr = tag->GetVR();
+ voidArea = tag->GetVoidArea();
if ( type == ACR )
{
- if (gr < 0x0008) continue; // ignore pure DICOM V3 groups
- if (gr %2) continue; // ignore shadow groups
- if (vr == "SQ" ) continue; // ignore Sequences
+ if (gr < 0x0008) return; // ignore pure DICOM V3 groups
+ if (gr %2) return; // ignore shadow groups
+ if (vr == "SQ" ) return; // ignore Sequences
// TODO : find a trick to *skip* the SeQuences !
// Not only ignore the SQ element
- if (gr == 0xfffe ) continue; // ignore delimiters
+ if (gr == 0xfffe ) return; // ignore delimiters
}
fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group
if (gr == 0xfffe) { // NO Value Representation for 'delimiters'
// no length : write ffffffff
fwrite (&ff,(size_t)4 ,(size_t)1 ,_fp);
- continue; // NO value for 'delimiters'
+ return; // NO value for 'delimiters'
}
shortLgr=lgr;
// === Deal with the value
// -------------------
- if (vr == "SQ") continue; // no "value" to write for the SEQuences
- if (gr == 0xfffe)continue; // no "value" to write for the delimiters
+ if (vr == "SQ") return; // no "value" to write for the SEQuences
+ if (gr == 0xfffe)return; // no "value" to write for the delimiters
if (voidArea != NULL)
{ // there is a 'non string' LUT, overlay, etc
fwrite ( voidArea,(size_t)lgr ,(size_t)1 ,_fp); // Elem value
- continue;
+ return;
}
if (vr == "US" || vr == "SS")
{
tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
- Tokenize ((*tag2)->GetValue(), tokens, "\\");
+ Tokenize (tag->GetValue(), tokens, "\\");
for (unsigned int i=0; i<tokens.size();i++)
{
val_uint16 = atoi(tokens[i].c_str());
fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
}
tokens.clear();
- continue;
+ return;
}
if (vr == "UL" || vr == "SL")
{
tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
- Tokenize ((*tag2)->GetValue(), tokens, "\\");
+ Tokenize (tag->GetValue(), tokens, "\\");
for (unsigned int i=0; i<tokens.size();i++)
{
val_uint32 = atoi(tokens[i].c_str());
fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
}
tokens.clear();
- continue;
+ return;
}
// Pixels are never loaded in the element !
if ((gr == GrPixel) && (el == NumPixel) ) {
compte++;
- if (compte == countGrPixel) // we passed *all* the GrPixel,NumPixel
- break;
+ if (compte == countGrPixel) {// we passed *all* the GrPixel,NumPixel
+ itsTimeToWritePixels = true;
+ return;
+ }
}
fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); // Elem value
- }
}
+/**
+ * \ingroup gdcmParser
+ * \brief writes on disc according to the requested format
+ * (ACR-NEMA, ExplicitVR, ImplicitVR) the image
+ * using the Chained List
+ * \warning does NOT add the missing elements in the header :
+ * it's up to the user doing it !
+ * (function CheckHeaderCoherence to be written)
+ * \warning DON'T try, right now, to write a DICOM image
+ * from an ACR Header (meta elements will be missing!)
+ * \sa WriteEntriesDeprecated (Special temporary method for Theralys)
+ * @param type type of the File to be written
+ * (ACR-NEMA, ExplicitVR, ImplicitVR)
+ * @param _fp already open file pointer
+ */
+
+void gdcmParser::WriteEntries(FILE *_fp,FileType type)
+{
+ // TODO (?) tester les echecs en ecriture (apres chaque fwrite)
+
+ for (ListTag::iterator tag2=listEntries.begin();
+ tag2 != listEntries.end();
+ ++tag2)
+ {
+ WriteEntry(*tag2,_fp,type);
+ if (itsTimeToWritePixels)
+ break;
+ }
+}
/**
* \ingroup gdcmParser
* (ACR-NEMA, ExplicitVR, ImplicitVR)
*/
void gdcmParser::WriteEntriesDeprecated(FILE *_fp,FileType type) {
- guint16 gr, el;
- guint32 lgr;
- const char * val;
- std::string vr;
- guint32 val_uint32;
- guint16 val_uint16;
-
- std::vector<std::string> tokens;
- void *ptr;
-
- // Tout ceci ne marche QUE parce qu'on est sur un proc Little Endian
// restent a tester les echecs en ecriture (apres chaque fwrite)
for (TagHeaderEntryHT::iterator tag2=tagHT.begin();
tag2 != tagHT.end();
++tag2){
-
- gr = tag2->second->GetGroup();
- el = tag2->second->GetElement();
- lgr = tag2->second->GetLength();
- val = tag2->second->GetValue().c_str();
- vr = tag2->second->GetVR();
-
- // std::cout << "Tag "<< std::hex << gr << " " << el << std::endl;
-
- if ( type == ACR ) {
- if (gr < 0x0008) continue; // ignore pure DICOM V3 groups
- if (gr %2) continue; // ignore shadow groups
- if (vr == "SQ" ) continue; // ignore Sequences
- if (gr == 0xfffe ) continue; // ignore delimiters
- }
-
- fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group
- fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element
-
- if ( (type == ExplicitVR) && (gr <= 0x0002) ) {
- // EXPLICIT VR
- guint16 z=0, shortLgr;
- fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp);
-
- if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) {
- fwrite ( &z, (size_t)2 ,(size_t)1 ,_fp);
- fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
-
- } else {
- shortLgr=lgr;
- fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp);
- }
- } else { // IMPLICIT VR
- fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
- }
-
- if (vr == "US" || vr == "SS") {
- tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
- Tokenize (tag2->second->GetValue(), tokens, "\\");
- for (unsigned int i=0; i<tokens.size();i++) {
- val_uint16 = atoi(tokens[i].c_str());
- ptr = &val_uint16;
- fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
- }
- tokens.clear();
- continue;
- }
- if (vr == "UL" || vr == "SL") {
- tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
- Tokenize (tag2->second->GetValue(), tokens, "\\");
- for (unsigned int i=0; i<tokens.size();i++) {
- val_uint32 = atoi(tokens[i].c_str());
- ptr = &val_uint32;
- fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
- }
- tokens.clear();
- continue;
- }
- // Pixels are never loaded in the element !
- if ((gr == 0x7fe0) && (el == 0x0010) ) break;
-
- fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); // Elem value
+ WriteEntry(tag2->second,_fp,type);
+ if (itsTimeToWritePixels)
+ break;
}
}
-
-
-
-
-
/**
* \ingroup gdcmParser
* \brief Swaps back the bytes of 4-byte long integer accordingly to
/**
* \ingroup gdcmParser
* \brief add a new Dicom Element pointer to
- * the H Table and to the chained List
+ * the H Table and at the end of the chained List
* \warning push_bash in listEntries ONLY during ParseHeader
* \todo something to allow further Elements addition,
* (at their right place in the chained list)
/**
* \ingroup gdcmParser
- * \brief Apply some heuristics to predict wether the considered
+ * \brief Apply some heuristics to predict whether the considered
* element value contains/represents an integer or not.
* @param Entry The element value on which to apply the predicate.
* @return The result of the heuristical predicate.
/**
* \ingroup gdcmParser
- * \brief
+ * \brief skips bytes inside the source file
* \warning NOT end user intended method !
* @return
*/
/**
* \ingroup gdcmParser
- * \brief
+ * \brief Loads all the needed Dictionaries
+ * \warning NOT end user intended method !
*/
void gdcmParser::Initialise(void)
{
/**
* \ingroup gdcmParser
- * \brief
+ * \brief Restore the unproperly loaded values i.e. the group, the element
+ * and the dictionary entry depending on them.
*/
void gdcmParser::SwitchSwapToBigEndian(void)
{
* \brief Sets the print level for the Dicom Header
* \note 0 for Light Print; 1 for 'medium' Print, 2 for Heavy
*/
- void SetPrintLevel(int level) { printLevel = level; };
+ void SetPrintLevel(int level)
+ { printLevel = level; };
/**
* \ingroup gdcmParser
* \brief canonical Printer
* \sa SetPrintLevel
*/
- virtual void Print (std::ostream &os = std::cout) {PrintEntry(os);};
+ virtual void Print (std::ostream &os = std::cout)
+ {PrintEntry(os);};
virtual void PrintEntry (std::ostream &os = std::cout);
virtual void PrintPubDict (std::ostream &os = std::cout);
virtual void PrintShaDict (std::ostream &os = std::cout);
* \ingroup gdcmParser
* \brief Gets the external File Name
*/
- inline std::string GetFileName(void) {return filename;}
+ inline std::string GetFileName(void)
+ {return filename;}
// Dictionnaries
gdcmDict *GetPubDict(void);
virtual int GetEntryLengthByNumber(guint16 group, guint16 element);
virtual bool SetEntryByName (std::string content, std::string tagName);
- virtual bool SetEntryByNumber(std::string content, guint16 group, guint16 element);
+ virtual bool SetEntryByNumber(std::string content, guint16 group, guint16 element);
virtual bool SetEntryLengthByNumber(guint32 length, guint16 group, guint16 element);
virtual size_t GetEntryOffsetByNumber (guint16 Group, guint16 Elem);
void LoadHeaderEntrySafe(gdcmHeaderEntry *);
void UpdateGroupLength(bool SkipSequence = false, FileType type = ImplicitVR);
+ void WriteEntry(gdcmHeaderEntry *tag,FILE *_fp,FileType type);
void WriteEntries(FILE *_fp,FileType type);
void WriteEntriesDeprecated(FILE *_fp,FileType type); // JPR
* Let's remember how many times!
*/
int countGrPixel;
+ /**
+ * \brief = true when the 'pixel Element' is reached during writting process
+ */
+ bool itsTimeToWritePixels;
private:
// Read
std::string vr = "unkn",
std::string fourth = "unkn",
std::string name = "unkn");
- gdcmDictEntry *NewVirtualDictEntry(gdcmHeaderEntry *);
+ //gdcmDictEntry *NewVirtualDictEntry(gdcmHeaderEntry *); // never defined
// HeaderEntry related utilities
+
gdcmHeaderEntry *ReadNextHeaderEntry (void);
gdcmHeaderEntry *NewHeaderEntryByNumber(guint16 group,
guint16 element);
// Deprecated (Not used) --> commented out
//gdcmHeaderEntry *NewManualHeaderEntryToPubDict(std::string NewTagName,
- // std::string VR);
+ // std::string VR);
+
guint32 GenerateFreeTagKeyInGroup(guint16 group);
- // Refering underlying filename.
+ /**
+ * \brief Refering underlying filename.
+ */
std::string filename;
- // Public dictionary used to parse this header
+ /**
+ * \brief Public dictionary used to parse this header
+ */
gdcmDict *RefPubDict;
- // Optional "shadow dictionary" (private elements) used to parse this header
+
+ /**
+ * \brief Optional "shadow dictionary" (private elements) used to parse this header
+ */
gdcmDict *RefShaDict;
- // = 1 if a gdcmHeaderEntry was added post parsing
+ /**
+ * \brief = 1 if a gdcmHeaderEntry was added post parsing
+ */
int wasUpdated;
- // =1 if user wants to skip shadow groups while parsing (to save space)
+ /**
+ * \brief =1 if user wants to skip shadow groups while parsing (to save space)
+ */
int ignoreShadow;
-
- // Swap code e.g. little, big, bad-big, bad-little endian). Warning:
- // this code is not fixed during header parsing.
+
+ /**
+ * \brief Swap code e.g. little, big, bad-big, bad-little endian).
+ * \warning : this code is not fixed during header parsing.
+ */
int sw;
-
- // Size treshold above which an element value will NOT be loaded in
- // memory (to avoid loading the image/volume itself). By default,
- // this upper bound is fixed to 1024 bytes (which might look reasonable
- // when one considers the definition of the various VR contents).
+ /**
+ * \brief Size treshold above which an element value will NOT be loaded in
+ * memory (to avoid loading the image/volume itself). By default,
+ * this upper bound is fixed to 1024 bytes (which might look reasonable
+ * when one considers the definition of the various VR contents).
+ */
guint32 MaxSizeLoadEntry;
- // Size treshold above which an element value will NOT be *printed* in
- // order no to polute the screen output. By default,
- // this upper bound is fixed to 64 bytes.
+
+ /**
+ * \brief Size treshold above which an element value will NOT be *printed* in
+ * order no to polute the screen output.
+ * By default, this upper bound is fixed to 64 bytes.
+ */
guint32 MaxSizePrintEntry;
};