+ {
+ // we assume that *all* kinds of YBR are dealt with
+ return 3;
+ }
+}
+
+/**
+ * \brief This function is intended to user that DOESN'T want
+ * to get RGB pixels image when it's stored as a PALETTE COLOR image
+ * - the (vtk) user is supposed to know how deal with LUTs -
+ * \warning to be used with GetImagePixelsRaw()
+ * @return 1 if Gray level, 3 if Color (RGB or YBR - NOT 'PALETTE COLOR' -)
+ */
+int File::GetNumberOfScalarComponentsRaw()
+{
+ // 0028 0100 US IMG Bits Allocated
+ // (in order no to be messed up by old RGB images)
+ if ( File::GetEntryValue(0x0028,0x0100) == "24" )
+ {
+ return 3;
+ }
+
+ // we assume that *all* kinds of YBR are dealt with
+ return GetSamplesPerPixel();
+}
+
+/**
+ * \brief Recover the offset (from the beginning of the file)
+ * of *image* pixels (not *icone image* pixels, if any !)
+ * @return Pixel Offset
+ */
+size_t File::GetPixelOffset()
+{
+ DocEntry *pxlElement = GetDocEntry(GrPixel, NumPixel);
+ if ( pxlElement )
+ {
+ return pxlElement->GetOffset();
+ }
+ else
+ {
+ gdcmDebugMacro( "Big trouble : Pixel Element ("
+ << std::hex << GrPixel<<","<< NumPixel<< ") NOT found" );
+ return 0;
+ }
+}
+
+/**
+ * \brief Recover the pixel area length (in Bytes)
+ * @return Pixel Element Length, as stored in the header
+ * (NOT the memory space necessary to hold the Pixels
+ * -in case of embeded compressed image-)
+ * 0 : NOT USABLE file. The caller has to check.
+ */
+size_t File::GetPixelAreaLength()
+{
+ DocEntry *pxlElement = GetDocEntry(GrPixel, NumPixel);
+ if ( pxlElement )
+ {
+ return pxlElement->GetLength();
+ }
+ else
+ {
+ gdcmDebugMacro( "Big trouble : Pixel Element ("
+ << std::hex << GrPixel<<","<< NumPixel<< ") NOT found" );
+ return 0;
+ }
+}
+
+/**
+ * \brief Adds the characteristics of a new element we want to anonymize
+ * @param group Group number of the target tag.
+ * @param elem Element number of the target tag.
+ * @param value new value (string) to substitute with
+ */
+void File::AddAnonymizeElement (uint16_t group, uint16_t elem,
+ std::string const &value)
+{
+ Element el;
+ el.Group = group;
+ el.Elem = elem;
+ el.Value = value;
+ UserAnonymizeList.push_back(el);
+}
+
+/**
+ * \brief Overwrites in the file the values of the DicomElements
+ * held in the list
+ */
+void File::AnonymizeNoLoad()
+{
+ std::fstream *fp = new std::fstream(Filename.c_str(),
+ std::ios::in | std::ios::out | std::ios::binary);
+ gdcm::DocEntry *d;
+ uint32_t offset;
+ uint32_t lgth;
+ uint32_t valLgth = 0;
+ std::string *spaces;
+ for (ListElements::iterator it = UserAnonymizeList.begin();
+ it != UserAnonymizeList.end();
+ ++it)
+ {
+ d = GetDocEntry( (*it).Group, (*it).Elem);
+
+ if ( d == NULL)
+ continue;
+
+ if ( dynamic_cast<SeqEntry *>(d) )
+ {
+ gdcmWarningMacro( "You cannot 'Anonymize' a SeqEntry ");
+ continue;
+ }
+
+ offset = d->GetOffset();
+ lgth = d->GetLength();
+ if (valLgth < lgth)
+ {
+ spaces = new std::string( lgth-valLgth, ' ');
+ (*it).Value = (*it).Value + *spaces;
+ delete spaces;
+ }
+ fp->seekp( offset, std::ios::beg );
+ fp->write( (*it).Value.c_str(), lgth );
+
+ }
+ fp->close();
+ delete fp;
+}
+
+/**
+ * \brief anonymize a File (remove Patient's personal info passed with
+ * AddAnonymizeElement()
+ * \note You cannot Anonymize a BinEntry (to be fixed)
+ */
+bool File::AnonymizeFile()
+{
+ // If Anonymisation list is empty, let's perform some basic anonymization
+ if ( UserAnonymizeList.begin() == UserAnonymizeList.end() )
+ {
+ // 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 )
+ {
+ SetValEntry(studyInstanceUID, 0x0010, 0x0010);
+ }
+ else
+ {
+ SetValEntry("anonymized", 0x0010, 0x0010);
+ }
+ }
+ }
+ else
+ {
+ gdcm::DocEntry *d;
+ for (ListElements::iterator it = UserAnonymizeList.begin();
+ it != UserAnonymizeList.end();
+ ++it)
+ {
+ d = GetDocEntry( (*it).Group, (*it).Elem);
+
+ if ( d == NULL)
+ continue;
+
+ if ( dynamic_cast<SeqEntry *>(d) )
+ {
+ gdcmWarningMacro( "You cannot 'Anonymize' a SeqEntry ");
+ continue;
+ }
+
+ if ( dynamic_cast<BinEntry *>(d) )
+ {
+ gdcmWarningMacro( "To 'Anonymize' a BinEntry, better use AnonymizeNoLoad (FIXME) ");
+ continue;
+ }
+ else
+ SetValEntry ((*it).Value, (*it).Group, (*it).Elem);
+ }
+}
+
+ // In order to make definitively impossible any further identification
+ // 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;
+}
+
+/**
+ * \brief Performs some consistency checking on various 'File related'
+ * (as opposed to 'DicomDir related') entries
+ * then writes in a file all the (Dicom Elements) included the Pixels
+ * @param fileName file name to write to
+ * @param writetype type of the file to be written
+ * (ACR, ExplicitVR, ImplicitVR)
+ */
+bool File::Write(std::string fileName, FileType writetype)
+{
+ std::ofstream *fp = new std::ofstream(fileName.c_str(),
+ std::ios::out | std::ios::binary);
+ if (*fp == NULL)
+ {
+ gdcmWarningMacro("Failed to open (write) File: " << fileName.c_str());
+ return false;
+ }
+
+ // Entry : 0002|0000 = group length -> recalculated
+ ValEntry*e0000 = GetValEntry(0x0002,0x0000);
+ if ( e0000 )
+ {
+ std::ostringstream sLen;
+ sLen << ComputeGroup0002Length(writetype);
+ e0000->SetValue(sLen.str());
+ }
+
+ int i_lgPix = GetEntryLength(GrPixel, NumPixel);
+ if (i_lgPix != -2)
+ {
+ // no (GrPixel, NumPixel) element
+ std::string s_lgPix = Util::Format("%d", i_lgPix+12);
+ s_lgPix = Util::DicomString( s_lgPix.c_str() );
+ InsertValEntry(s_lgPix,GrPixel, 0x0000);
+ }
+
+ Document::WriteContent(fp, writetype);
+
+ fp->close();
+ delete fp;
+
+ return true;