1 /*=========================================================================
2 
3   Program: GDCM (Grassroots DICOM). A DICOM library
4 
5   Copyright (c) 2006-2011 Mathieu Malaterre
6   All rights reserved.
7   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 #include "gdcmDataSet.h"
15 #include "gdcmPrivateTag.h"
16 
17 namespace gdcm_ns
18 {
19 DataElement DataSet::DEEnd = DataElement( Tag(0xffff,0xffff) );
20 
GetDEEnd() const21 const DataElement& DataSet::GetDEEnd() const
22 {
23   return DEEnd;
24 }
25 
GetPrivateCreator(const Tag & t) const26 std::string DataSet::GetPrivateCreator(const Tag &t) const
27 {
28   if( t.IsPrivate() && !t.IsPrivateCreator() )
29     {
30     Tag pc = t.GetPrivateCreator();
31     if( pc.GetElement() )
32       {
33       const DataElement r(pc);
34       ConstIterator it = DES.find(r);
35       if( it == DES.end() )
36         {
37         // FIXME, could this happen ?
38         return "";
39         }
40       const DataElement &de = *it;
41       if( de.IsEmpty() ) return "";
42       const ByteValue *bv = de.GetByteValue();
43       assert( bv );
44       std::string owner = std::string(bv->GetPointer(),bv->GetLength());
45       // There should not be any trailing space character...
46       // TODO: tmp.erase(tmp.find_last_not_of(' ') + 1);
47       while( !owner.empty() && owner[owner.size()-1] == ' ' )
48         {
49         // osirix/AbdominalCT/36382443
50         owner.erase(owner.size()-1,1);
51         }
52       assert( owner.size() == 0 || owner[owner.size()-1] != ' ' );
53       return owner;
54       }
55     }
56   return "";
57 }
58 
ComputeDataElement(const PrivateTag & t) const59 Tag DataSet::ComputeDataElement(const PrivateTag & t) const
60 {
61   gdcmDebugMacro( "Entering ComputeDataElement" );
62   //assert( t.IsPrivateCreator() ); // No this is wrong to do the assert: eg. (0x07a1,0x000a,"ELSCINT1")
63   // is valid because we have not yet done the mapping, so 0xa < 0x10 fails but might not later on
64   const Tag start(t.GetGroup(), 0x0010 ); // First possible private creator (0x0 -> 0x9 are reserved...)
65   const DataElement r(start);
66   ConstIterator it = DES.lower_bound(r);
67   const char *refowner = t.GetOwner();
68   assert( refowner );
69   bool found = false;
70   while( it != DES.end() && it->GetTag().GetGroup() == t.GetGroup() && it->GetTag().GetElement() < 0x100 )
71     {
72     //assert( it->GetTag().GetOwner() );
73     const ByteValue * bv = it->GetByteValue();
74     if( bv )
75       {
76       //if( strcmp( bv->GetPointer(), refowner ) == 0 )
77       std::string tmp(bv->GetPointer(),bv->GetLength());
78       // trim trailing whitespaces:
79       tmp.erase(tmp.find_last_not_of(' ') + 1);
80       assert( tmp.size() == 0 || tmp[ tmp.size() - 1 ] != ' ' ); // FIXME
81       if( System::StrCaseCmp( tmp.c_str(), refowner ) == 0 )
82         {
83         // found !
84         found = true;
85         break;
86         }
87       }
88     ++it;
89     }
90   gdcmDebugMacro( "In compute found is:" << found );
91   if (!found) return GetDEEnd().GetTag();
92   // else
93   // ok we found the Private Creator Data Element, let's construct the proper data element
94   Tag copy = t;
95   copy.SetPrivateCreator( it->GetTag() );
96   gdcmDebugMacro( "Compute found:" << copy );
97   return copy;
98 }
99 
FindDataElement(const PrivateTag & t) const100 bool DataSet::FindDataElement(const PrivateTag &t) const
101 {
102   return FindDataElement( ComputeDataElement(t) );
103 }
104 
GetDataElement(const PrivateTag & t) const105 const DataElement& DataSet::GetDataElement(const PrivateTag &t) const
106 {
107   return GetDataElement( ComputeDataElement(t) );
108 }
109 
GetMediaStorage() const110 MediaStorage DataSet::GetMediaStorage() const
111 {
112   // Let's check 0008,0016:
113   // D 0008|0016 [UI] [SOP Class UID] [1.2.840.10008.5.1.4.1.1.7 ]
114   // ==> [Secondary Capture Image Storage]
115   const Tag tsopclassuid(0x0008, 0x0016);
116   if( !FindDataElement( tsopclassuid) )
117     {
118     gdcmDebugMacro( "No SOP Class UID" );
119     return MediaStorage::MS_END;
120     }
121   const DataElement &de = GetDataElement(tsopclassuid);
122   if( de.IsEmpty() )
123     {
124     gdcmDebugMacro( "Empty SOP Class UID" );
125     return MediaStorage::MS_END;
126     }
127   std::string ts;
128     {
129     const ByteValue *bv = de.GetByteValue();
130     assert( bv );
131     if( bv->GetPointer() && bv->GetLength() )
132       {
133       // Pad string with a \0
134       ts = std::string(bv->GetPointer(), bv->GetLength());
135       }
136     }
137   // Paranoid check: if last character of a VR=UI is space let's pretend this is a \0
138   if( !ts.empty() )
139     {
140     char &last = ts[ts.size()-1];
141     if( last == ' ' )
142       {
143       gdcmWarningMacro( "Media Storage Class UID: " << ts << " contained a trailing space character" );
144       last = '\0';
145       }
146     }
147   gdcmDebugMacro( "TS: " << ts );
148   MediaStorage ms = MediaStorage::GetMSType(ts.c_str());
149   if( ms == MediaStorage::MS_END )
150     {
151     gdcmWarningMacro( "Media Storage Class UID: " << ts << " is unknown" );
152     }
153   return ms;
154 }
155 
156 } // end namespace gdcm_ns
157