+/**
+ * \brief gets the info from 0028,1101 : Lookup Table Desc-Red
+ * else 0
+ * @return Lookup Table number of Bits , 0 by default
+ * when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+ * @ return bit number of each LUT item
+ */
+int File::GetLUTNbits()
+{
+ std::vector<std::string> tokens;
+ int lutNbits;
+
+ //Just hope Lookup Table Desc-Red = Lookup Table Desc-Red
+ // = Lookup Table Desc-Blue
+ // Consistency already checked in GetLUTLength
+ std::string lutDescription = GetEntryValue(0x0028,0x1101);
+ if ( lutDescription == GDCM_UNFOUND )
+ {
+ return 0;
+ }
+
+ tokens.clear(); // clean any previous value
+ Util::Tokenize ( lutDescription, tokens, "\\" );
+ //LutLength=atoi(tokens[0].c_str());
+ //LutDepth=atoi(tokens[1].c_str());
+
+ lutNbits = atoi( tokens[2].c_str() );
+ tokens.clear();
+
+ return lutNbits;
+}
+
+/**
+ * \brief gets the info from 0020,0037 : Image Orientation Patient
+ * (needed to organize DICOM files based on their x,y,z position)
+ * @param iop adress of the (6)float aray to receive values
+ * @return cosines of image orientation patient
+ */
+void File::GetImageOrientationPatient( float iop[6] )
+{
+ std::string strImOriPat;
+ //iop is supposed to be float[6]
+ iop[0] = iop[1] = iop[2] = iop[3] = iop[4] = iop[5] = 0.;
+
+ // 0020 0037 DS REL Image Orientation (Patient)
+ if ( (strImOriPat = GetEntryValue(0x0020,0x0037)) != GDCM_UNFOUND )
+ {
+ if( sscanf( strImOriPat.c_str(), "%f\\%f\\%f\\%f\\%f\\%f",
+ &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6 )
+ {
+ gdcmVerboseMacro( "Wrong Image Orientation Patient (0020,0037). Less than 6 values were found." );
+ }
+ }
+ //For ACR-NEMA
+ // 0020 0035 DS REL Image Orientation (RET)
+ else if ( (strImOriPat = GetEntryValue(0x0020,0x0035)) != GDCM_UNFOUND )
+ {
+ if( sscanf( strImOriPat.c_str(), "%f\\%f\\%f\\%f\\%f\\%f",
+ &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6 )
+ {
+ gdcmVerboseMacro( "wrong Image Orientation Patient (0020,0035). Less than 6 values were found." );
+ }
+ }
+}
+
+/**
+ * \brief anonymize a File (removes Patient's personal info)
+ * (read the code to see which ones ...)
+ */
+bool File::AnonymizeFile()
+{
+ // If exist, replace by spaces
+ SetValEntry (" ",0x0010, 0x2154); // Telephone
+ SetValEntry (" ",0x0010, 0x1040); // Adress
+ SetValEntry (" ",0x0010, 0x0020); // Patient ID
+
+ DocEntry* patientNameHE = GetDocEntry (0x0010, 0x0010);
+
+ if ( patientNameHE ) // we replace it by Study Instance UID (why not)
+ {
+ std::string studyInstanceUID = GetEntryValue (0x0020, 0x000d);
+ if ( studyInstanceUID != GDCM_UNFOUND )
+ {
+ InsertValEntry(studyInstanceUID, 0x0010, 0x0010);
+ }
+ else
+ {
+ InsertValEntry("anonymised", 0x0010, 0x0010);
+ }
+ }
+
+ // Just for fun :-(
+ // (if any) remove or replace all the stuff that contains a Date
+
+//0008 0012 DA ID Instance Creation Date
+//0008 0020 DA ID Study Date
+//0008 0021 DA ID Series Date
+//0008 0022 DA ID Acquisition Date
+//0008 0023 DA ID Content Date
+//0008 0024 DA ID Overlay Date
+//0008 0025 DA ID Curve Date
+//0008 002a DT ID Acquisition Datetime
+//0018 9074 DT ACQ Frame Acquisition Datetime
+//0018 9151 DT ACQ Frame Reference Datetime
+//0018 a002 DT ACQ Contribution Date Time
+//0020 3403 SH REL Modified Image Date (RET)
+//0032 0032 DA SDY Study Verified Date
+//0032 0034 DA SDY Study Read Date
+//0032 1000 DA SDY Scheduled Study Start Date
+//0032 1010 DA SDY Scheduled Study Stop Date
+//0032 1040 DA SDY Study Arrival Date
+//0032 1050 DA SDY Study Completion Date
+//0038 001a DA VIS Scheduled Admission Date
+//0038 001c DA VIS Scheduled Discharge Date
+//0038 0020 DA VIS Admitting Date
+//0038 0030 DA VIS Discharge Date
+//0040 0002 DA PRC Scheduled Procedure Step Start Date
+//0040 0004 DA PRC Scheduled Procedure Step End Date
+//0040 0244 DA PRC Performed Procedure Step Start Date
+//0040 0250 DA PRC Performed Procedure Step End Date
+//0040 2004 DA PRC Issue Date of Imaging Service Request
+//0040 4005 DT PRC Scheduled Procedure Step Start Date and Time
+//0040 4011 DT PRC Expected Completion Date and Time
+//0040 a030 DT PRC Verification Date Time
+//0040 a032 DT PRC Observation Date Time
+//0040 a120 DT PRC DateTime
+//0040 a121 DA PRC Date
+//0040 a13a DT PRC Referenced Datetime
+//0070 0082 DA ??? Presentation Creation Date
+//0100 0420 DT ??? SOP Autorization Date and Time
+//0400 0105 DT ??? Digital Signature DateTime
+//2100 0040 DA PJ Creation Date
+//3006 0008 DA SSET Structure Set Date
+//3008 0024 DA ??? Treatment Control Point Date
+//3008 0054 DA ??? First Treatment Date
+//3008 0056 DA ??? Most Recent Treatment Date
+//3008 0162 DA ??? Safe Position Exit Date
+//3008 0166 DA ??? Safe Position Return Date
+//3008 0250 DA ??? Treatment Date
+//300a 0006 DA RT RT Plan Date
+//300a 022c DA RT Air Kerma Rate Reference Date
+//300e 0004 DA RT Review Date
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+/**
+ * \brief Initialize a default DICOM File that should contain all the
+ * field require by other reader. DICOM standard does not
+ * explicitely defines those fields, heuristic has been choosen.
+ * This is not perfect as we are writting a CT image...
+ */
+void File::InitializeDefaultFile()
+{
+ typedef struct
+ {
+ const char *value;
+ uint16_t group;
+ uint16_t elem;
+ } DICOM_DEFAULT_VALUE;
+
+ std::string date = Util::GetCurrentDate();
+ std::string time = Util::GetCurrentTime();
+ std::string uid = Util::CreateUniqueUID();
+ std::string uidMedia = uid;
+ std::string uidInst = uid;
+ std::string uidClass = Util::CreateUniqueUID();
+ std::string uidStudy = Util::CreateUniqueUID();
+ std::string uidSerie = Util::CreateUniqueUID();
+
+ static DICOM_DEFAULT_VALUE defaultvalue[] = {
+ { "146 ", 0x0002, 0x0000}, // Meta Element Group Length // FIXME: how to recompute ?
+ { "1.2.840.10008.5.1.4.1.1.2", 0x0002, 0x0002}, // Media Storage SOP Class UID (CT Image Storage)
+ { uidClass.c_str(), 0x0002, 0x0003}, // Media Storage SOP Instance UID
+ { "1.2.840.10008.1.2.1 ", 0x0002, 0x0010}, // Transfer Syntax UID (Explicit VR Little Endian)
+ { uidClass.c_str(), 0x0002, 0x0012}, // META Implementation Class UID
+ { "GDCM", 0x0002, 0x0016}, // Source Application Entity Title
+
+ { date.c_str(), 0x0008, 0x0012}, // Instance Creation Date
+ { time.c_str(), 0x0008, 0x0013}, // Instance Creation Time
+ { "1.2.840.10008.5.1.4.1.1.2", 0x0008, 0x0016}, // SOP Class UID
+ { uidInst.c_str(), 0x0008, 0x0018}, // SOP Instance UID
+ { "CT", 0x0008, 0x0060}, // Modality
+ { "GDCM", 0x0008, 0x0070}, // Manufacturer
+ { "GDCM", 0x0008, 0x0080}, // Institution Name
+ { "http://www-creatis.insa-lyon.fr/Public/Gdcm", 0x0008, 0x0081}, // Institution Address
+
+ { "GDCM", 0x0010, 0x0010}, // Patient's Name
+ { "GDCMID", 0x0010, 0x0020}, // Patient ID
+
+ { uidStudy.c_str(), 0x0020, 0x000d}, // Study Instance UID
+ { uidSerie.c_str(), 0x0020, 0x000e}, // Series Instance UID
+ { "1", 0x0020, 0x0010}, // StudyID
+ { "1", 0x0020, 0x0011}, // SeriesNumber
+
+ { "1", 0x0028, 0x0002}, // Samples per pixel 1 or 3
+ { "MONOCHROME1", 0x0028, 0x0004}, // photochromatic interpretation
+ { "0", 0x0028, 0x0010}, // nbRows
+ { "0", 0x0028, 0x0011}, // nbCols
+ { "8", 0x0028, 0x0100}, // BitsAllocated 8 or 12 or 16
+ { "8", 0x0028, 0x0101}, // BitsStored <= BitsAllocated
+ { "7", 0x0028, 0x0102}, // HighBit <= BitsAllocated - 1
+ { "0", 0x0028, 0x0103}, // Pixel Representation 0(unsigned) or 1(signed)
+ { 0, 0, 0 }
+ };
+
+ // default value
+ // Special case this is the image (not a string)
+ GrPixel = 0x7fe0;
+ NumPixel = 0x0010;
+ InsertBinEntry(0, 0, GrPixel, NumPixel);
+
+ // All remaining strings:
+ unsigned int i = 0;
+ DICOM_DEFAULT_VALUE current = defaultvalue[i];
+ while( current.value )
+ {
+ InsertValEntry(current.value, current.group, current.elem);
+ current = defaultvalue[++i];
+ }
+}
+