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-2010 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   bool operator==(const Value &val) const
00123     {
00124     const ByteValue &bv = dynamic_cast<const ByteValue&>(val);
00125     return Length == bv.Length && Internal == bv.Internal;
00126     }
00127 
00128 
00129   void Clear() {
00130     Internal.clear();
00131   }
00132   // Use that only if you understand what you are doing
00133   const char *GetPointer() const {
00134     if(!Internal.empty()) return &Internal[0];
00135     return 0;
00136   }
00137   void Fill(char c) {
00138     //if( Internal.empty() ) return;
00139     std::vector<char>::iterator it = Internal.begin();
00140     for(; it != Internal.end(); ++it) *it = c;
00141   }
00142   bool GetBuffer(char *buffer, unsigned long length) const {
00143     // SIEMENS_GBS_III-16-ACR_NEMA_1.acr has a weird pixel length
00144     // so we need an inequality
00145     if( length <= Internal.size() )
00146       {
00147       memcpy(buffer, &Internal[0], length);
00148       return true;
00149       }
00150     gdcmDebugMacro( "Could not handle length= " << length );
00151     return false;
00152     }
00153   bool WriteBuffer(std::ostream &os) const {
00154     if( Length ) {
00155       //assert( Internal.size() <= Length );
00156       assert( !(Internal.size() % 2) );
00157       os.write(&Internal[0], Internal.size() );
00158       }
00159     return true;
00160   }
00161 
00162   template <typename TSwap, typename TType>
00163   std::istream &Read(std::istream &is) {
00164     // If Length is odd we have detected that in SetLength
00165     // and calling std::vector::resize make sure to allocate *AND* 
00166     // initialize values to 0 so we are sure to have a \0 at the end
00167     // even in this case
00168     if(Length)
00169       {
00170       is.read(&Internal[0], Length);
00171       assert( Internal.size() == Length || Internal.size() == Length + 1 );
00172       TSwap::SwapArray((TType*)&Internal[0], Internal.size() / sizeof(TType) );
00173       }
00174     return is;
00175   }
00176 
00177   template <typename TSwap>
00178   std::istream &Read(std::istream &is) {
00179     return Read<TSwap,uint8_t>(is);
00180   }
00181 
00182 
00183   template <typename TSwap, typename TType>
00184   std::ostream const &Write(std::ostream &os) const {
00185     assert( !(Internal.size() % 2) );
00186     if( !Internal.empty() ) {
00187       //os.write(&Internal[0], Internal.size());
00188       std::vector<char> copy = Internal;
00189       TSwap::SwapArray((TType*)&copy[0], Internal.size() / sizeof(TType) );
00190       os.write(&copy[0], copy.size());
00191       }
00192     return os;
00193   }
00194 
00195   template <typename TSwap>
00196   std::ostream const &Write(std::ostream &os) const {
00197     return Write<TSwap,uint8_t>(os);
00198   }
00199 
00206   bool IsPrintable(VL length) const {
00207     assert( length <= Length );
00208     for(unsigned int i=0; i<length; i++)
00209       {
00210       if ( i == (length-1) && Internal[i] == '\0') continue;
00211       if ( !( isprint((unsigned char)Internal[i]) || isspace((unsigned char)Internal[i]) ) )
00212         {
00213         //gdcmWarningMacro( "Cannot print :" << i );
00214         return false;
00215         }
00216       }
00217     return true;
00218     }
00219 
00220 protected:
00221   void Print(std::ostream &os) const {
00222   // This is perfectly valid to have a Length = 0 , so we cannot check
00223   // the length for printing
00224   if( !Internal.empty() )
00225     {
00226     if( IsPrintable(Length) )
00227       {
00228       // WARNING: Internal.end() != Internal.begin()+Length
00229       std::vector<char>::size_type length = Length;
00230       if( Internal.back() == 0 ) --length;
00231       std::copy(Internal.begin(), Internal.begin()+length,
00232         std::ostream_iterator<char>(os));
00233       }
00234     else
00235       os << "Loaded:" << Internal.size();
00236     }
00237   else
00238     {
00239     //os << "Not Loaded";
00240     os << "(no value available)";
00241     }
00242   }
00243 
00244 
00245 private:
00246   std::vector<char> Internal;
00247 
00248   // WARNING Length IS NOT Internal.size() some *featured* DICOM
00249   // implementation define odd length, we always load them as even number
00250   // of byte, so we need to keep the right Length
00251   VL Length;
00252 };
00253 
00254 } // end namespace gdcm
00255 
00256 #endif //GDCMBYTEVALUE_H
00257 

Generated on Sat Dec 4 2010 08:58:39 for GDCM by doxygen 1.7.2
SourceForge.net Logo