GDCM 2.0.17

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 
00048   ByteValue(std::vector<char> &v):Internal(v),Length((uint32_t)v.size()) {}
00049   //ByteValue(std::ostringstream const &os) {
00050   //  (void)os;
00051   //   assert(0); // TODO
00052   //}
00053   ~ByteValue() {
00054     Internal.clear();
00055   }
00056 
00057   // When 'dumping' dicom file we still have some information from
00058   // Either the VR: eg LO (private tag)
00059   void PrintASCII(std::ostream &os, VL maxlength ) const;
00060 
00061   void PrintHex(std::ostream &os, VL maxlength) const;
00062 
00063   // Either from Element Number (== 0x0000)
00064   void PrintGroupLength(std::ostream &os) {
00065     assert( Length == 2 );
00066     (void)os;
00067   }
00068 
00069   bool IsEmpty() const {
00070     if( Internal.empty() ) assert( Length == 0 );
00071     return Internal.empty();
00072   }
00073   VL GetLength() const { return Length; }
00074   // Does a reallocation
00075   void SetLength(VL vl) {
00076     VL l(vl);
00077 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
00078     // CompressedLossy.dcm
00079     if( l.IsUndefined() ) throw Exception( "Impossible" );
00080     if ( l.IsOdd() ) {
00081       gdcmDebugMacro(
00082         "BUGGY HEADER: Your dicom contain odd length value field." );
00083       ++l;
00084       }
00085 #else
00086     assert( !l.IsUndefined() && !l.IsOdd() );
00087 #endif
00088     // I cannot use reserve for now. I need to implement:
00089     // STL - vector<> and istream
00090     // http://groups.google.com/group/comp.lang.c++/msg/37ec052ed8283e74
00091 //#define SHORT_READ_HACK
00092     try
00093       {
00094 #ifdef SHORT_READ_HACK
00095     if( l <= 0xff )
00096 #endif
00097       Internal.resize(l);
00098       //Internal.reserve(l);
00099       }
00100     catch(...)
00101       {
00102       //throw Exception("Impossible to allocate: " << l << " bytes." );
00103       throw Exception("Impossible to allocate" );
00104       }
00105     // Keep the exact length
00106     Length = vl;
00107   }
00108 
00109   operator const std::vector<char>& () const { return Internal; }
00110 
00111   ByteValue &operator=(const ByteValue &val) {
00112     Internal = val.Internal;
00113     Length = val.Length;
00114     return *this;
00115     }
00116 
00117   bool operator==(const ByteValue &val) const {
00118     if( Length != val.Length )
00119       return false;
00120     if( Internal == val.Internal )
00121       return true;
00122     return false;
00123     }
00124   bool operator==(const Value &val) const
00125     {
00126     const ByteValue &bv = dynamic_cast<const ByteValue&>(val);
00127     return Length == bv.Length && Internal == bv.Internal;
00128     }
00129 
00130 
00131   void Clear() {
00132     Internal.clear();
00133   }
00134   // Use that only if you understand what you are doing
00135   const char *GetPointer() const {
00136     if(!Internal.empty()) return &Internal[0];
00137     return 0;
00138   }
00139   void Fill(char c) {
00140     //if( Internal.empty() ) return;
00141     std::vector<char>::iterator it = Internal.begin();
00142     for(; it != Internal.end(); ++it) *it = c;
00143   }
00144   bool GetBuffer(char *buffer, unsigned long length) const {
00145     // SIEMENS_GBS_III-16-ACR_NEMA_1.acr has a weird pixel length
00146     // so we need an inequality
00147     if( length <= Internal.size() )
00148       {
00149       memcpy(buffer, &Internal[0], length);
00150       return true;
00151       }
00152     gdcmDebugMacro( "Could not handle length= " << length );
00153     return false;
00154     }
00155   bool WriteBuffer(std::ostream &os) const {
00156     if( Length ) {
00157       //assert( Internal.size() <= Length );
00158       assert( !(Internal.size() % 2) );
00159       os.write(&Internal[0], Internal.size() );
00160       }
00161     return true;
00162   }
00163 
00164   template <typename TSwap, typename TType>
00165   std::istream &Read(std::istream &is) {
00166     // If Length is odd we have detected that in SetLength
00167     // and calling std::vector::resize make sure to allocate *AND*
00168     // initialize values to 0 so we are sure to have a \0 at the end
00169     // even in this case
00170     if(Length)
00171       {
00172       is.read(&Internal[0], Length);
00173       assert( Internal.size() == Length || Internal.size() == Length + 1 );
00174       TSwap::SwapArray((TType*)&Internal[0], Internal.size() / sizeof(TType) );
00175       }
00176     return is;
00177   }
00178 
00179   template <typename TSwap>
00180   std::istream &Read(std::istream &is) {
00181     return Read<TSwap,uint8_t>(is);
00182   }
00183 
00184 
00185   template <typename TSwap, typename TType>
00186   std::ostream const &Write(std::ostream &os) const {
00187     assert( !(Internal.size() % 2) );
00188     if( !Internal.empty() ) {
00189       //os.write(&Internal[0], Internal.size());
00190       std::vector<char> copy = Internal;
00191       TSwap::SwapArray((TType*)&copy[0], Internal.size() / sizeof(TType) );
00192       os.write(&copy[0], copy.size());
00193       }
00194     return os;
00195   }
00196 
00197   template <typename TSwap>
00198   std::ostream const &Write(std::ostream &os) const {
00199     return Write<TSwap,uint8_t>(os);
00200   }
00201 
00208   bool IsPrintable(VL length) const {
00209     assert( length <= Length );
00210     for(unsigned int i=0; i<length; i++)
00211       {
00212       if ( i == (length-1) && Internal[i] == '\0') continue;
00213       if ( !( isprint((unsigned char)Internal[i]) || isspace((unsigned char)Internal[i]) ) )
00214         {
00215         //gdcmWarningMacro( "Cannot print :" << i );
00216         return false;
00217         }
00218       }
00219     return true;
00220     }
00221 
00222 protected:
00223   void Print(std::ostream &os) const {
00224   // This is perfectly valid to have a Length = 0 , so we cannot check
00225   // the length for printing
00226   if( !Internal.empty() )
00227     {
00228     if( IsPrintable(Length) )
00229       {
00230       // WARNING: Internal.end() != Internal.begin()+Length
00231       std::vector<char>::size_type length = Length;
00232       if( Internal.back() == 0 ) --length;
00233       std::copy(Internal.begin(), Internal.begin()+length,
00234         std::ostream_iterator<char>(os));
00235       }
00236     else
00237       os << "Loaded:" << Internal.size();
00238     }
00239   else
00240     {
00241     //os << "Not Loaded";
00242     os << "(no value available)";
00243     }
00244   }
00245 
00246 
00247 private:
00248   std::vector<char> Internal;
00249 
00250   // WARNING Length IS NOT Internal.size() some *featured* DICOM
00251   // implementation define odd length, we always load them as even number
00252   // of byte, so we need to keep the right Length
00253   VL Length;
00254 };
00255 
00256 } // end namespace gdcm
00257 
00258 #endif //GDCMBYTEVALUE_H

Generated on Tue Feb 1 2011 12:30:25 for GDCM by doxygen 1.7.3
SourceForge.net Logo