3 This is a vi-able/notepad-able document to (try to) explain in a few words
4 how to use efficently gdcm.
5 -->Feel free to send/add your comments/suggestions/modifications.
6 -->Don't try to 'beautify' this page.
7 (I plane to rewrite it in html, as soon as there is enough 'content' within it)
12 ------------------------------------------------------------------------
16 1) How to Read a DICOM file
17 ===========================
20 1-1-1-1) Deal with the file header
21 1-1-1-2) Load the 'pixels' in memory
22 1-1-1-3) Get the value of a single Dicom DataElement
23 1-1-1-4) Get the value of a Dicom Sequence
34 1-4) Retrictions for Python users
36 2) How to write DICOM file
37 ==========================
40 2-1-1-1) Deal with optional DataElements
41 2-1-1-1-1) Add a single Dicom DataElement // TODO
42 2-1-1-1-2) Add a Dicom Sequence // TODO
49 2-4) Retrictions for Python users
51 3) Some 'Command line' utilities
52 ================================
55 3-) exXCoherentFileSet
58 3-) AnonymizeMultiPatient
63 3-) exMoveImagesToSingleSerieUID
66 3-) vtkgdcmSerieViewer2
71 ----------------------------------------------------------------------------
76 If you are not familiar with DICOM files, use :
78 PrintFile filein=yourDicomFile.dcm
80 and have a look at the output.
81 You'll see a lot of self explanatory (?) lines, e.g.
83 D 0008|0021 [DA] [Series Date] [20020524]
84 D 0008|0060 [CS] [Modality] [US]
85 D 0018|602c [FD] [Physical Delta X][0]
86 D 0020|0013 [IS] [Instance Number] [5 ]
87 D 0028|0010 [US] [Rows] [480]
88 D 0011|0010 [ ] [gdcm::Unknown] [DLX_PATNT_01]
89 D 0028|1222 [OW] [Segmented Green Palette Color Lookup Table Data]
90 ===> [gdcm::Binary data loaded;length = 113784]
92 0008|0021 : 'Group Number'|'Element Number' -> The Element identifier
93 Have a look at gdcm/Dicts/dicomV3.dic for the whole list of Elements
95 DA : The 'Value Representation' : DA for Date, US for Unsigned Short, ...
96 Have a look at gdcm/Dicts/dicomVR.dic for the set of possible values
98 [Series Date] : The 'official' English name of the Element
99 (When *you* have to deal with a given Element, its meaning should be clear for
102 [20020524] : the value, printed in a human readable way.
105 D 0028|1222 [OW] [Segmented Green Palette Color Lookup Table Data]
106 ===> [gdcm::Binary data loaded;length = 113784]
107 is displayed, it means that it's a 'long' binary area, gdcm (I) decided not to
110 D 0011|0010 [ ] [gdcm::Unknown] [DLX_PATNT_01]
111 is a 'Private (or Shadow) Element', depending on the manufacturer.
112 It's *not* known within the 'official' Dicom Dictionnary.
113 Except if someone told you, you cannot guess the meaning of such an element.
114 Probabely, you'll never have to deal with Shadow Elements (hope so!).
116 You can find also something like :
118 S 0018|6011 [SQ] [Sequence of Ultrasound Regions]
119 | --- SQItem number 0
120 | D fffe|e000 [UL] [Item]
121 | D 0018|6018 [UL] [Region Location Min X0] [32]
122 | D 0018|601a [UL] [Region Location Min Y0] [24]
123 | D 0018|601c [UL] [Region Location Max X1] [335]
124 | D 0018|601e [UL] [Region Location Max Y1] [415]
125 | D 0018|602c [FD] [Physical Delta X] [0.0382653]
126 | D 0018|602e [FD] [Physical Delta Y] [0.0382653]
127 | --- SQItem number 1
128 | D fffe|e000 [UL] [Item]
129 | D 0018|6018 [UL] [Region Location Min X0] [336]
130 | D 0018|601a [UL] [Region Location Min Y0] [24]
131 | D 0018|601c [UL] [Region Location Max X1] [639]
132 | D 0018|601e [UL] [Region Location Max Y1] [415]
133 | D 0018|602c [FD] [Physical Delta X] [0.0382653]
134 | D 0018|602e [FD] [Physical Delta Y] [0.0382653]
135 | --- SQItem number 2
136 | D fffe|e000 [UL] [Item]
137 | D 0018|6018 [UL] [Region Location Min X0] [32]
138 | D 0018|601a [UL] [Region Location Min Y0] [40]
139 | D 0018|601c [UL] [Region Location Max X1] [63]
140 | D 0018|601e [UL] [Region Location Max Y1] [103]
141 | D 0018|6024 [US] [Physical Units X Direction] [0]
142 | D 0018|6026 [US] [Physical Units Y Direction] [0]
143 | D 0018|602c [FD] [Physical Delta X] [0]
144 | D 0018|602e [FD] [Physical Delta Y] [0]
146 0018|6011 is a 'Sequence' (SQ), composed of various Sequence Items(SQItem)
147 Each SQItem is a set of Elements (an Element may be a DataElement (D) or a
148 Sequence (S), recursively.
149 Probabely, you'll never have to deal with Sequences (hope so!).
151 1) How to Read a DICOM File
152 ===========================
160 1-1-1-1) Deal with the file header
162 The first step is to load the file header :
164 gdcm::File *f = new gdcm::File();
165 f->SetLoadMode(NO_SEQ); | depending on what
166 f->SetLoadMode(NO_SHADOW); | you want *not*
167 f->SetLoadMode(NO_SEQ | NO_SHADOW);| to load from the
168 f->SetLoadMode(NO_SHADOWSEQ); | target file
169 f->SetFileName(fileName);
173 The 'long' Data Element (>4096 char) are not loaded by default
174 You may modify this default length :
175 f->SetMaxSizeLoadEntry(int yourOwnMaxSize);
176 Or ask to force the loading of given Data Elements, whatever their size is:
177 f->AddForceLoadElement (uint16_t group, uint16_t elem);
178 before calling gdcm::File::Load();
181 Except if you are really aware about it, do *not* use SetLoadMode().
183 Check if the file is gdcm-readable.
185 if ( !f->IsReadable() )
186 std::cout << "major troubles on [" << f->GetFileName() <<"]"
189 Decide if this is a 'File Of Interest' for you.
190 Check some fields, e.g
192 std::string StudyDate = f->GetEntryString(0x0008,0x0020);
193 std::string PatientName = f->GetEntryString(0x0010,0x0010);
194 std::string PatientID = f->GetEntryString(0x0010,0x0020);
195 std::string PatientSex = f->GetEntryString(0x0010,0x0040);
196 std::string Modality = f->GetEntryString(0x0008,0x0060);
198 (or whatever you feel like ...)
200 1-1-1-2) Load the 'pixels' in memory
202 Next step is to load the pixels in memory.
203 Uncompression (JPEG lossless, JPEG lossy, JPEG 2000, RLE, ...)
204 is automatically performed if necessary.
206 gdcm::FileHelper *fh = gdcm::FileHelper::New(f);
207 void *imageData = fh->GetImageDataRaw();
208 uint32_t dataSize = fh->GetImageDataRawSize();
210 Generally, you work on 'Grey level' images (as opposed to RGB images).
211 Depending on the Pixel size (8/16/32 bits) and the Pixel Type (signed/unsigned),
212 you cast the imageData
214 std::string pixelType = f->GetPixelType();
216 Possible values are :
218 - "8U" unsigned 8 bit,
220 - "16U" unsigned 16 bit,
221 - "16S" signed 16 bit,
222 - "32U" unsigned 32 bit,
223 - "32S" signed 32 bit,
224 - (NEITHER 'float' NOR 'double' pixels in DICOM!)
226 int dimX = f->GetXSize();
227 int dimY = f->GetYSize();
228 int dimZ = f->GetZSize(); // meaningfull only for 'Volumes' or 'multiframe files'
229 int dimT = f->GetTSize(); // meaningfull only for 4D objects (?)
231 Now, you can enjoy your image !
233 Sometimes, you deal with 'colour' images :-(
234 They may be stored, on disc, as :
239 Grey level images + LUT.
241 You'll get an 'RGB Pixels' image in memory if you use:
243 gdcm::FileHelper *fh = gdcm::FileHelper::New(f);
244 void *imageData = fh->GetImageData();
245 uint32_t dataSize = fh->GetImageDataSize();
248 1-1-1-3) Get the value of a single Dicom DataElement
250 1-1-1-3-1) as a std::string
252 - some DataEntries are 'human readable' (those whose VR is AE, DA, DS, PN, SH, TM)
253 Get their value using group number-element number :
254 std::string patientName = f->GetEntryString(0x0010,0x0010);
256 - Some DataEntries are stored with their own binary representation, but maybe you feel like
257 to get them in a 'human readable' form (those whose VR is FL, FD, SL, SS, UL, US)
258 Get their value using group number-element number :
259 std::string rowNumber =f->GetEntryString(0x0028, 0x0010);// nb of Rows
261 (of course, the very often used DataEntries have their own accessors :
262 e.g. GetXsize, GetYSize, GetSpacing, GetImageOrientationPatient, GetImagePositionPatient,
263 GetRescaleSlope, GetRescaleIntercept, GetNumberOfScalarComponents, etc -see gdcmFile.h-)
266 1-1-1-3-3) as a void* pointer
267 - Some DataEntries are stored with their own binary representation, and you want to get them 'as they are'.
268 You will have to cast them, according to the knowledge you have about them.
269 LutRedData = (uint8_t*)f->GetEntryBinArea( 0x0028, 0x1201 );
271 1-1-1-4) Get the value(s) of a Dicom Sequence
273 Actually, a 'Dicom Sequence' is composed of a list a 'Sequence Items',
274 each Sequence Item is a set of DataElement (that can be a Sequence Element, recursively).
275 You have to get the Sequence element, to get its number of Sequence items, to iterate on each one.
278 SeqEntry *seqEntry = f->GetSeqEntry(0x3006,0x0020); //Structure Set ROI sequence
279 unsigned int n = seqEntry->GetNumberOfSQItems(); // useless : just to see !
280 currentItem = seqEntry->GetFirstSQItem(); // Get the first ROI
281 while (currentItem != NULL) {
282 std::string roiName = currentItem->GetEntryString(0x3006,0x0026); //ROI name
283 std::string roiDescr = currentItem->GetEntryString(0x3006,0x0028); //ROI description
285 // do what you want with the current ROI
286 currentItem = seqEntry->GetNextSQItem(); // Get the next ROI
293 If you are 150 % sure of the files you're dealing with, just read the files you
294 feel like, and concatenate the pixels.
296 Sometimes you are not sure at all (say : you were given a CDROM with an amount
297 of images, laying in a Directories tree-like structure, you don't know anything
298 about the Patients, and so on)
300 A class gdcm::SerieHelper is designed to help solving this problem.
303 gdcm::SerieHelper *sh = gdcm::SerieHelper::New();
304 while (int i=0; i < nbOfFiles; i++) {
305 sh->AddFileName(currentFileName[i]);
308 You can also pass a 'root directory', and ask or not for recursive parsing.
309 gdcm::SerieHelper *sh = gdcm::SerieHelper::New();
310 sh->SetDirectory(yourRootDirectoryName, true); // true : recursive parsing
312 Files are 'splitted' into as many 'Single Serie UID File Set'
313 as Series Instance UID ( 0020|000e );
315 // -------- skip this one, for a first reading ! -----------
317 Sometimes, the Serie UID is not enough to disseminate properly the images.
318 We may want to disseminate into multiple sub serie when needed.
321 void SerieHelper::SetUseSeriesDetails(bool s);
322 /// This function will add the following DICOM tag as being part of a
324 /// 0020 0011 Series Number
325 /// 0018 0024 Sequence Name
326 /// 0018 0050 Slice Thickness
328 /// 0028 0011 Columns
330 If it's not enough for you, use :
331 void SerieHelper::AddSeriesDetail(uint16_t group, uint16_t elem, bool convert);
333 std::string SerieHelper::CreateUniqueSeriesIdentifier(gdcm::File *inFile);
334 void SerieHelper::CreateDefaultUniqueSeriesIdentifier();
336 You may also create a "tokenizable' File Identifier of your own, using :
337 void SerieHelper::AddSeriesDetail(uint16_t group, uint16_t elem, bool convert);
339 std::string SerieHelper::CreateUserDefinedFileIdentifier(gdcm::File *inFile);
340 and use it as you feel like.
342 // ------------ Resume reading, here !--------------------
344 If you want to 'order' the files within each 'Single Serie UID File Set'
345 (to build a volume, for instance), use :
347 gdcm::FileList *l = sh->GetFirstSingleSerieUIDFileSet();
350 sh->OrderFileList(l); // sort the list
351 l = sh->GetNextSingleSerieUIDFileSet();
354 The sorting will be performed on the ImagePositionPatient;
355 if not found, on ImageNumber;
356 if not found, on the File Name.
358 Aware user is allowed to pass his own comparison function
359 (if he knows, for instance, the files must be sorted on 'Trigger Time')
360 He will use the method
361 void SerieHelper::SetUserLessThanFunction( bool(*) userFunc((File *,File *) );
362 He may ask for a reverse sorting :
363 sh->SetSortOrderToReverse();
364 or back to Direct Order
365 sh->SetSortOrderToDirect();
367 If, for any reason of his own, user already get the file headers,
368 he may add the gdcm::File (instead of the file name) to the SerieHelper.
370 gdcm::SerieHelper *sh = gdcm::SerieHelper::New();
371 while (int i=0; i < nbOfFiles; i++) {
372 sh->AddFile(currentFile[i]);
374 * \warning : this method should be used by aware users only!
375 * User is supposed to know the files he want to deal with
376 * and consider them they belong to the same Set
377 * (even if their Serie UID is different)
378 * user will probabely OrderFileList() this list (actually, ordering
379 * user choosen gdm::File is the sole interest of this method)
380 * Moreover, using vtkGdcmReader::SetCoherentFileList() will avoid
381 * vtkGdcmReader parsing twice the same files.
382 * *no* coherence check is performed, but those specified
383 * by SerieHelper::AddRestriction()
385 User may want to exclude some files.
387 void SerieHelper::AddRestriction(uint16_t group, uint16_t elem,
388 std::string const &value, int op);
391 /// \brief comparison operators
399 gdcm::SerieHelper *sh = gdcm::SerieHelper::New();
400 sh->AddRestriction(0x0010,0x0040,"F",GDCM_EQUAL); // Patient's Sex
401 sh->AddRestriction(0x0008,0x0060,"MR",GDCM_DIFFERENT); // Modality
402 while (int i=0; i < nbOfFiles; i++) {
404 User wants to deal only with Female patient, any Modality but MR (why not?)
406 Maybe user knows there are several images with the same position
407 and *no dicom field* may discriminates them.
408 He wants to drop the 'duplicate images'
410 sh->SetDropDuplicatePositions(true);
412 Sometimes the previous stuff is *not enough* !
414 Within a SingleSerieUIDFileSet, you can have have various orientations,
415 or various positions, at various times. (not only various position , at a single
416 time, for a single orientation).
418 User may consider that dealing only with the 'Series Instance UID'
419 is not enough and wishes to 'refine' the image selection :
421 Suppose he has a Single Serie UID File Set (gdcm::FileList).
422 He may ask to split it into several 'X Coherent File Sets' (X stands for
425 gdcm::SerieHelper *s;
426 gdcm::XCoherentFileSetmap xcm;
427 gdcm::FileList *l = s->GetFirstSingleSerieUIDFileSet(); // or what you want
430 The following methods must be called by user, depending on
431 what *he* wants to do, at application time.
432 - *he* only knows what his Series contain ! -
433 They return a std::map of Filesets (actually : a std::map of std::vector<gdcm::File* >).
435 He may ask for 'splitting' on the Orientation:
436 gdcm::XCoherentFileSetmap xcm = s->SplitOnOrientation(l);
438 He may ask for 'splitting' on the Position:
439 gdcm::XCoherentFileSetmap xcm = s->SplitOnPosition(l);
441 He may ask for 'splitting' on the any DataElement you feel like :
442 gdcm::XCoherentFileSetmap xcm = s->SplitOnTagValue(l, group,elem);
445 He can now work on each 'X Coherent File Set' within the std::map
447 for (gdcm::XCoherentFileSetmap::iterator i = xcm.begin();
452 // ask for 'ordering' according to the 'Image Position Patient'
453 // Sorting the Fileset (*) is mandatory!
454 // ( computing an accurate Series ZSpacing -whenever possible- is a side effect ...)
456 s->OrderFileList((*i).second); // sort the XCoherent Fileset
459 (have a look at gdcm/Examples/exXCoherentFileSet.cxx for an example)
463 a vtkGdcmReader() method ( derived from vtkReader() ) is available.
468 vtkGdcmReader *reader = vtkGdcmReader::New();
469 reader->SetFileName( yourDicomFilename );
470 reader->SetLoadMode( yourLoadMode); // See C++ part
472 vtkImageData* ima = reader->GetOutput();
473 int* Size = ima->GetDimensions();
479 If you are 150 % sure of the files you're dealing with, just 'add' the files you
482 vtkGdcmReader *reader = vtkGdcmReader::New();
483 for(int i=1; i< yourNumberOfFiles; i++)
484 reader->AddFileName( yourTableOfFileNames[i] );
485 reader->SetLoadMode( yourLoadMode); // See C++ part
487 vtkImageData* ima = reader->GetOutput();
488 int* Size = ima->GetDimensions();
491 Warning : The first file is assumed to be the reference file.
492 All the inconsistent files (different sizes, pixel types, etc) are discarted
493 and replaced by a black image !
495 User is allowed to pass a Pointer to a function of his own
496 to allow modification of pixel order (i.e. : Mirror, UpsideDown, )
497 to gdcm::FileHeleper, using SetUserFunction(userSuppliedFunction)
499 described as : void userSuppliedFunction(uint8_t *im, gdcm::File *f);
501 NB : the "uint8_t *" type of first param is just for prototyping.
502 User will Cast it according what he found with f->GetPixelType()
503 See vtkgdcmSerieViewer for an example
506 Many users expect from vtkGdcmReader it 'orders' the images
507 (Actually, that's the job of gdcm::SerieHelper ...)
508 When user knows the files with same Serie UID have same sizes,
509 same 'pixel' type, same color convention, ...
510 the right way to proceed is as follow :
512 gdcm::SerieHelper *sh= new gdcm::SerieHelper();
513 // if user wants *not* to load some parts of the file headers
514 sh->SetLoadMode(yourLoadMode);
516 // if user wants *not* to load some files
517 sh->AddRestriction(group, element, value, operator);
518 sh->AddRestriction( ...
519 sh->SetDirectory(directoryWithImages);
521 // if user *knows* how to order his files
522 sh->SetUserLessThanFunction(userSuppliedComparisonFunction);
524 // if user wants to sort reverse order
525 sh->SetSortOrderToReverse();
527 // here, we suppose only the first 'Single SerieUID' Fileset is of interest
528 // Just iterate using sh->NextSingleSerieUIDFileSet()
529 // if you want to get all of them
530 gdcm::FileList *l = sh->GetFirstSingleSerieUIDFileSet();
532 // if user is doesn't trust too much the files with same Serie UID
533 if ( !sh->IsCoherent(l) )
534 return; // not same sizes, or not same 'pixel type' -> stop
536 // Maybe user knows there are several images with the same position
537 // and *no dicom field* may discriminates them.
538 // He wants to drop the 'duplicate images'
540 sh->SetDropDuplicatePositions(true);
542 // Sorting the Fileset (*) is mandatory!
543 // ( computing an accurate Series ZSpacing is a side effect ...)
544 sh->OrderFileList(l);
546 vtkGdcmReader *reader = vtkGdcmReader::New();
547 // if user wants to modify pixel order (Mirror, TopDown, ...)
548 // he has to supply the function that does the job
549 // (a *very* simple example is given in vtkgdcmSerieViewer.cxx)
550 reader->SetUserFunction (userSuppliedFunction);
552 // to pass a 'Single SerieUID' Fileset as produced by gdcm::SerieHelper
553 reader->SetCoherentFileList(l);
559 User may also pass an 'X Coherent Fileset', created by one of the following
560 methods : (see 1-1-2 for more details)
562 xcm = sh->SplitOnOrientation(l);
563 xcm = sh->SplitOnPosition(l);
564 xcm = sh->SplitOnTagValue(l, groupelem[0],groupelem[1]);
568 You can see a full example in vtk/vtkgdcmSerieViewer2.cxx
570 vtkgdcmSerieViewer dirname=Dentist mirror
571 vtkgdcmSerieViewer dirname=Dentist reverse
572 vtkgdcmSerieViewer dirname=Dentist reverse upsidedown
575 1-4) Retrictions for Python users
576 ---------------------------------
578 None of the methods receiving a function pointer, or a gdcm::File as a parameter
583 2) How to write DICOM file
584 ==========================
591 In C++, if you have already the pixels in main memory,
592 you just have to process as follow :
594 --> Create an empty gdcm::File
595 gdcm::File *file = gdcm::File::New();
597 std::ostringstream str;
599 // --> Set the mandatory fields
600 // Set the image size
603 file->InsertEntryString(str.str(),0x0028,0x0010,"US"); // Rows
606 file->InsertEntryString(str.str(),0x0028,0x0011,"US"); // Columns
609 file->InsertEntryString(str.str(),0x0028,0x0008, "IS"); // Nbr of Frames
610 // Set the pixel type
612 str << componentSize; //8, 16, 32
613 file->InsertEntryString(str.str(),0x0028,0x0100,"US"); // Bits Allocated
615 str << componentUse; // may be 12 or 16 if componentSize =16
616 file->InsertEntryString(str.str(),0x0028,0x0101,"US"); // Bits Stored
618 str << componentSize - 1 ;
619 file->InsertEntryString(str.str(),0x0028,0x0102,"US"); // High Bit
620 // Set the pixel representation // 0/1
623 file->InsertEntryString(str.str(),0x0028,0x0103, "US"); // Pixel Representation
624 // Set the samples per pixel // 1:Grey level, 3:RGB
627 file->InsertEntryString(str.str(),0x0028,0x0002, "US"); // Samples per Pixel
629 //--> Set Optional fields
630 se further how to deal with optional fields
632 //--> Create a gdcm::FileHelper
633 gdcm::FileHelper *fileH = gdcm::FileHelper::New(file);
635 //--> Tell the FileHelper what you did for creating the image:
637 // gdcm cannot guess how user built his image
638 // (and therefore cannot be clever about some Dicom fields)
639 // It's up to the user to tell gdcm what he did.
640 // -1) user created ex nihilo his own image and wants to write it
643 // -2) user modified the pixels of an existing image.
645 // -3) user created a new image, using existing a set of images
646 // (eg MIP, MPR, cartography image)
648 // -4) user modified/added some tags *without processing* the pixels
649 // (anonymization, ...)
650 // UNMODIFIED_PIXELS_IMAGE
651 // -Probabely some more to be added
652 //(see gdcmFileHelper.h for more explanations)
656 fileH->SetContentType(GDCM_NAME_SPACE::USER_OWN_IMAGE);
657 fileH->SetContentType(GDCM_NAME_SPACE::FILTERED_IMAGE);
658 fileH->SetContentType(GDCM_NAME_SPACE::CREATED_IMAGE);
659 fileH->SetContentType(GDCM_NAME_SPACE::UNMODIFIED_PIXELS_IMAGE);
661 // depending on what you did before!
663 //--> Set the Image Data
664 fileH->SetImageData((unsigned char *)imageData,size);
665 // ( Casting as 'unsigned char *' is just to avoid warnings.
666 // It doesn't change the values. )
668 //--> Set the compression type :
669 fileH->SetWriteTypeToJPEG();
670 fileH->SetWriteTypeToJPEG2000();
671 fileH->SetWriteTypeToDcmExplVR(); // Explicit Value Represtation (no compression)
672 fileH->SetWriteTypeToDcmImplVR(); // Implicit Value Represtation (no compression)
674 fileH->SetWriteModeToRaw(); // Probabely you don't want to convert any LUT into RGB pixels ...
677 fileH->Write(fileName.str());
679 //This works for a single image (singleframe or multiframe)
681 2-1-1-1) Deal with optional DataElements // TODO : finish it
682 Any Data Element may be added (it's up to the user to understand what he is doing!)
683 The supplied methods 'InsertXxx' will create the DataElement or replace it if it already exists.
684 Have a look at gdcm/Dict/dicomV3.dic to see what are the various DICOM fields, with their VR.
686 2-1-1-1-1) Add a single Dicom DataElement // TODO : finish it
689 DataEntry * File::InsertEntryString(std::string const &value,
690 uint16_t group, uint16_t elem,
691 VRKey const &vr = GDCM_VRUNKNOWN);
693 // (e.g. : patient name, patient ID, ... , or what you want,
694 // using their Dicom identifier, and 'VR'
695 file->InsertEntryString("MyOwnPatient" ,0x0010,0x0010,"PN"); // 0010 0010 : Patient's Name
697 DataEntry * File:InsertEntryBinArea(uint8_t *binArea, int lgth,
698 uint16_t group, uint16_t elem,
699 VRKey const &vr = GDCM_VRUNKNOWN);
701 2-1-1-1-2) Add a Dicom Sequence // TODO : finish it
702 SeqEntry * File::InsertSeqEntry(uint16_t group, uint16_t elem);
706 /// \todo : write it!
709 // If you deal with a Serie of images, it up to you to tell gdcm, for each image,
710 // what are the values of
711 // 0020 0032 DS 3 Image Position (Patient)
712 // 0020 0037 DS 6 Image Orientation (Patient)
714 // You will probabely want that all the images of your file set belong to the same 'Serie'
720 /// \todo : write it!
725 /// \todo : finish it!
727 // User of the CVS version of VTK 5 may set some 'Medical Image Properties'
728 // Only the predefined DataElements are available :
729 // PatientName, PatientID, PatientAge, PatientSex, PatientBirthDate, StudyID
730 // It's reasonably enough for any 'decent use'
732 // todo : explain how to use it.
733 //vtkMedicalImageProperties
735 // Aware user is allowed to pass his own gdcm::File *,
736 // so he may set *any Dicom field* he wants.
737 // (including his own Shadow Elements, or any gdcm::SeqEntry)
738 // gdcm::FileHelper::CheckMandatoryElements() will check inconsistencies,
739 // as far as it knows how.
740 // Sorry, not yet available under Python.
741 //vtkSetMacro(GdcmFile, gdcm::File *);
743 void vtkGdcmWriter::SetGdcmFile(gdcm::File *);
745 // gdcm cannot guess how user built his image
746 // (and therefore cannot be clever about some Dicom fields)
747 // It's up to the user to tell gdcm what he did.
748 // -1) user created ex nihilo his own image and wants to write it
751 // -2) user modified the pixels of an existing image.
753 // -3) user created a new image, using existing a set of images
754 // (eg MIP, MPR, cartography image)
756 // -4) user modified/added some tags *without processing* the pixels
758 // UNMODIFIED_PIXELS_IMAGE
759 // -Probabely some more to be added
760 //(see gdcmFileHelper.h for more explanations)
762 // User is allowed to use the following methods:
764 void vtkGdcmWriter::SetContentTypeToUserOwnImage()
765 void vtkGdcmWriter::SetContentTypeToFilteredImage()
766 void vtkGdcmWriter::SetContentTypeToUserCreatedImage()
767 vtkGdcmWriter::void SetContentTypeToUnmodifiedPixelsImage()
769 // depending on what he did before!
775 /// \todo : write it!
780 /// \todo : write it!
782 2-4) Retrictions for Python users
783 ---------------------------------
784 /// \todo : write it!
786 3) Some 'Command line' utilities /// \todo: finish it!
787 ================================
791 3-) exXCoherentFileSet
794 3-) AnonymizeMultiPatient
795 3-) AnonymizeDicomDir
799 3-) exMoveImagesToSingleSerieUID
802 3-) vtkgdcmSerieViewer2