00001
00002
00003 #include "gdcmDicomDir.h"
00004 #include "gdcmStudy.h"
00005 #include "gdcmSerie.h"
00006 #include "gdcmImage.h"
00007 #include "gdcmDirList.h"
00008 #include "gdcmUtil.h"
00009
00010 #include <string>
00011 #include <algorithm>
00012
00013 #include <sys/types.h>
00014 #include <errno.h>
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir,
00025 bool exception_on_error):
00026 gdcmParser(FileName,exception_on_error,true)
00027 {
00028 if( GetListEntry().begin()==GetListEntry().end() )
00029 {
00030 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
00031
00032 if(parseDir)
00033 {
00034 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir");
00035 ParseDirectory();
00036 }
00037 }
00038 else
00039 CreateDicomDir();
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 gdcmDicomDir::~gdcmDicomDir()
00060 {
00061 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
00062 {
00063 delete *cc;
00064 }
00065 }
00066
00067
00068
00069
00070
00071
00072
00073 void gdcmDicomDir::Print(std::ostream &os)
00074 {
00075 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
00076 {
00077 (*cc)->SetPrintLevel(printLevel);
00078 (*cc)->Print(os);
00079 }
00080 }
00081
00082
00083
00092 bool gdcmDicomDir::Write(std::string fileName)
00093 {
00094 FILE * fp1;
00095
00096 fp1=fopen(fileName.c_str(),"wb");
00097 if(fp1==NULL)
00098 {
00099 printf("Failed to open(write) File [%s] \n",fileName.c_str());
00100 return(false);
00101 }
00102
00103 char * filePreamble;
00104 filePreamble=(char*)calloc(128,1);
00105 fwrite(filePreamble,128,1,fp1);
00106 fwrite("DICM",4,1,fp1);
00107 free(filePreamble);
00108
00109 WriteEntries(fp1,DICOMDIR);
00110
00111 fclose(fp1);
00112
00113 return true;
00114 }
00115
00116
00117
00118
00119
00120 void gdcmDicomDir::ParseDirectory(void)
00121 {
00122 NewDicomDir(GetPath());
00123 CreateDicomDir();
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133 void gdcmDicomDir::NewDicomDir(std::string path)
00134 {
00135 gdcmDirList fileList(path,1);
00136 ListHeader list;
00137 gdcmHeader *header;
00138
00139 listEntries.clear();
00140 patients.clear();
00141
00142 for(gdcmDirList::iterator it=fileList.begin();
00143 it!=fileList.end(); ++it)
00144 {
00145 header=new gdcmHeader(it->c_str());
00146 if(header->IsReadable())
00147 list.push_back(header);
00148 else
00149 delete header;
00150 }
00151
00152 std::sort(list.begin(),list.end(),gdcmDicomDir::HeaderLessThan);
00153
00154 std::string tmp=fileList.GetDirName();
00155 SetElements(tmp,list);
00156 }
00157
00158
00159
00160
00161
00162
00163 std::string gdcmDicomDir::GetPath(void)
00164 {
00165 std::string path=GetFileName();
00166
00167 int pos1=path.rfind("/");
00168 int pos2=path.rfind("\\");
00169 if(pos1>pos2)
00170 path.resize(pos1);
00171 else
00172 path.resize(pos2);
00173
00174 return(path);
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184 void gdcmDicomDir::CreateDicomDir()
00185 {
00186
00187
00188
00189
00190
00191
00192
00193 gdcmDicomDirType type=gdcmDicomDir::GDCM_NONE;
00194 ListTag::iterator begin;
00195 ListTag::iterator end;
00196
00197 begin=listEntries.begin();
00198 end=begin;
00199 for(ListTag::iterator i=listEntries.begin();i !=listEntries.end();++i)
00200 {
00201 std::string v=(*i)->GetValue();
00202 if(v=="PATIENT ")
00203 {
00204 end=i;
00205 AddObjectToEnd(type,begin,end);
00206
00207 type=gdcmDicomDir::GDCM_PATIENT;
00208 begin=end;
00209 }
00210
00211 if(v=="STUDY ")
00212 {
00213 end=i;
00214 AddObjectToEnd(type,begin,end);
00215
00216 type=gdcmDicomDir::GDCM_STUDY;
00217 begin=end;
00218 }
00219
00220 if(v=="SERIES")
00221 {
00222 end=i;
00223 AddObjectToEnd(type,begin,end);
00224
00225 type=gdcmDicomDir::GDCM_SERIE;
00226 begin=end;
00227 }
00228
00229 if(v=="IMAGE ")
00230 {
00231 end=i;
00232 AddObjectToEnd(type,begin,end);
00233
00234 type=gdcmDicomDir::GDCM_IMAGE;
00235 begin=end;
00236 }
00237 }
00238
00239 end=GetListEntry().end();
00240 AddObjectToEnd(type,begin,end);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249 void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end)
00250 {
00251 if(begin==end)
00252 return;
00253
00254 switch(type)
00255 {
00256 case gdcmDicomDir::GDCM_PATIENT:
00257 AddPatientToEnd(begin,end);
00258 break;
00259 case gdcmDicomDir::GDCM_STUDY:
00260 AddStudyToEnd(begin,end);
00261 break;
00262 case gdcmDicomDir::GDCM_SERIE:
00263 AddSerieToEnd(begin,end);
00264 break;
00265 case gdcmDicomDir::GDCM_IMAGE:
00266 AddImageToEnd(begin,end);
00267 break;
00268 }
00269 }
00270
00271
00272
00273
00274
00275
00276
00277 void gdcmDicomDir::AddPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
00278 {
00279 patients.push_back(new gdcmPatient(begin,end));
00280 }
00281
00282
00283
00284
00285
00286
00287
00288 void gdcmDicomDir::AddStudyToEnd(ListTag::iterator begin,ListTag::iterator end)
00289 {
00290 if(patients.size()>0)
00291 {
00292 ListPatient::iterator itp=patients.end();
00293 itp--;
00294 (*itp)->AddStudy(new gdcmStudy(begin,end));
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303 void gdcmDicomDir::AddSerieToEnd(ListTag::iterator begin,ListTag::iterator end)
00304 {
00305 if(patients.size()>0)
00306 {
00307 ListPatient::iterator itp=patients.end();
00308 itp--;
00309
00310 if((*itp)->GetStudies().size()>0)
00311 {
00312 ListStudy::iterator itst=(*itp)->GetStudies().end();
00313 itst--;
00314 (*itst)->AddSerie(new gdcmSerie(begin,end));
00315 }
00316 }
00317 }
00318
00319
00320
00321
00322
00323
00324
00325 void gdcmDicomDir::AddImageToEnd(ListTag::iterator begin,ListTag::iterator end)
00326 {
00327 if(patients.size()>0)
00328 {
00329 ListPatient::iterator itp=patients.end();
00330 itp--;
00331
00332 if((*itp)->GetStudies().size()>0)
00333 {
00334 ListStudy::iterator itst=(*itp)->GetStudies().end();
00335 itst--;
00336
00337 if((*itst)->GetSeries().size()>0)
00338 {
00339 ListSerie::iterator its=(*itst)->GetSeries().end();
00340 its--;
00341 (*its)->AddImage(new gdcmImage(begin,end));
00342 }
00343 }
00344 }
00345 }
00346
00347
00348
00349
00350
00351
00352
00353 void gdcmDicomDir::SetElements(std::string &path,ListHeader &list)
00354 {
00355 std::string patPrevName="", patPrevID="";
00356 std::string studPrevInstanceUID="", studPrevID="";
00357 std::string serPrevInstanceUID="", serPrevID="";
00358
00359 std::string patCurName, patCurID;
00360 std::string studCurInstanceUID, studCurID;
00361 std::string serCurInstanceUID, serCurID;
00362
00363 SetElement(path,GDCM_NONE,NULL);
00364
00365 ListTag::iterator debPat=listEntries.begin();
00366 for(ListHeader::iterator it=list.begin();it!=list.end();++it)
00367 {
00368
00369 patCurName=(*it)->GetEntryByNumber(0x0010,0x0010);
00370 patCurID=(*it)->GetEntryByNumber(0x0010,0x0011);
00371 studCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000d);
00372 studCurID=(*it)->GetEntryByNumber(0x0020,0x0010);
00373 serCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000e);
00374 serCurID=(*it)->GetEntryByNumber(0x0020,0x0011);
00375
00376 if(patCurName!=patPrevName || patCurID!=patPrevID)
00377 SetElement(path,GDCM_PATIENT,*it);
00378
00379
00380 if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID)
00381 SetElement(path,GDCM_STUDY,*it);
00382
00383
00384 if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID)
00385 {
00386 SetElement(path,GDCM_SERIE,*it);
00387 }
00388
00389
00390 SetElement(path,GDCM_IMAGE,*it);
00391
00392 patPrevName=patCurName;
00393 patPrevID=patCurID;
00394 studPrevInstanceUID=studCurInstanceUID;
00395 studPrevID=studCurID;
00396 serPrevInstanceUID=serCurInstanceUID;
00397 serPrevID=serCurID;
00398 }
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408 void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
00409 {
00410 std::list<gdcmElement> elemList;
00411 std::list<gdcmElement>::iterator it;
00412 guint16 tmpGr, tmpEl;
00413 gdcmDictEntry *dictEntry;
00414 gdcmHeaderEntry *entry;
00415 std::string val;
00416
00417 switch(type)
00418 {
00419 case GDCM_PATIENT:
00420 elemList=gdcmGlobal::GetDicomDirElements()->GetPatientElements();
00421 break;
00422 case GDCM_STUDY:
00423 elemList=gdcmGlobal::GetDicomDirElements()->GetStudyElements();
00424 break;
00425 case GDCM_SERIE:
00426 elemList=gdcmGlobal::GetDicomDirElements()->GetSerieElements();
00427 break;
00428 case GDCM_IMAGE:
00429 elemList=gdcmGlobal::GetDicomDirElements()->GetImageElements();
00430 break;
00431 case GDCM_NONE:
00432 elemList=gdcmGlobal::GetDicomDirElements()->GetMetaElements();
00433 break;
00434 default:
00435 return;
00436 }
00437
00438 for(it=elemList.begin();it!=elemList.end();++it)
00439 {
00440 tmpGr=it->group;
00441 tmpEl=it->elem;
00442
00443 dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
00444 entry=new gdcmHeaderEntry(dictEntry);
00445 entry->SetOffset(0);
00446
00447 if(header)
00448 val=header->GetEntryByNumber(tmpGr,tmpEl);
00449 else
00450 val=GDCM_UNFOUND;
00451
00452 if(val==GDCM_UNFOUND)
00453 {
00454 if((tmpGr==0x0004) &&(tmpEl==0x1130) )
00455 {
00456
00457 val=path;
00458 }
00459 else if( (tmpGr==0x0004) && (tmpEl==0x1500) )
00460 {
00461 if(header->GetFileName().substr(0,path.length())!=path)
00462 {
00463 dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect");
00464 val=header->GetFileName();
00465 }
00466 else
00467 val=&(header->GetFileName()[path.length()]);
00468 }
00469 else
00470 {
00471 val=it->value;
00472 }
00473 }
00474 entry->SetValue(val);
00475
00476 if(dictEntry)
00477 {
00478 if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
00479 {
00480 entry->SetLength(4);
00481 }
00482 else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
00483 {
00484 entry->SetLength(2);
00485 }
00486 else if(dictEntry->GetVR()=="SQ")
00487 {
00488 entry->SetLength(0xffffffff);
00489 }
00490 else
00491 {
00492 entry->SetLength(entry->GetValue().length());
00493 }
00494 }
00495
00496 listEntries.push_back(entry);
00497 }
00498 }
00499
00500 bool gdcmDicomDir::HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2)
00501 {
00502 return(*header1<*header2);
00503 }
00504
00505