2 //-----------------------------------------------------------------------------
3 #include "gdcmDicomDir.h"
7 #include "gdcmDirList.h"
12 #include <sys/types.h>
15 //-----------------------------------------------------------------------------
19 ELEMENTS(unsigned short int _group,unsigned short int _elem,std::string _value)
20 {group=_group;elem=_elem;value=_value;}
22 unsigned short int group;
23 unsigned short int elem;
28 //Meta Group Length : to be computed later
29 ELEMENTS(0x0002,0x0000,"12345"),
30 //File Meta Information Version
31 ELEMENTS(0x0002,0x0001,"\2\0\0\0"),
32 //Media Stored SOP Class UID i.e. : 'Media Storage Directory Storage'
33 ELEMENTS(0x0002,0x0002,"1.2.840.10008.1.3.10"),
34 //Media Stored SOP Instance UID : may be forged later
35 ELEMENTS(0x0002,0x0003,""),
36 //Transfer Syntax UID i.e. : Explicit VR - Little Endian
37 ELEMENTS(0x0002,0x0010,"1.2.840.10008.1.2.1"),
38 //Implementation Class UID : may be forged later
39 ELEMENTS(0x0002,0x0012,""),
40 //Implementation Version Name
41 ELEMENTS(0x0002,0x0013,"gdcmLib"),
43 ELEMENTS(0x0004,0x1130,""),
44 //Offset of the first dir of root dir entity : to be computed later
45 ELEMENTS(0x0004,0x1200,"0"),
46 //Offset of the last dir of root dir entity : to be computed later
47 ELEMENTS(0x0004,0x1202,"0"),
48 //File-set consistency flag
49 ELEMENTS(0x0004,0x1212,"0"),
50 //Directory record sequence : *length* to be set later
51 ELEMENTS(0x0004,0x1220,"0"),
52 ELEMENTS(0xffff,0xffff,"")
55 ELEMENTS patientElem[]={
56 ELEMENTS(0xfffe,0xe000,"0"),
57 // Offset of next directory record : to be computed later
58 ELEMENTS(0x0004,0x1400,"0"),
59 // Record in use flag : 65535(?)
60 ELEMENTS(0x0004,0x1410,"65535"),
61 // Offset of referenced lower-level dir entity : to be computed later
62 ELEMENTS(0x0004,0x1420,"0"),
63 // Directory Record Type
64 ELEMENTS(0x0004,0x1430,"PATIENT "), // don't remove trailing space !
66 // Specific Character Set
67 ELEMENTS(0x0008,0x0005,"ISO_IR 100"),
69 ELEMENTS(0x0010,0x0010,""),
71 ELEMENTS(0x0010,0x0020,""),
72 // Patient's Birthdate
73 ELEMENTS(0x0010,0x0030,""),
75 ELEMENTS(0x0010,0x0040,""),
76 ELEMENTS(0xffff,0xffff,"")
79 ELEMENTS studyElem[]={
80 ELEMENTS(0xfffe,0xe000,"0"),
81 // Offset of next directory record : to be computed later
82 ELEMENTS(0x0004,0x1400,"0"),
83 // Record in use flag : 65535(?)
84 ELEMENTS(0x0004,0x1410,"65535"),
85 // Offset of referenced lower-level dir entity : to be computed later
86 ELEMENTS(0x0004,0x1420,"0"),
87 // Directory Record Type
88 ELEMENTS(0x0004,0x1430,"STUDY "), // don't remove trailing space !
90 // Specific Character Set
91 ELEMENTS(0x0008,0x0005,"ISO_IR 100"),
93 ELEMENTS(0x0008,0x0020,""),
95 ELEMENTS(0x0008,0x0030,""),
97 ELEMENTS(0x0008,0x0050,""),
99 ELEMENTS(0x0008,0x1030,""),
100 // Study Instance UID : may be forged later
101 ELEMENTS(0x0020,0x000d,""),
102 // Study ID : may be forged later
103 ELEMENTS(0x0020,0x0010,""),
104 ELEMENTS(0xffff,0xffff,"")
108 ELEMENTS serieElem[]={
109 ELEMENTS(0xfffe,0xe000,"0"),
110 // Offset of next directory record : to be computed later
111 ELEMENTS(0x0004,0x1400,"0"),
112 // Record in use flag : 65535(?)
113 ELEMENTS(0x0004,0x1410,"65535"),
114 // Offset of referenced lower-level dir entity : to be computed later
115 ELEMENTS(0x0004,0x1420,"0"),
116 // Directory Record Type
117 ELEMENTS(0x0004,0x1430,"SERIES"), // don't add trailing space !
119 // Specific Character Set
120 ELEMENTS(0x0008,0x0005,"ISO_IR 100"),
122 ELEMENTS(0x0008,0x0021,""),
124 ELEMENTS(0x0008,0x0031,""),
126 ELEMENTS(0x0008,0x0060,""),
127 // Institution Name : may be forged later
128 ELEMENTS(0x0008,0x0080,""),
129 // Institution Address : may be forged later
130 ELEMENTS(0x0008,0x0081,""),
131 // Series Description : may be forged later
132 ELEMENTS(0x0008,0x103e,""),
133 // Series Instance UID : may be forged later
134 ELEMENTS(0x0020,0x000e,""),
135 // Series Number : may be forged later
136 ELEMENTS(0x0020,0x0011,"0"),
137 ELEMENTS(0xffff,0xffff,"")
140 ELEMENTS imageElem[]={
141 ELEMENTS(0xfffe,0xe000,"0"),
142 // Offset of next directory record : to be computed later
143 ELEMENTS(0x0004,0x1400,"0"),
144 // Record in use flag : 65535(?)
145 ELEMENTS(0x0004,0x1410,"65535"),
146 // Offset of referenced lower-level dir entity : to be computed later
147 ELEMENTS(0x0004,0x1420,"0"),
148 // Directory Record Type
149 ELEMENTS(0x0004,0x1430,"IMAGE "), // don't remove trailing space !
151 // Referenced File ID : to be set later(relative File Name)
152 ELEMENTS(0x0004,0x1500,""),
153 // Referenced SOP Class UID in File : may be forged later
154 ELEMENTS(0x0004,0x1510,""),
155 // Referenced SOP Class UID in File : may be forged later
156 ELEMENTS(0x0004,0x1511,""),
157 // Referenced Transfer Syntax in File
158 ELEMENTS(0x0004,0x1512,""),
159 // Specific Character Set
160 ELEMENTS(0x0008,0x0005,"ISO_IR 100"),
162 ELEMENTS(0x0008,0x0008,""),
163 // SOP Class UID : to be set/forged later
164 ELEMENTS(0x0008,0x0016,""),
165 // SOP Instance UID : to be set/forged later
166 ELEMENTS(0x0008,0x0018,""),
168 ELEMENTS(0x0008,0x0023,""),
170 ELEMENTS(0x0008,0x0033,""),
171 // Referenced Image Sequence : to be set/forged later
172 ELEMENTS(0x0008,0x1040,""),
173 ELEMENTS(0xfffe,0xe000,"0"),
174 // Referenced SOP Class UID : to be set/forged later
175 ELEMENTS(0x0008,0x1150,""),
176 // Referenced SOP Instance UID : to be set/forged later
177 ELEMENTS(0x0008,0x1155,""),
179 ELEMENTS(0x0020,0x0013,"0"),
180 // Image Position Patient
181 ELEMENTS(0x0020,0x0032,"0"),
182 // Image Orientation(Patient)
183 ELEMENTS(0x0020,0x0037,"0"),
184 // Frame of Reference UID
185 ELEMENTS(0x0020,0x0052,"0"),
187 ELEMENTS(0x0028,0x0010,"0"),
189 ELEMENTS(0x0028,0x0011,"0"),
191 ELEMENTS(0x0028,0x0030,"0"),
193 ELEMENTS(0x0050,0x0004,"0"),
194 ELEMENTS(0xffff,0xffff,"")
197 //-----------------------------------------------------------------------------
198 // Constructor / Destructor
200 * \ingroup gdcmDicomDir
203 * @param exception_on_error
205 gdcmDicomDir::gdcmDicomDir(const char *FileName,
206 bool exception_on_error):
207 gdcmParser(FileName,exception_on_error,true)
209 if( GetListEntry().begin()==GetListEntry().end() )
211 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
212 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir");
214 std::string path=FileName;
217 int pos1=path.rfind("/");
218 int pos2=path.rfind("\\");
230 * \ingroup gdcmDicomDir
232 * @param exception_on_error
234 gdcmDicomDir::gdcmDicomDir(ListTag *l,
235 bool exception_on_error):
236 gdcmParser(exception_on_error )
243 * \ingroup gdcmDicomDir
244 * \brief Canonical destructor
246 gdcmDicomDir::~gdcmDicomDir()
248 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
254 //-----------------------------------------------------------------------------
256 void gdcmDicomDir::Print(std::ostream &os)
258 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
260 (*cc)->SetPrintLevel(printLevel);
265 //-----------------------------------------------------------------------------
268 * \ingroup gdcmDicomDir
269 * \brief writes on disc a DICOMDIR
270 * \ warning does NOT add the missing elements in the header :
271 * \ it's up to the user doing it !
272 * @param fileName file to be written to
275 bool gdcmDicomDir::Write(std::string fileName)
279 fp1=fopen(fileName.c_str(),"wb");
282 printf("Failed to open(write) File [%s] \n",fileName.c_str());
287 filePreamble=(char*)calloc(128,1);
288 fwrite(filePreamble,128,1,fp1);
289 fwrite("DICM",4,1,fp1);
292 WriteEntries(fp1,DICOMDIR);
299 //-----------------------------------------------------------------------------
302 * \ingroup gdcmDicomDir
306 void gdcmDicomDir::NewDicomDir(std::string path)
308 gdcmDirList fileList(path,1);
314 for(gdcmDirList::iterator it=fileList.begin();
315 it!=fileList.end(); ++it)
317 // std::cout<<*it<<std::endl;
318 header=new gdcmHeader(it->c_str());
319 if(header->IsReadable())
320 list.push_back(header);
325 SetElements(path,list);
328 //-----------------------------------------------------------------------------
331 * \ingroup gdcmDicomDir
335 void gdcmDicomDir::CreateDicomDir()
337 // The list is parsed. When a tag is found :
338 // 1 - we save the beginning iterator
339 // 2 - we continue to parse
340 // 3 - we find an other tag
341 // + we create the object for the precedent tag
344 gdcmDicomDirType type=gdcmDicomDir::GDCM_NONE;
345 ListTag::iterator begin;
346 ListTag::iterator end;
348 begin=listEntries.begin();
350 for(ListTag::iterator i=listEntries.begin();i !=listEntries.end();++i)
352 // std::cout << std::hex <<(*i)->GetGroup() <<
353 // " " <<(*i)->GetElement() << endl;
355 std::string v=(*i)->GetValue();
358 // std::cout<<"PATIENT"<<std::endl;
360 AddObjectToEnd(type,begin,end);
362 type=gdcmDicomDir::GDCM_PATIENT;
368 // std::cout<<"STUDY"<<std::endl;
370 AddObjectToEnd(type,begin,end);
372 type=gdcmDicomDir::GDCM_STUDY;
378 // std::cout<<"SERIES"<<std::endl;
380 AddObjectToEnd(type,begin,end);
382 type=gdcmDicomDir::GDCM_SERIE;
388 // std::cout<<"IMAGE"<<std::endl;
390 AddObjectToEnd(type,begin,end);
392 type=gdcmDicomDir::GDCM_IMAGE;
397 end=GetListEntry().end();
398 AddObjectToEnd(type,begin,end);
401 * \ingroup gdcmDicomDir
405 void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end)
412 case gdcmDicomDir::GDCM_PATIENT:
413 AddPatientToEnd(begin,end);
415 case gdcmDicomDir::GDCM_STUDY:
416 AddStudyToEnd(begin,end);
418 case gdcmDicomDir::GDCM_SERIE:
419 AddSerieToEnd(begin,end);
421 case gdcmDicomDir::GDCM_IMAGE:
422 AddImageToEnd(begin,end);
428 * \ingroup gdcmDicomDir
432 void gdcmDicomDir::AddPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
434 patients.push_back(new gdcmPatient(begin,end));
438 * \ingroup gdcmDicomDir
442 void gdcmDicomDir::AddStudyToEnd(ListTag::iterator begin,ListTag::iterator end)
444 if(patients.size()>0)
446 ListPatient::iterator itp=patients.end();
448 (*itp)->AddStudy(new gdcmStudy(begin,end));
452 * \ingroup gdcmDicomDir
456 void gdcmDicomDir::AddSerieToEnd(ListTag::iterator begin,ListTag::iterator end)
458 if(patients.size()>0)
460 ListPatient::iterator itp=patients.end();
463 if((*itp)->GetStudies().size()>0)
465 ListStudy::iterator itst=(*itp)->GetStudies().end();
467 (*itst)->AddSerie(new gdcmSerie(begin,end));
473 * \ingroup gdcmDicomDir
477 void gdcmDicomDir::AddImageToEnd(ListTag::iterator begin,ListTag::iterator end)
479 if(patients.size()>0)
481 ListPatient::iterator itp=patients.end();
484 if((*itp)->GetStudies().size()>0)
486 ListStudy::iterator itst=(*itp)->GetStudies().end();
489 if((*itst)->GetSeries().size()>0)
491 ListSerie::iterator its=(*itst)->GetSeries().end();
493 (*its)->AddImage(new gdcmImage(begin,end));
500 * \ingroup gdcmDicomDir
504 void gdcmDicomDir::SetElements(std::string &path,ListHeader &list)
506 std::string patPrevName="", patPrevID="";
507 std::string studPrevInstanceUID="", studPrevID="";
508 std::string serPrevInstanceUID="", serPrevID="";
510 std::string patCurName, patCurID;
511 std::string studCurInstanceUID, studCurID;
512 std::string serCurInstanceUID, serCurID;
514 SetElement(path,GDCM_NONE,NULL);
516 ListTag::iterator debPat=listEntries.begin();
517 for(ListHeader::iterator it=list.begin();it!=list.end();++it)
519 // get the current file characteristics
520 patCurName=(*it)->GetEntryByNumber(0x0010,0x0010);
521 patCurID=(*it)->GetEntryByNumber(0x0010,0x0011);
522 studCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000d);
523 studCurID=(*it)->GetEntryByNumber(0x0020,0x0010);
524 serCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000e);
525 serCurID=(*it)->GetEntryByNumber(0x0020,0x0011);
527 if(patCurName!=patPrevName || patCurID!=patPrevID)
528 SetElement(path,GDCM_PATIENT,*it);
530 // if new Study Deal with 'STUDY' Elements
531 if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID)
532 SetElement(path,GDCM_STUDY,*it);
534 // if new Serie Deal with 'SERIE' Elements
535 if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID)
537 SetElement(path,GDCM_SERIE,*it);
540 // Always Deal with 'IMAGE' Elements
541 SetElement(path,GDCM_IMAGE,*it);
543 patPrevName=patCurName;
545 studPrevInstanceUID=studCurInstanceUID;
546 studPrevID=studCurID;
547 serPrevInstanceUID=serCurInstanceUID;
553 * \ingroup gdcmDicomDir
557 void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
560 guint16 tmpGr, tmpEl;
561 gdcmDictEntry *dictEntry;
562 gdcmHeaderEntry *entry;
568 elemList=patientElem;
588 tmpGr=elemList[i].group;
589 tmpEl=elemList[i].elem;
593 dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
595 entry=new gdcmHeaderEntry(dictEntry);
596 entry->SetOffset(0); // just to avoid missprinting
599 val=header->GetEntryByNumber(tmpGr,tmpEl);
603 if(val==GDCM_UNFOUND)
605 if((tmpGr==0x0004) &&(tmpEl==0x1130) )
607 // TODO force the *end* File Name(remove path)
610 else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) // Only used for image
612 if(header->GetFileName().substr(0,path.length())!=path)
614 dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect");
615 val=header->GetFileName();
618 val=&(header->GetFileName()[path.length()]);
622 val=elemList[i].value;
625 entry->SetValue(val);
629 if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
633 else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
637 else if(dictEntry->GetVR()=="SQ")
639 entry->SetLength(0xffffffff);
643 entry->SetLength(entry->GetValue().length());
647 listEntries.push_back(entry);
651 //-----------------------------------------------------------------------------