/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Module: $URL$ Copyright (c) 2006-2009 Mathieu Malaterre All rights reserved. See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "gdcmStringFilter.h" #include "gdcmGlobal.h" #include "gdcmElement.h" #include "gdcmByteValue.h" #include "gdcmAttribute.h" #include "gdcmDataSetHelper.h" namespace gdcm { //----------------------------------------------------------------------------- StringFilter::StringFilter():F(new File) { } //----------------------------------------------------------------------------- StringFilter::~StringFilter() { } 00034 void StringFilter::SetDicts(const Dicts &dicts) { assert(0); // FIXME } 00039 std::string StringFilter::ToString(const Tag& t) const { return ToStringPair(t).second; } /* std::string StringFilter::ToMIME64(const Tag& t) const { return ToStringPair(t).second; // base64 streams have to be a multiple of 4 bytes long int encodedLengthEstimate = 2 * bv->GetLength(); encodedLengthEstimate = ((encodedLengthEstimate / 4) + 1) * 4; char *bin = new char[encodedLengthEstimate]; unsigned int encodedLengthActual = static_cast<unsigned int>( itksysBase64_Encode( (const unsigned char *) bv->GetPointer(), static_cast< unsigned long>( bv->GetLength() ), (unsigned char *) bin, static_cast< int >( 0 ) )); std::string encodedValue(bin, encodedLengthActual); } */ #define StringFilterCase(type) \ case VR::type: \ { \ Element<VR::type,VM::VM1_n> el; \ if( !de.IsEmpty() ) { \ el.Set( de.GetValue() ); \ if( el.GetLength() ) { \ os << el.GetValue(); \ for(unsigned long i = 1; i < el.GetLength(); ++i) os << "\\" << el.GetValue(i); \ ret.second = os.str(); } } \ } break 00076 std::pair<std::string, std::string> StringFilter::ToStringPair(const Tag& t) const { if( t.GetGroup() == 0x2 ) { const FileMetaInformation &header = GetFile().GetHeader(); return ToStringPair(t, header); } else { const DataSet &ds = GetFile().GetDataSet(); return ToStringPair(t, ds); } } std::pair<std::string, std::string> StringFilter::ToStringPair(const Tag& t, DataSet const &ds) const { std::pair<std::string, std::string> ret; const Global &g = GlobalInstance; const Dicts &dicts = g.GetDicts(); if( ds.IsEmpty() || !ds.FindDataElement(t) ) { gdcmDebugMacro( "DataSet is empty or does not contains tag:" ); return ret; } const DataElement &de = ds.GetDataElement( t ); //assert( de.GetTag().IsPublic() ); std::string strowner; const char *owner = 0; if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(de.GetTag(), owner); const VR &vr_read = de.GetVR(); const VR &vr_dict = entry.GetVR(); if( vr_dict == VR::INVALID ) { // FIXME This is a public element we do not support... return ret; } VR vr; // always prefer the vr from the file: if( vr_read == VR::INVALID ) { vr = vr_dict; } else if ( vr_read == VR::UN && vr_dict != VR::INVALID ) // File is explicit, but still prefer vr from dict when UN { vr = vr_dict; } else // cool the file is Explicit ! { vr = vr_read; } if( vr.IsDual() ) // This mean vr was read from a dict entry: { vr = DataSetHelper::ComputeVR(*F,ds, t); } if( vr == VR::UN ) { // this element is not known... return ret; } assert( vr != VR::UN && vr != VR::INVALID ); //std::cerr << "Found " << vr << " for " << de.GetTag() << std::endl; ret.first = entry.GetName(); if( VR::IsASCII( vr ) ) { assert( vr & VR::VRASCII ); const ByteValue *bv = de.GetByteValue(); if( de.GetVL() ) { assert( bv /*|| bv->IsEmpty()*/ ); ret.second = std::string( bv->GetPointer(), bv->GetLength() ); // Let's remove any trailing \0 : ret.second.resize( std::min( ret.second.size(), strlen( ret.second.c_str() ) ) ); // strlen is garantee to be lower or equal to ::size() } else { //assert( bv == NULL ); ret.second = ""; // ?? } } else { assert( vr & VR::VRBINARY ); const ByteValue *bv = de.GetByteValue(); std::ostringstream os; if( bv ) { VM::VMType vm = entry.GetVM(); //assert( vm == VM::VM1 ); if( vr.IsDual() ) // This mean vr was read from a dict entry: { vr = DataSetHelper::ComputeVR(GetFile(),ds, t); } std::ostringstream os; switch(vr) { StringFilterCase(AT); StringFilterCase(FL); StringFilterCase(FD); //StringFilterCase(OB); StringFilterCase(OF); //StringFilterCase(OW); StringFilterCase(SL); //StringFilterCase(SQ); StringFilterCase(SS); StringFilterCase(UL); //StringFilterCase(UN); StringFilterCase(US); StringFilterCase(UT); case VR::UN: case VR::US_SS: assert(0); break; case VR::OB: case VR::OW: case VR::OB_OW: case VR::SQ: gdcmWarningMacro( "Unhandled: " << vr << " for tag " << de.GetTag() ); ret.second = ""; break; default: assert(0); break; } } } return ret; } 00215 std::string StringFilter::FromString(const Tag&t, const char * value, VL const & vl) { abort(); return ""; } #define FromStringFilterCase(type) \ case VR::type: \ { \ Element<VR::type,VM::VM1_n> el; \ /* el.ReadComputeLength( is ); */ \ el.SetLength( vl ); \ for(unsigned int i = 0; i < vm.GetLength(); ++i) \ is >> el.GetValue(i); \ el.Write(os); \ } \ break size_t count_backslash(const char *s, size_t len) { size_t c = 0; for(size_t i = 0; i < len; ++i, ++s) { if( *s == '\\' ) { ++c; } } return c; } std::string StringFilter::FromString(const Tag&t, const char * value, size_t len) { if( !value || !len ) return ""; const Global &g = GlobalInstance; const Dicts &dicts = g.GetDicts(); std::string strowner; const char *owner = 0; const DataSet &ds = GetFile().GetDataSet(); if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(t, owner); const VM &vm = entry.GetVM(); //const VR &vr = entry.GetVR(); const DataElement &de = ds.GetDataElement( t ); const VR &vr_read = de.GetVR(); const VR &vr_dict = entry.GetVR(); VR vr; // always prefer the vr from the file: if( vr_read == VR::INVALID ) { vr = vr_dict; } else if ( vr_read == VR::UN && vr_dict != VR::INVALID ) // File is explicit, but still prefer vr from dict when UN { vr = vr_dict; } else // cool the file is Explicit ! { vr = vr_read; } if( vr.IsDual() ) // This mean vr was read from a dict entry: { vr = DataSetHelper::ComputeVR(*F,ds, t); } if( vr == VR::UN ) { // this element is not known... //return ret; } std::string s(value,value+len); if( VR::IsASCII( vr ) ) { return s; } unsigned int count = VM::GetNumberOfElementsFromArray(value, len); VL vl = vm.GetLength() * vr.GetSizeof(); if( vm.GetLength() == 0 ) { // VM1_n vl = count * vr.GetSizeof(); VM check = VM::GetVMTypeFromLength(count, 1); assert( vm.Compatible( check ) ); } //if( vl != vm.GetLength() * vr.GetSizeof() ) // { // assert(0); // } std::istringstream is; is.str( s ); std::ostringstream os; switch(vr) { FromStringFilterCase(AT); FromStringFilterCase(FL); FromStringFilterCase(FD); //FromStringFilterCase(OB); FromStringFilterCase(OF); //FromStringFilterCase(OW); FromStringFilterCase(SL); //FromStringFilterCase(SQ); FromStringFilterCase(SS); FromStringFilterCase(UL); //FromStringFilterCase(UN); FromStringFilterCase(US); FromStringFilterCase(UT); default: gdcmErrorMacro( "Not implemented" ); assert(0); } return os.str(); } }