+ // 'Imager Pixel Spacing' : defaulted to 'Pixel Spacing'
+ // --> This one is the *legal* one !
+ // FIXME : we should write it only when we are *sure* the image comes from
+ // an imager (see also 0008,0x0064)
+ CheckMandatoryEntry(0x0018,0x1164,pixelSpacing);
+
+ // Samples Per Pixel (type 1) : default to grayscale
+ CheckMandatoryEntry(0x0028,0x0002,"1");
+
+ // --- Check UID-related Entries ---
+
+ // If 'SOP Class UID' exists ('true DICOM' image)
+ // we create the 'Source Image Sequence' SeqEntry
+ // to hold informations about the Source Image
+
+ DataEntry *e_0008_0016 = FileInternal->GetDataEntry(0x0008, 0x0016);
+ if ( e_0008_0016 )
+ {
+ // Create 'Source Image Sequence' SeqEntry
+ SeqEntry *sis = SeqEntry::New (
+ Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x2112) );
+ SQItem *sqi = SQItem::New(1);
+ // (we assume 'SOP Instance UID' exists too)
+ // create 'Referenced SOP Class UID'
+ DataEntry *e_0008_1150 = DataEntry::New(
+ Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1150) );
+ e_0008_1150->SetString( e_0008_0016->GetString());
+ sqi->AddEntry(e_0008_1150);
+ e_0008_1150->Delete();
+
+ // create 'Referenced SOP Instance UID'
+ DataEntry *e_0008_0018 = FileInternal->GetDataEntry(0x0008, 0x0018);
+ DataEntry *e_0008_1155 = DataEntry::New(
+ Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1155) );
+ e_0008_1155->SetString( e_0008_0018->GetString());
+ sqi->AddEntry(e_0008_1155);
+ e_0008_1155->Delete();
+
+ sis->AddSQItem(sqi,1);
+ sqi->Delete();
+
+ // temporarily replaces any previous 'Source Image Sequence'
+ Archive->Push(sis);
+ sis->Delete();
+
+ // FIXME : is 'Image Type' *really* depending on the presence of'SOP Class UID'?
+ if ( KeepMediaStorageSOPClassUID)
+ // It up to the use to *know* whether he modified the pixels or not.
+ // he is allowed to keep the original 'Media Storage SOP Class UID'
+ // and 'Image Type' as well
+ CheckMandatoryEntry(0x0008,0x0008,"DERIVED\\PRIMARY");
+ else
+ // Potentialy this is a post-processed image
+ // (The written image is no longer an 'ORIGINAL' one)
+ CopyMandatoryEntry(0x0008,0x0008,"DERIVED\\PRIMARY");
+
+ }
+
+ // At the end, not to overwrite the original ones,
+ // needed by 'Referenced SOP Instance UID', 'Referenced SOP Class UID'
+ // 'SOP Instance UID'
+ CopyMandatoryEntry(0x0008,0x0018,sop);
+
+ // the gdcm written image is a [Secondary Capture Image Storage]
+ // except if user told us he dind't modify the pixels, and, therefore
+ // he want to keep the 'Media Storage SOP Class UID'
+
+ // 'Media Storage SOP Class UID' : [Secondary Capture Image Storage]
+ if ( KeepMediaStorageSOPClassUID)
+ {
+ // It up to the use to *know* whether he modified the pixels or not.
+ // he is allowed to keep the original 'Media Storage SOP Class UID'
+ CheckMandatoryEntry(0x0008,0x0016,"1.2.840.10008.5.1.4.1.1.7");
+ }
+ else
+ {
+ // Potentialy this is a post-processed image
+ // 'Media Storage SOP Class UID' --> [Secondary Capture Image Storage]
+ CopyMandatoryEntry(0x0008,0x0016,"1.2.840.10008.5.1.4.1.1.7");
+
+ // FIXME : Must we Force Value, or Default value ?
+ // Is it Type 1 for any Modality ?
+ // --> Answer seems to be NO :-(
+ // FIXME : we should write it only when we are *sure* the image
+ // *does not* come from an imager (see also 0018,0x1164)
+
+ // Conversion Type.
+ // Other possible values are :
+ // See PS 3.3, Page 408
+
+ // DV = Digitized Video
+ // DI = Digital Interface
+ // DF = Digitized Film
+ // WSD = Workstation
+ // SD = Scanned Document
+ // SI = Scanned Image
+ // DRW = Drawing
+ // SYN = Synthetic Image
+
+ CheckMandatoryEntry(0x0008,0x0064,"SYN");
+ }
+
+ // ---- The user will never have to take any action on the following ----
+
+ // new value for 'SOP Instance UID'
+ //SetMandatoryEntry(0x0008,0x0018,Util::CreateUniqueUID());
+
+ // Instance Creation Date
+ const std::string &date = Util::GetCurrentDate();
+ CopyMandatoryEntry(0x0008,0x0012,date);
+
+ // Instance Creation Time
+ const std::string &time = Util::GetCurrentTime();
+ CopyMandatoryEntry(0x0008,0x0013,time);
+
+ // Study Date
+ CopyMandatoryEntry(0x0008,0x0020,date);
+ // Study Time
+ CopyMandatoryEntry(0x0008,0x0030,time);
+
+ // Accession Number
+ //CopyMandatoryEntry(0x0008,0x0050,"");
+ CheckMandatoryEntry(0x0008,0x0050,"");
+
+
+ // ----- Add Mandatory Entries if missing ---
+ // Entries whose type is 1 are mandatory, with a mandatory value
+ // Entries whose type is 1c are mandatory-inside-a-Sequence,
+ // with a mandatory value
+ // Entries whose type is 2 are mandatory, with an optional value
+ // Entries whose type is 2c are mandatory-inside-a-Sequence,
+ // with an optional value
+ // Entries whose type is 3 are optional
+
+ // 'Study Instance UID'
+ // Keep the value if exists
+ // The user is allowed to create his own Study,
+ // keeping the same 'Study Instance UID' for various images
+ // The user may add images to a 'Manufacturer Study',
+ // adding new Series to an already existing Study
+ CheckMandatoryEntry(0x0020,0x000d,Util::CreateUniqueUID());
+
+ // 'Serie Instance UID'
+ // Keep the value if exists
+ // The user is allowed to create his own Series,
+ // keeping the same 'Serie Instance UID' for various images
+ // The user shouldn't add any image to a 'Manufacturer Serie'
+ // but there is no way no to prevent him for doing that
+ CheckMandatoryEntry(0x0020,0x000e,Util::CreateUniqueUID());
+
+ // Study ID
+ CheckMandatoryEntry(0x0020,0x0010,"");
+
+ // Series Number
+ CheckMandatoryEntry(0x0020,0x0011,"");
+
+ // Instance Number
+ CheckMandatoryEntry(0x0020,0x0013,"");
+
+ // Patient Orientation
+ // Can be computed from (0020|0037) : Image Orientation (Patient)
+ gdcm::Orientation *o = gdcm::Orientation::New();
+ std::string ori = o->GetOrientation ( FileInternal );
+ o->Delete();
+ if (ori != "\\" )
+ CheckMandatoryEntry(0x0020,0x0020,ori);
+ else
+ CheckMandatoryEntry(0x0020,0x0020,"");
+
+ // Modality : if missing we set it to 'OTher'
+ CheckMandatoryEntry(0x0008,0x0060,"OT");
+
+ // Manufacturer : if missing we set it to 'GDCM Factory'
+ CheckMandatoryEntry(0x0008,0x0070,"GDCM Factory");
+
+ // Institution Name : if missing we set it to 'GDCM Hospital'
+ CheckMandatoryEntry(0x0008,0x0080,"GDCM Hospital");
+
+ // Patient's Name : if missing, we set it to 'GDCM^Patient'
+ CheckMandatoryEntry(0x0010,0x0010,"GDCM^Patient");
+
+ // Patient ID
+ CheckMandatoryEntry(0x0010,0x0020,"");
+
+ // Patient's Birth Date : 'type 2' entry -> must exist, value not mandatory
+ CheckMandatoryEntry(0x0010,0x0030,"");
+
+ // Patient's Sex :'type 2' entry -> must exist, value not mandatory
+ CheckMandatoryEntry(0x0010,0x0040,"");
+
+ // Referring Physician's Name :'type 2' entry -> must exist, value not mandatory
+ CheckMandatoryEntry(0x0008,0x0090,"");
+
+ // Remove some inconstencies (probably some more will be added)
+
+ // if (0028 0008)Number of Frames exists
+ // Push out (0020 0052),Frame of Reference UID
+ // (only meaningfull within a Serie)
+ DataEntry *e_0028_0008 = FileInternal->GetDataEntry(0x0028, 0x0008);
+ if ( !e_0028_0008 )
+ {
+ Archive->Push(0x0020, 0x0052);
+ }