+
+/**
+ * \brief adds to the HTable
+ * the gdcmEntries (Dicom Elements) corresponding to the given type
+ * @param path full path file name (only used when type = GDCM_DICOMDIR_IMAGE
+ * @param type gdcmDicomDirObject 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,
+ gdcmDocument *header)
+{
+ std::list<gdcmElement> elemList;
+ std::list<gdcmElement>::iterator it;
+ uint16_t tmpGr, tmpEl;
+ gdcmDictEntry *dictEntry;
+ gdcmValEntry *entry;
+ std::string val;
+ gdcmSQItem *si = new gdcmSQItem(0); // all the items will be at level 1
+ switch( type )
+ {
+ case GDCM_DICOMDIR_IMAGE:
+ elemList = gdcmGlobal::GetDicomDirElements()->GetDicomDirImageElements();
+ break;
+
+ case GDCM_DICOMDIR_SERIE:
+ elemList = gdcmGlobal::GetDicomDirElements()->GetDicomDirSerieElements();
+ break;
+
+ case GDCM_DICOMDIR_STUDY:
+ elemList = gdcmGlobal::GetDicomDirElements()->GetDicomDirStudyElements();
+ break;
+
+ case GDCM_DICOMDIR_PATIENT:
+ elemList = gdcmGlobal::GetDicomDirElements()->GetDicomDirPatientElements();
+ break;
+
+ case GDCM_DICOMDIR_META:
+ elemList = gdcmGlobal::GetDicomDirElements()->GetDicomDirMetaElements();
+ break;
+
+ default:
+ return;
+ }
+ // removed all the seems-to-be-useless stuff about Referenced Image Sequence
+ // to avoid further troubles
+ // imageElem 0008 1140 "" // Referenced Image Sequence
+ // imageElem fffe e000 "" // 'no length' item : length to be set to 0xffffffff later
+ // imageElem 0008 1150 "" // Referenced SOP Class UID : to be set/forged later
+ // imageElem 0008 1155 "" // Referenced SOP Instance UID : to be set/forged later
+ // imageElem fffe e00d "" // Item delimitation : length to be set to ZERO later
+ // for all the relevant elements found in their own spot of the DicomDir.dic
+ // FIXME : troubles found when it's a SeqEntry
+
+ for( it = elemList.begin(); it != elemList.end(); ++it)
+ {
+ tmpGr = it->group;
+ tmpEl = it->elem;
+ dictEntry = GetPubDict()->GetDictEntryByNumber(tmpGr, tmpEl);
+
+ entry = new gdcmValEntry( dictEntry ); // Be sure it's never a BinEntry !
+
+ entry->SetOffset(0); // just to avoid further missprinting
+ entry->SetLength(0); // just to avoid further missprinting
+
+ if( header ) // NULL when we Build Up (ex nihilo) a DICOMDIR
+ // or when we add the META elems
+ val = header->GetEntryByNumber(tmpGr, tmpEl);
+ else
+ val = GDCM_UNFOUND;
+
+ if( val == GDCM_UNFOUND)
+ {
+ if( tmpGr == 0x0004 && tmpEl == 0x1130 ) // File-set ID
+ {
+ // force to the *end* File Name
+ val = GetName( path );
+ }
+ else if( tmpGr == 0x0004 && tmpEl == 0x1500 ) // Only used for image
+ {
+ if( header->GetFileName().substr(0, path.length()) != path )
+ {
+ dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path"
+ " of file name is incorrect");
+ val = header->GetFileName();
+ }
+ else
+ val = &(header->GetFileName().c_str()[path.length()]);
+ }
+ else
+ val = it->value;
+ }
+ else
+ {
+ if ( header->GetEntryLengthByNumber(tmpGr,tmpEl) == 0 )
+ val = it->value;
+ }
+
+ // GDCM_UNFOUND or not !
+
+ entry->SetValue( val ); // troubles expected when vr=SQ ...
+
+ if( dictEntry )
+ {
+ if( dictEntry->GetGroup() == 0xfffe )
+ {
+ entry->SetLength( entry->GetValue().length() ); // FIXME
+ }
+ 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() );
+ }
+ }
+
+ if ( type == GDCM_DICOMDIR_META ) // fusible : should never print !
+ {
+ std::cout << "GDCM_DICOMDIR_META ?!? should never print that"
+ << std::endl;
+ }
+ si->AddEntry(entry);
+ }
+ switch( type )
+ {
+ case GDCM_DICOMDIR_IMAGE:
+ AddDicomDirImageToEnd(si);
+ break;
+
+ case GDCM_DICOMDIR_SERIE:
+ AddDicomDirSerieToEnd(si);
+ break;
+
+ case GDCM_DICOMDIR_STUDY:
+ AddDicomDirStudyToEnd(si);
+ break;
+
+ case GDCM_DICOMDIR_PATIENT:
+ AddDicomDirPatientToEnd(si);
+ break;
+
+ default:
+ return;
+ }
+ //int count=1; // find a trick to increment
+ //s->AddEntry(si, count); // Seg Faults
+
+}
+
+/**
+ * \brief CallStartMethod
+ */
+void gdcmDicomDir::CallStartMethod()
+{
+ progress = 0.0f;
+ abort = false;
+ if( startMethod )
+ {
+ startMethod( startArg );
+ }
+}
+
+/**
+ * \ingroup gdcmDicomDir
+ * \brief CallProgressMethod
+ */
+void gdcmDicomDir::CallProgressMethod()
+{
+ if( progressMethod )
+ {
+ progressMethod( progressArg );
+ }
+}
+
+/**
+ * \ingroup gdcmDicomDir
+ * \brief CallEndMethod
+ */
+void gdcmDicomDir::CallEndMethod()
+{
+ progress = 1.0f;
+ if( endMethod )
+ {
+ endMethod( endArg );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \ingroup gdcmDicomDir
+ * \brief create a 'gdcmDicomDir' from a DICOMDIR gdcmHeader
+ */
+void gdcmDicomDir::CreateDicomDir()
+{
+ // 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
+ // + we create the object for the precedent tag
+ // + loop to 1 -
+
+ // Directory record sequence
+ gdcmDocEntry *e = GetDocEntryByNumber(0x0004, 0x1220);
+ if ( !e )
+ {
+ dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : NO Directory record"
+ " sequence (0x0004,0x1220)");
+ /// \todo FIXME: what to do when the parsed file IS NOT a DICOMDIR file ?
+ return;
+ }
+
+ gdcmSeqEntry* s = dynamic_cast<gdcmSeqEntry*>(e);
+ if ( !s )
+ {
+ dbg.Verbose(0, "gdcmDicomDir::CreateDicomDir: no SeqEntry present");
+ // useless : (0x0004,0x1220) IS a Sequence !
+ return;
+ }
+
+ gdcmDicomDirType type = gdcmDicomDir::GDCM_DICOMDIR_META;
+ metaElems = NewMeta();
+
+ ListSQItem listItems = s->GetSQItems();
+
+ gdcmDocEntry * d;
+ std::string v;
+ for( ListSQItem::iterator i = listItems.begin();
+ i !=listItems.end(); ++i )
+ {
+ d = (*i)->GetDocEntryByNumber(0x0004, 0x1430); // Directory Record Type
+ if ( gdcmValEntry* ValEntry = dynamic_cast< gdcmValEntry* >(d) )
+ {
+ v = ValEntry->GetValue();
+ }
+ else
+ {
+ dbg.Verbose(0, "gdcmDicomDir::CreateDicomDir: not a ValEntry.");
+ continue;
+ }
+
+ if( v == "PATIENT " )
+ {
+ AddDicomDirPatientToEnd( *i );
+ type = gdcmDicomDir::GDCM_DICOMDIR_PATIENT;
+ }
+ else if( v == "STUDY " )
+ {
+ AddDicomDirStudyToEnd( *i );
+ type = gdcmDicomDir::GDCM_DICOMDIR_STUDY;
+ }
+ else if( v == "SERIES" )
+ {
+ AddDicomDirSerieToEnd( *i );
+ type = gdcmDicomDir::GDCM_DICOMDIR_SERIE;
+ }
+ else if( v == "IMAGE " )
+ {
+ AddDicomDirImageToEnd( *i );
+ type = gdcmDicomDir::GDCM_DICOMDIR_IMAGE;
+ }
+ else
+ {
+ // It was not a 'PATIENT', nor a 'STUDY', nor a 'SERIE',
+ // neither an 'IMAGE' SQItem. Skip to next item.
+ continue;
+ }
+ }
+}
+
+/**
+ * \ingroup gdcmDicomDir
+ * \brief Well ... there is only one occurence
+ */
+void gdcmDicomDir::AddDicomDirMeta()
+{
+ if( metaElems )
+ {
+ delete metaElems;
+ }
+ metaElems = new gdcmDicomDirMeta( &TagHT );
+}
+
+/**
+ * \ingroup gdcmDicomDir
+ * \brief AddDicomDirPatientToEnd
+ * @param s SQ Item to enqueue to the DicomPatient chained List
+ */
+void gdcmDicomDir::AddDicomDirPatientToEnd(gdcmSQItem *s)
+{
+ patients.push_back(new gdcmDicomDirPatient(s, &TagHT));
+}
+
+/**
+ * \ingroup gdcmDicomDir
+ * \brief AddDicomDirStudyToEnd
+ * @param s SQ Item to enqueue to the DicomDirStudy chained List
+ */
+ void gdcmDicomDir::AddDicomDirStudyToEnd(gdcmSQItem *s)
+{
+ if( patients.size() > 0 )
+ {
+ ListDicomDirPatient::iterator itp = patients.end();
+ itp--;
+ (*itp)->AddDicomDirStudy(new gdcmDicomDirStudy(s, &TagHT));
+ }
+}
+
+/**
+ * \ingroup gdcmDicomDir
+ * \brief AddDicomDirSerieToEnd
+ * @param s SQ Item to enqueue to the DicomDirSerie chained List
+ */
+void gdcmDicomDir::AddDicomDirSerieToEnd(gdcmSQItem *s)
+{
+ if( patients.size() > 0 )
+ {
+ ListDicomDirPatient::iterator itp = patients.end();
+ itp--;
+
+ if( (*itp)->GetDicomDirStudies().size() > 0 )
+ {
+ ListDicomDirStudy::iterator itst=(*itp)->GetDicomDirStudies().end();
+ itst--;
+ (*itst)->AddDicomDirSerie(new gdcmDicomDirSerie(s, &TagHT));
+ }
+ }
+}
+
+/**
+ * \ingroup gdcmDicomDir
+ * \brief AddDicomDirImageToEnd
+ * @param s SQ Item to enqueue to the DicomDirImage chained List
+ */
+ void gdcmDicomDir::AddDicomDirImageToEnd(gdcmSQItem *s)
+{
+ if( patients.size() > 0 )
+ {
+ ListDicomDirPatient::iterator itp = patients.end();
+ itp--;
+
+ if( (*itp)->GetDicomDirStudies().size() > 0 )
+ {
+ ListDicomDirStudy::iterator itst = (*itp)->GetDicomDirStudies().end();
+ itst--;
+
+ if( (*itst)->GetDicomDirSeries().size() > 0 )
+ {
+ ListDicomDirSerie::iterator its = (*itst)->GetDicomDirSeries().end();
+ its--;
+ (*its)->AddDicomDirImage(new gdcmDicomDirImage(s, &TagHT));
+ }
+ }
+ }
+}
+
+/**
+ * \ingroup gdcmDicomDir
+ * \brief for each Header of the chained list, add/update the Patient/Study/Serie/Image info
+ * @param path path of the root directory
+ * @param list chained list of Headers
+ */
+void gdcmDicomDir::SetElements(std::string &path, VectDocument &list)
+{
+ std::string patPrevName = "", patPrevID = "";
+ std::string studPrevInstanceUID = "", studPrevID = "";
+ std::string serPrevInstanceUID = "", serPrevID = "";
+
+ std::string patCurName, patCurID;
+ std::string studCurInstanceUID, studCurID;
+ std::string serCurInstanceUID, serCurID;
+
+ for( VectDocument::iterator it = list.begin();
+ it != list.end(); ++it )
+ {
+ // get the current file characteristics
+ patCurName = (*it)->GetEntryByNumber(0x0010,0x0010);
+ patCurID = (*it)->GetEntryByNumber(0x0010,0x0011);
+ studCurInstanceUID = (*it)->GetEntryByNumber(0x0020,0x000d);
+ studCurID = (*it)->GetEntryByNumber(0x0020,0x0010);
+ serCurInstanceUID = (*it)->GetEntryByNumber(0x0020,0x000e);
+ serCurID = (*it)->GetEntryByNumber(0x0020,0x0011);
+
+ if( patCurName != patPrevName || patCurID != patPrevID)
+ {
+ SetElement(path, GDCM_DICOMDIR_PATIENT, *it);
+ }
+
+ // if new Study Deal with 'STUDY' Elements
+ if( studCurInstanceUID != studPrevInstanceUID || studCurID != studPrevID )
+ {
+ SetElement(path, GDCM_DICOMDIR_STUDY, *it);
+ }
+
+ // if new Serie Deal with 'SERIE' Elements
+ if( serCurInstanceUID != serPrevInstanceUID || serCurID != serPrevID )
+ {
+ SetElement(path, GDCM_DICOMDIR_SERIE, *it);
+ }
+
+ // Always Deal with 'IMAGE' Elements
+ SetElement(path, GDCM_DICOMDIR_IMAGE, *it);
+
+ patPrevName = patCurName;
+ patPrevID = patCurID;
+ studPrevInstanceUID = studCurInstanceUID;
+ studPrevID = studCurID;
+ serPrevInstanceUID = serCurInstanceUID;
+ serPrevID = serCurID;
+ }
+}
+
+/**
+ * \ingroup gdcmDicomDir
+ * \brief compares two dgcmHeaders
+ */
+bool gdcmDicomDir::HeaderLessThan(gdcmDocument *header1, gdcmDocument *header2)
+{
+ return *header1 < *header2;
+}
+
+//-----------------------------------------------------------------------------