Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
// PS 3.3-2003, pages 731-750
//-----------------------------------------------------------------------------
#include "gdcmDicomDir.h"
// PS 3.3-2003, pages 731-750
//-----------------------------------------------------------------------------
#include "gdcmDicomDir.h"
#include "gdcmDicomDirImage.h"
#include "gdcmDicomDirPatient.h"
#include "gdcmDicomDirMeta.h"
#include "gdcmDicomDirImage.h"
#include "gdcmDicomDirPatient.h"
#include "gdcmDicomDirMeta.h"
// Directory Record Type Directory Record Types which may be included
// in the next lower-level directory Entity
//
// Directory Record Type Directory Record Types which may be included
// in the next lower-level directory Entity
//
-// STUDY SERIES, VISIT, RESULTS, STUDY COMPONENT
+// STUDY SERIES, VISIT, RESULTS, STUDY COMPONENT, PRIVATE
//
// SERIES IMAGE, OVERLAYS, MODALITY LUT, VOI LUT,
// CURVE, STORED PRINT, RT DOSE, RT STRUCTURE SET
// RT PLAN, RT TREAT RECORD, PRESENTATION, WAVEFORM,
// SR DOCUMENT, KEY OBJECT DOC, SPECTROSCOPY,
//
// SERIES IMAGE, OVERLAYS, MODALITY LUT, VOI LUT,
// CURVE, STORED PRINT, RT DOSE, RT STRUCTURE SET
// RT PLAN, RT TREAT RECORD, PRESENTATION, WAVEFORM,
// SR DOCUMENT, KEY OBJECT DOC, SPECTROSCOPY,
-// RAW DATA, REGISTRATION, FIDUCIAL
+// RAW DATA, REGISTRATION, FIDUCIAL, PRIVATE,
+// ENCAP DOC
//
// ----------------------
// The current gdcm version only deals with :
//
// (Root directory Entity) PATIENT
// PATIENT STUDY
//
// ----------------------
// The current gdcm version only deals with :
//
// (Root directory Entity) PATIENT
// PATIENT STUDY
/**
* \brief Constructor Parses recursively the directory and creates the DicomDir
* or uses an already built DICOMDIR, depending on 'parseDir' value.
/**
* \brief Constructor Parses recursively the directory and creates the DicomDir
* or uses an already built DICOMDIR, depending on 'parseDir' value.
* and wants to explore recursively the directories
* - false if user passed an already built DICOMDIR file
* and wants to use it
* and wants to explore recursively the directories
* - false if user passed an already built DICOMDIR file
* and wants to use it
// and whatever the value of parseDir was.
// (nothing is cheked in Document constructor, to avoid overhead)
// and whatever the value of parseDir was.
// (nothing is cheked in Document constructor, to avoid overhead)
+ ParseDir = parseDir;
+ SetLoadMode (0x00000000); // concerns only dicom files
+ SetFileName( fileName );
+ Load( );
+}
+#endif
+
+/**
+ * \brief Canonical destructor
+ */
+DicomDir::~DicomDir()
+{
+ SetStartMethod(NULL);
+ SetProgressMethod(NULL);
+ SetEndMethod(NULL);
+
+ ClearPatient();
+ if ( MetaElems )
+ {
+ delete MetaElems;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+/**
+ * \brief Loader. use SetFileName(fn)
+ * or SetLoadMode(lm) + SetDirectoryName(dn) before !
+ * @return false if file cannot be open or no swap info was found,
+ * or no tag was found.
+ */
+bool DicomDir::Load( )
+{
+ // We should clean out anything that already exists.
- if ( GetFirstEntry() == 0 ) // when user passed a Directory to parse
+ #ifndef GDCM_LEGACY_REMOVE
+/**
+ * \brief Loader. (DEPRECATED : kept not to break the API)
+ * @param fileName file to be open for parsing
+ * @return false if file cannot be open or no swap info was found,
+ * or no tag was found.
+ * @deprecated use SetFileName(n) + Load() instead
+ */
+bool DicomDir::Load(std::string const &fileName )
+{
+ // We should clean out anything that already exists.
+ Initialize(); // sets all private fields to NULL
+
+ SetFileName( fileName );
+ if (!ParseDir)
- // Only if user passed a root directory
- // ------------------------------------
- if ( fileName == "." )
+/// DEPRECATED : use SetDirectoryName(dname) instead
+void DicomDir::SetParseDir(bool parseDir)
+{
+ ParseDir = parseDir;
+}
+#endif
+
+/**
+ * \brief Does the Loading Job (internal use only)
+ * @return false if file cannot be open or no swap info was found,
+ * or no tag was found.
+ */
+bool DicomDir::DoTheLoadingJob( )
+{
+ // We should clean out anything that already exists.
+ Initialize(); // sets all private fields to NULL
+
+ if (!ParseDir)
+ {
+ // Only if user passed a DICOMDIR
+ // ------------------------------
+ Fp = 0;
+ if ( !OpenFile() )
- // user passed '.' as Name
- // we get current directory name
- char dummy[1000];
- getcwd(dummy, (size_t)1000);
- SetFileName( dummy ); // will be converted into a string
// Directory record sequence
DocEntry *e = GetDocEntry(0x0004, 0x1220);
if ( !e )
{
gdcmWarningMacro( "NO 'Directory record sequence' (0x0004,0x1220)"
// Directory record sequence
DocEntry *e = GetDocEntry(0x0004, 0x1220);
if ( !e )
{
gdcmWarningMacro( "NO 'Directory record sequence' (0x0004,0x1220)"
+ // Only if user passed a root directory
+ // ------------------------------------
+ if ( GetFileName() == "." )
+ {
+ // user passed '.' as Name
+ // we get current directory name
+ char dummy[1000];
+ getcwd(dummy, (size_t)1000);
+ SetFileName( dummy ); // will be converted into a string
+ }
+ NewMeta();
+ gdcmWarningMacro( "Parse directory and create the DicomDir : "
+ << GetFileName() );
+ ParseDirectory();
/**
* \brief This predicate, based on hopefully reasonable heuristics,
* decides whether or not the current document was properly parsed
/**
* \brief This predicate, based on hopefully reasonable heuristics,
* decides whether or not the current document was properly parsed
void DicomDir::SetStartMethod( DicomDir::Method *method, void *arg,
DicomDir::Method *argDelete )
{
void DicomDir::SetStartMethod( DicomDir::Method *method, void *arg,
DicomDir::Method *argDelete )
{
void DicomDir::SetProgressMethod( DicomDir::Method *method, void *arg,
DicomDir::Method *argDelete )
{
void DicomDir::SetProgressMethod( DicomDir::Method *method, void *arg,
DicomDir::Method *argDelete )
{
void DicomDir::SetEndMethod( DicomDir::Method *method, void *arg,
DicomDir::Method *argDelete )
{
void DicomDir::SetEndMethod( DicomDir::Method *method, void *arg,
DicomDir::Method *argDelete )
{
std::ofstream *fp = new std::ofstream(fileName.c_str(),
std::ios::out | std::ios::binary);
std::ofstream *fp = new std::ofstream(fileName.c_str(),
std::ios::out | std::ios::binary);
+/**
+ * \brief Anonymize a DICOMDIR
+ * @return true
+ */
+
+bool DicomDir::AnonymizeDicomDir()
+{
+ ValEntry *v;
+ // Something clever to be found to forge the Patient names
+ std::ostringstream s;
+ int i = 1;
+ for(ListDicomDirPatient::iterator cc = Patients.begin();
+ cc!= Patients.end();
+ ++cc)
+ {
+ s << i;
+ v = (*cc)->GetValEntry(0x0010, 0x0010) ; // Patient's Name
+ if (v)
+ {
+ v->SetValue(s.str());
+ }
+
+ v = (*cc)->GetValEntry(0x0010, 0x0020) ; // Patient ID
+ if (v)
+ {
+ v->SetValue(" ");
+ }
+
+ v = (*cc)->GetValEntry(0x0010, 0x0030) ; // Patient's BirthDate
+ if (v)
+ {
+ v->SetValue(" ");
+ }
+ s << "";
+ i++;
+ }
+ return true;
+}
+
- header = new File( it->c_str() );
- if( !header )
- {
- gdcmWarningMacro( "Failure in new gdcm::File " << it->c_str() );
- continue;
- }
+ f = new File( );
+ f->SetLoadMode(LoadMode); // we allow user not to load Sequences, or Shadow
+ // groups, or ......
+ f->SetFileName( it->c_str() );
+ /*int res = */f->Load( );
+
+// if ( !f )
+// {
+// gdcmWarningMacro( "Failure in new gdcm::File " << it->c_str() );
+// continue;
+// }
- gdcmErrorMacro( "Add AddImageToEnd failed");
+ gdcmErrorMacro( "Add AddStudyToEnd failed");
+ }
+ }
+ else if ( v == "PATIENT " )
+ {
+ si = new DicomDirPatient(true);
+ if ( !AddPatientToEnd( static_cast<DicomDirPatient *>(si)) )
+ {
+ delete si;
+ si = NULL;
+ gdcmErrorMacro( "Add PatientToEnd failed");
- // It was not a 'PATIENT', nor a 'STUDY', nor a 'SERIE',
- // neither an 'IMAGE' SQItem. Skip to next item.
- continue;
+ // It was neither a 'PATIENT', nor a 'STUDY', nor a 'SERIE',
+ // nor an 'IMAGE' SQItem. Skip to next item.
+ gdcmWarningMacro( " -------------------------------------------"
+ << "a non PATIENT/STUDY/SERIE/IMAGE SQItem was found : "
+ << v);
+
+ // FIXME : deal with other item types !
+ tmpSI=s->GetNextSQItem(); // To avoid infinite loop
+ continue;
+/**
+ * \brief AddVisitToEnd
+ * @param dd SQ Item to enqueue to the DicomDirVisit chained List
+ */
+bool DicomDir::AddVisitToEnd(DicomDirVisit *dd)
+{
+ if ( Patients.size() > 0 )
+ {
+ ListDicomDirPatient::iterator itp = Patients.end();
+ itp--;
+
+ DicomDirStudy *study = (*itp)->GetLastStudy();
+ if ( study )
+ {
+ study->AddVisit(dd);
+ return true;
+ }
+ }
+ return false;
+}
/**
* \brief AddImageToEnd
* @param dd SQ Item to enqueue to the DicomDirImage chained List
*/
bool DicomDir::AddImageToEnd(DicomDirImage *dd)
{
/**
* \brief AddImageToEnd
* @param dd SQ Item to enqueue to the DicomDirImage chained List
*/
bool DicomDir::AddImageToEnd(DicomDirImage *dd)
{
serCurInstanceUID = (*it)->GetEntryValue(0x0020,0x000e);
serCurID = (*it)->GetEntryValue(0x0020,0x0011);
serCurInstanceUID = (*it)->GetEntryValue(0x0020,0x000e);
serCurID = (*it)->GetEntryValue(0x0020,0x0011);
- // if new Study Deal with 'STUDY' Elements
- if( studCurInstanceUID != studPrevInstanceUID || studCurID != studPrevID
+ // if new Study, deal with 'STUDY' Elements
+ if ( studCurInstanceUID != studPrevInstanceUID || studCurID != studPrevID
- // if new Serie Deal with 'SERIE' Elements
- if( serCurInstanceUID != serPrevInstanceUID || serCurID != serPrevID
+ // if new Serie, deal with 'SERIE' Elements
+ if ( serCurInstanceUID != serPrevInstanceUID || serCurID != serPrevID
case GDCM_DICOMDIR_IMAGE:
elemList = Global::GetDicomDirElements()->GetDicomDirImageElements();
si = new DicomDirImage(true);
case GDCM_DICOMDIR_IMAGE:
elemList = Global::GetDicomDirElements()->GetDicomDirImageElements();
si = new DicomDirImage(true);
case GDCM_DICOMDIR_SERIE:
elemList = Global::GetDicomDirElements()->GetDicomDirSerieElements();
si = new DicomDirSerie(true);
case GDCM_DICOMDIR_SERIE:
elemList = Global::GetDicomDirElements()->GetDicomDirSerieElements();
si = new DicomDirSerie(true);
case GDCM_DICOMDIR_STUDY:
elemList = Global::GetDicomDirElements()->GetDicomDirStudyElements();
si = new DicomDirStudy(true);
case GDCM_DICOMDIR_STUDY:
elemList = Global::GetDicomDirElements()->GetDicomDirStudyElements();
si = new DicomDirStudy(true);
case GDCM_DICOMDIR_PATIENT:
elemList = Global::GetDicomDirElements()->GetDicomDirPatientElements();
si = new DicomDirPatient(true);
case GDCM_DICOMDIR_PATIENT:
elemList = Global::GetDicomDirElements()->GetDicomDirPatientElements();
si = new DicomDirPatient(true);
* @param src source SQItem
*/
void DicomDir::MoveSQItem(DocEntrySet *dst,DocEntrySet *src)
* @param src source SQItem
*/
void DicomDir::MoveSQItem(DocEntrySet *dst,DocEntrySet *src)