+ {
+ gdcmWarningMacro( "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
+ {
+ gdcmWarningMacro( "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)
+{
+ DicomElement 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 DataEntry (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
+ SetEntryString(" ",0x0010, 0x2154); // Telephone
+ SetEntryString(" ",0x0010, 0x1040); // Adress
+ SetEntryString(" ",0x0010, 0x0020); // Patient ID
+
+ DocEntry *patientNameHE = GetDocEntry (0x0010, 0x0010);
+
+ if ( patientNameHE ) // we replace it by Study Instance UID (why not ?)
+ {
+ std::string studyInstanceUID = GetEntryString (0x0020, 0x000d);
+ if ( studyInstanceUID != GDCM_UNFOUND )
+ {
+ SetEntryString(studyInstanceUID, 0x0010, 0x0010);
+ }
+ else
+ {
+ SetEntryString("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<DataEntry *>(d) )
+ {
+ gdcmWarningMacro( "To 'Anonymize' a DataEntry, better use AnonymizeNoLoad (FIXME) ");
+ continue;
+ }
+ else
+ SetEntryString ((*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
+ DataEntry *e0000 = GetDataEntry(0x0002,0x0000);
+ if ( e0000 )
+ {
+ std::ostringstream sLen;
+ sLen << ComputeGroup0002Length( );
+ e0000->SetString(sLen.str());
+ }
+
+ // FIXME : Derma?.dcm does not have it...let's remove it ?!? JPRx
+ if( writetype != JPEG )
+ {
+ 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() );
+ InsertEntryString(s_lgPix,GrPixel, 0x0000);
+ }
+ }
+ Document::WriteContent(fp, writetype);
+
+ fp->close();
+ delete fp;
+
+ return true;