1 /*=========================================================================
4 Module: $RCSfile: gdcmDataEntry.cxx,v $
6 Date: $Date: 2005/10/18 10:19:27 $
7 Version: $Revision: 1.2 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "gdcmDataEntry.h"
22 #include "gdcmGlobal.h"
24 #include "gdcmDebug.h"
30 //-----------------------------------------------------------------------------
31 #define MAX_SIZE_PRINT_ELEMENT_VALUE 0x7fffffff
32 uint32_t DataEntry::MaxSizePrintEntry = MAX_SIZE_PRINT_ELEMENT_VALUE;
34 //-----------------------------------------------------------------------------
35 // Constructor / Destructor
37 * \brief Constructor for a given DictEntry
38 * @param e Pointer to existing dictionary entry
40 DataEntry::DataEntry(DictEntry *e)
51 * \brief Constructor for a given DocEntry
52 * @param e Pointer to existing Doc entry
54 DataEntry::DataEntry(DocEntry *e)
55 : DocEntry(e->GetDictEntry())
65 * \brief Canonical destructor.
67 DataEntry::~DataEntry ()
72 //-----------------------------------------------------------------------------
75 //-----------------------------------------------------------------------------
78 * \brief Sets the value (non string) of the current Dicom Header Entry
80 void DataEntry::SetBinArea( uint8_t *area, bool self )
90 void DataEntry::CopyBinArea( uint8_t *area, uint32_t length )
94 uint32_t lgh = length + length%2;
97 if( area && length > 0 )
100 memcpy(BinArea,area,length);
104 State = STATE_LOADED;
108 void DataEntry::SetValue(const uint32_t &id,const double &val)
112 State = STATE_LOADED;
114 if( id > GetValueCount() )
116 gdcmErrorMacro("Index (" << id << ")is greater than the data size");
120 const VRKey &vr = GetVR();
121 if( vr == "US" || vr == "SS" )
123 uint16_t *data = (uint16_t *)BinArea;
124 data[id] = (uint16_t)val;
126 else if( vr == "UL" || vr == "SL" )
128 uint32_t *data = (uint32_t *)BinArea;
129 data[id] = (uint32_t)val;
131 else if( vr == "FL" )
133 float *data = (float *)BinArea;
134 data[id] = (float)val;
136 else if( vr == "FD" )
138 double *data = (double *)BinArea;
139 data[id] = (double)val;
141 else if( Global::GetVR()->IsVROfStringRepresentable(vr) )
143 gdcmErrorMacro("SetValue on String representable not implemented yet");
147 BinArea[id] = (uint8_t)val;
151 double DataEntry::GetValue(const uint32_t &id) const
155 gdcmErrorMacro("BinArea not set. Can't get the value");
159 uint32_t count = GetValueCount();
162 gdcmErrorMacro("Index (" << id << ")is greater than the data size");
166 const VRKey &vr = GetVR();
167 if( vr == "US" || vr == "SS" )
168 return ((uint16_t *)BinArea)[id];
169 else if( vr == "UL" || vr == "SL" )
170 return ((uint32_t *)BinArea)[id];
171 else if( vr == "FL" )
172 return ((float *)BinArea)[id];
173 else if( vr == "FD" )
174 return ((double *)BinArea)[id];
175 else if( Global::GetVR()->IsVROfStringRepresentable(vr) )
179 // Don't use std::string to accelerate processing
181 char *tmp = new char[GetLength()+1];
182 memcpy(tmp,BinArea,GetLength());
193 for(uint32_t i=0;i<GetLength();i++)
222 uint32_t DataEntry::GetValueCount(void) const
224 const VRKey &vr = GetVR();
225 if( vr == "US" || vr == "SS" )
226 return GetLength()/sizeof(uint16_t);
227 else if( vr == "UL" || vr == "SL" )
228 return GetLength()/sizeof(uint32_t);
229 else if( vr == "FL" )
230 return GetLength()/sizeof(float);
231 else if( vr == "FD" )
232 return GetLength()/sizeof(double);
233 else if( Global::GetVR()->IsVROfStringRepresentable(vr) )
235 // Don't use std::string to accelerate processing
237 for(uint32_t i=0;i<GetLength();i++)
239 if( BinArea[i] == '\\')
248 void DataEntry::SetString(std::string const &value)
252 const VRKey &vr = GetVR();
253 if ( vr == "US" || vr == "SS" )
255 std::vector<std::string> tokens;
256 Util::Tokenize (value, tokens, "\\");
257 SetLength(tokens.size()*sizeof(uint16_t));
260 uint16_t *data = (uint16_t *)BinArea;
261 for (unsigned int i=0; i<tokens.size();i++)
262 data[i] = atoi(tokens[i].c_str());
265 else if ( vr == "UL" || vr == "SL" )
267 std::vector<std::string> tokens;
268 Util::Tokenize (value, tokens, "\\");
269 SetLength(tokens.size()*sizeof(uint32_t));
272 uint32_t *data = (uint32_t *)BinArea;
273 for (unsigned int i=0; i<tokens.size();i++)
274 data[i] = atoi(tokens[i].c_str());
277 else if ( vr == "FL" )
279 std::vector<std::string> tokens;
280 Util::Tokenize (value, tokens, "\\");
281 SetLength(tokens.size()*sizeof(float));
284 float *data = (float *)BinArea;
285 for (unsigned int i=0; i<tokens.size();i++)
286 data[i] = (float)atof(tokens[i].c_str());
289 else if ( vr == "FD" )
291 std::vector<std::string> tokens;
292 Util::Tokenize (value, tokens, "\\");
293 SetLength(tokens.size()*sizeof(double));
296 double *data = (double *)BinArea;
297 for (unsigned int i=0; i<tokens.size();i++)
298 data[i] = atof(tokens[i].c_str());
303 if( value.size() > 0 )
305 std::string finalVal = Util::DicomString( value.c_str() );
306 SetLength(finalVal.size());
309 memcpy(BinArea, &(finalVal[0]), finalVal.size());
312 State = STATE_LOADED;
315 std::string const &DataEntry::GetString() const
317 static std::ostringstream s;
318 const VRKey &vr = GetVR();
326 if( vr == "US" || vr == "SS" )
328 uint16_t *data=(uint16_t *)BinArea;
330 for (int i=0; i < GetValueCount(); i++)
338 // See above comment on multiple integers (mutatis mutandis).
339 else if( vr == "UL" || vr == "SL" )
341 uint32_t *data=(uint32_t *)BinArea;
343 for (int i=0; i < GetValueCount(); i++)
351 else if( vr == "FL" )
353 float *data=(float *)BinArea;
355 for (int i=0; i < GetValueCount(); i++)
363 else if( vr == "FD" )
365 double *data=(double *)BinArea;
367 for (int i=0; i < GetValueCount(); i++)
376 StrArea.append((const char *)BinArea,GetLength());
381 void DataEntry::Copy(DocEntry *doc)
385 DataEntry *entry = dynamic_cast<DataEntry *>(doc);
388 State = entry->State;
390 CopyBinArea(entry->BinArea,entry->GetLength());
394 void DataEntry::WriteContent(std::ofstream *fp, FileType filetype)
396 DocEntry::WriteContent(fp, filetype);
398 if ( GetGroup() == 0xfffe )
400 return; //delimitors have NO value
403 uint8_t *binArea8 = BinArea; //safe notation
404 size_t lgr = GetLength();
405 if (BinArea) // the binArea was *actually* loaded
408 // The same operation should be done if we wanted
409 // to write image with Big Endian Transfer Syntax,
410 // while working on Little Endian Processor
411 // --> forget Big Endian Transfer Syntax writting!
412 // Next DICOM version will give it up ...
415 // The stuff looks nice, but it's probably bugged,
416 // since troubles occur on big endian processors (SunSparc, Motorola)
417 // while reading the pixels of a
418 // gdcm-written Little-Endian 16 bits per pixel image
420 #if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)
422 /// \todo FIXME : Right now, we only care of Pixels element
423 /// we should deal with *all* the BinEntries
424 /// Well, not really since we are not interpreting values read...
426 // 8 Bits Pixels *are* OB, 16 Bits Pixels *are* OW
427 // -value forced while Reading process-
430 // --> the following lines *looked* very clever,
431 // --> but they don't work on big endian processors.
432 // --> since I've no access for the moment to a big endian proc :-(
433 // --> I comment them out, to see the result on the dash board
436 // --> Revert to initial code : TestWriteSimple hangs on Darwin :-(
437 if (GetGroup() == 0x7fe0 && GetVR() == "OW")
439 uint16_t *binArea16 = (uint16_t*)binArea8;
440 binary_write (*fp, binArea16, lgr );
444 // For any other VR, DataEntry is re-written as-is
445 binary_write (*fp, binArea8, lgr );
449 // --> remove the following line, an uncomment the previous ones,
450 // --> if it doesn't work better
452 /*binary_write ( *fp, binArea8, lgr ); // Elem value*/
455 binary_write ( *fp, binArea8, lgr ); // Elem value
456 #endif //GDCM_WORDS_BIGENDIAN
460 // nothing was loaded, but we need to skip space on disc
462 // --> WARNING : nothing is written;
463 // --> the initial data (on the the source image) is lost
464 // --> user is *not* informed !
466 fp->seekp(lgr, std::ios::cur);
470 //-----------------------------------------------------------------------------
472 void DataEntry::NewBinArea(void)
475 if( GetLength() > 0 )
476 BinArea = new uint8_t[GetLength()];
480 void DataEntry::DeleteBinArea(void)
482 if (BinArea && SelfArea)
489 //-----------------------------------------------------------------------------
492 //-----------------------------------------------------------------------------
495 * \brief Prints a DataEntry (Dicom entry)
496 * @param os ostream we want to print in
497 * @param indent Indentation string to be prepended during printing
499 void DataEntry::Print(std::ostream &os, std::string const & )
504 std::ostringstream s;
510 const VRKey &vr = GetVR();
512 if( vr == "US" || vr == "SS" )
513 s << " [" << GetString() << "]";
514 else if( vr == "UL" || vr == "SL" )
515 s << " [" << GetString() << "]";
516 else if ( vr == "FL" )
517 s << " [" << GetString() << "]";
518 else if ( vr == "FD" )
519 s << " [" << GetString() << "]";
522 if(Global::GetVR()->IsVROfStringRepresentable(vr))
524 std::string cleanString = Util::CreateCleanString(v); // replace non printable characters by '.'
525 if ( cleanString.length() <= GetMaxSizePrintEntry()
529 s << " [" << cleanString << "]";
533 s << " [gdcm::too long for print (" << cleanString.length() << ") ]";
538 if ( Util::IsCleanArea( GetBinArea(),GetLength() ) )
540 std::string cleanString =
541 Util::CreateCleanString( BinArea,GetLength() );
542 s << " [" << cleanString << "]";
546 s << " [" << GDCM_BINLOADED << ";"
547 << "length = " << GetLength() << "]";
555 s << " [" << GDCM_NOTLOADED << "]";
556 else if( IsUnfound() )
557 s << " [" << GDCM_UNFOUND << "]";
558 else if( IsUnread() )
559 s << " [" << GDCM_UNREAD << "]";
560 else if ( GetLength() == 0 )
565 s << " (" << GDCM_PIXELDATA << ")";
567 // Display the UID value (instead of displaying only the rough code)
568 // First 'clean' trailing character (space or zero)
571 const uint16_t &gr = GetGroup();
572 const uint16_t &elt = GetElement();
573 TS *ts = Global::GetTS();
577 // Any more to be displayed ?
578 if ( elt == 0x0010 || elt == 0x0002 )
580 if ( v.length() != 0 ) // for brain damaged headers
582 if ( ! isdigit((unsigned char)v[v.length()-1]) )
584 v.erase(v.length()-1, 1);
587 s << " ==>\t[" << ts->GetValue(v) << "]";
590 else if (gr == 0x0008)
592 if ( elt == 0x0016 || elt == 0x1150 )
594 if ( v.length() != 0 ) // for brain damaged headers
596 if ( ! isdigit((unsigned char)v[v.length()-1]) )
598 v.erase(v.length()-1, 1);
601 s << " ==>\t[" << ts->GetValue(v) << "]";
604 else if (gr == 0x0004)
606 if ( elt == 0x1510 || elt == 0x1512 )
608 if ( v.length() != 0 ) // for brain damaged headers
610 if ( ! isdigit((unsigned char)v[v.length()-1]) )
612 v.erase(v.length()-1, 1);
615 s << " ==>\t[" << ts->GetValue(v) << "]";
623 //-----------------------------------------------------------------------------
624 } // end namespace gdcm