GDCM 2.0.17
|
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*)©[0], Internal.size() / sizeof(TType) ); 00192 os.write(©[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