gdcmByteValue.h

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program: GDCM (Grassroots DICOM). A DICOM library
00004   Module:  $URL$
00005 
00006   Copyright (c) 2006-2009 Mathieu Malaterre
00007   All rights reserved.
00008   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
00009 
00010      This software is distributed WITHOUT ANY WARRANTY; without even
00011      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00012      PURPOSE.  See the above copyright notice for more information.
00013 
00014 =========================================================================*/
00015 #ifndef __gdcmByteValue_h
00016 #define __gdcmByteValue_h
00017 
00018 #include "gdcmValue.h"
00019 #include "gdcmTrace.h"
00020 #include "gdcmVL.h"
00021 
00022 #include <vector>
00023 #include <iterator>
00024 #include <iomanip>
00025 
00026 //#include <stdlib.h> // abort
00027 
00028 namespace gdcm
00029 {
00034 class GDCM_EXPORT ByteValue : public Value
00035 {
00036 public:
00037   ByteValue(const char* array = 0, VL const &vl = 0):
00038     Internal(array, array+vl),Length(vl) {
00039       if( vl.IsOdd() )
00040         {
00041         gdcmDebugMacro( "Odd length" );
00042         Internal.resize(vl+1);
00043         Length++;
00044         }
00045   }
00046   ByteValue(std::vector<char> &v):Internal(v),Length(v.size()) {}
00047   //ByteValue(std::ostringstream const &os) {
00048   //  (void)os;
00049   //   assert(0); // TODO
00050   //}
00051   ~ByteValue() {
00052     Internal.clear();
00053   }
00054 
00055   // When 'dumping' dicom file we still have some information from
00056   // Either the VR: eg LO (private tag)
00057   void PrintASCII(std::ostream &os, VL maxlength ) const;
00058 
00059   void PrintHex(std::ostream &os, VL maxlength) const;
00060 
00061   // Either from Element Number (== 0x0000)
00062   void PrintGroupLength(std::ostream &os) {
00063     assert( Length == 2 );
00064     (void)os;
00065   }
00066 
00067   bool IsEmpty() const {
00068     if( Internal.empty() ) assert( Length == 0 ); 
00069     return Internal.empty(); 
00070   }
00071   VL GetLength() const { return Length; }
00072   // Does a reallocation
00073   void SetLength(VL vl) {
00074     VL l(vl);
00075 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
00076     // CompressedLossy.dcm
00077     if( l.IsUndefined() ) throw Exception( "Impossible" );
00078     if ( l.IsOdd() ) {
00079       gdcmDebugMacro(
00080         "BUGGY HEADER: Your dicom contain odd length value field." );
00081       ++l;
00082       }
00083 #else
00084     assert( !l.IsUndefined() && !l.IsOdd() );
00085 #endif
00086     // I cannot use reserve for now. I need to implement:
00087     // STL - vector<> and istream
00088     // http://groups.google.com/group/comp.lang.c++/msg/37ec052ed8283e74
00089 //#define SHORT_READ_HACK
00090     try
00091       {
00092 #ifdef SHORT_READ_HACK
00093     if( l <= 0xff )
00094 #endif
00095       Internal.resize(l);
00096       //Internal.reserve(l);
00097       }
00098     catch(...)
00099       {
00100       //throw Exception("Impossible to allocate: " << l << " bytes." );
00101       throw Exception("Impossible to allocate" );
00102       }
00103     // Keep the exact length
00104     Length = vl;
00105   }
00106 
00107   operator const std::vector<char>& () const { return Internal; }
00108 
00109   ByteValue &operator=(const ByteValue &val) {
00110     Internal = val.Internal;
00111     Length = val.Length;
00112     return *this;
00113     }
00114 
00115   bool operator==(const ByteValue &val) const {
00116     if( Length != val.Length )
00117       return false;
00118     if( Internal == val.Internal )
00119       return true;
00120     return false;
00121     }
00122 
00123   void Clear() {
00124     Internal.clear();
00125   }
00126   // Use that only if you understand what you are doing
00127   const char *GetPointer() const {
00128     if(!Internal.empty()) return &Internal[0];
00129     return 0;
00130   }
00131   void Fill(char c) {
00132     //if( Internal.empty() ) return;
00133     std::vector<char>::iterator it = Internal.begin();
00134     for(; it != Internal.end(); ++it) *it = c;
00135   }
00136   bool GetBuffer(char *buffer, unsigned long length) const {
00137     // SIEMENS_GBS_III-16-ACR_NEMA_1.acr has a weird pixel length
00138     // so we need an inequality
00139     if( length <= Internal.size() )
00140       {
00141       memcpy(buffer, &Internal[0], length);
00142       return true;
00143       }
00144     gdcmDebugMacro( "Could not handle length= " << length );
00145     return false;
00146     }
00147   bool WriteBuffer(std::ostream &os) const {
00148     if( Length ) {
00149       //assert( Internal.size() <= Length );
00150       assert( !(Internal.size() % 2) );
00151       os.write(&Internal[0], Internal.size() );
00152       }
00153     return true;
00154   }
00155 
00156   template <typename TSwap, typename TType>
00157   std::istream &Read(std::istream &is) {
00158     // If Length is odd we have detected that in SetLength
00159     // and calling std::vector::resize make sure to allocate *AND* 
00160     // initialize values to 0 so we are sure to have a \0 at the end
00161     // even in this case
00162     if(Length)
00163       {
00164       is.read(&Internal[0], Length);
00165       assert( Internal.size() == Length || Internal.size() == Length + 1 );
00166       TSwap::SwapArray((TType*)&Internal[0], Internal.size() / sizeof(TType) );
00167       }
00168     return is;
00169   }
00170 
00171   template <typename TSwap>
00172   std::istream &Read(std::istream &is) {
00173     return Read<TSwap,uint8_t>(is);
00174   }
00175 
00176 
00177   template <typename TSwap, typename TType>
00178   std::ostream const &Write(std::ostream &os) const {
00179     assert( !(Internal.size() % 2) );
00180     if( !Internal.empty() ) {
00181       //os.write(&Internal[0], Internal.size());
00182       std::vector<char> copy = Internal;
00183       TSwap::SwapArray((TType*)&copy[0], Internal.size() / sizeof(TType) );
00184       os.write(&copy[0], copy.size());
00185       }
00186     return os;
00187   }
00188 
00189   template <typename TSwap>
00190   std::ostream const &Write(std::ostream &os) const {
00191     return Write<TSwap,uint8_t>(os);
00192   }
00193 
00200   bool IsPrintable(VL length) const {
00201     assert( length <= Length );
00202     for(unsigned int i=0; i<length; i++)
00203       {
00204       if ( i == (length-1) && Internal[i] == '\0') continue;
00205       if ( !( isprint((unsigned char)Internal[i]) || isspace((unsigned char)Internal[i]) ) )
00206         {
00207         //gdcmWarningMacro( "Cannot print :" << i );
00208         return false;
00209         }
00210       }
00211     return true;
00212     }
00213 
00214 protected:
00215   void Print(std::ostream &os) const {
00216   // This is perfectly valid to have a Length = 0 , so we cannot check
00217   // the length for printing
00218   if( !Internal.empty() )
00219     {
00220     if( IsPrintable(Length) )
00221       {
00222       // WARNING: Internal.end() != Internal.begin()+Length
00223       std::vector<char>::size_type length = Length;
00224       if( Internal.back() == 0 ) --length;
00225       std::copy(Internal.begin(), Internal.begin()+length,
00226         std::ostream_iterator<char>(os));
00227       }
00228     else
00229       os << "Loaded:" << Internal.size();
00230     }
00231   else
00232     {
00233     //os << "Not Loaded";
00234     os << "(no value available)";
00235     }
00236   }
00237 
00238 
00239 private:
00240   std::vector<char> Internal;
00241 
00242   // WARNING Length IS NOT Internal.size() some *featured* DICOM
00243   // implementation define odd length, we always load them as even number
00244   // of byte, so we need to keep the right Length
00245   VL Length;
00246 };
00247 
00248 } // end namespace gdcm
00249 
00250 #endif //__gdcmByteValue_h
00251 

Generated on Tue Mar 9 22:40:39 2010 for GDCM by doxygen 1.6.3
SourceForge.net Logo