comparison OrthancServer/FromDcmtkBridge.cpp @ 285:4031f73fe0e4

access to the raw dicom tags
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 12 Dec 2012 17:53:14 +0100
parents 81f11fb357f2
children 4d7469f72a0b
comparison
equal deleted inserted replaced
284:06aa7b7b6723 285:4031f73fe0e4
61 61
62 #include <boost/math/special_functions/round.hpp> 62 #include <boost/math/special_functions/round.hpp>
63 63
64 namespace Orthanc 64 namespace Orthanc
65 { 65 {
66 ParsedDicomFile::ParsedDicomFile(const std::string& content)
67 {
68 DcmInputBufferStream is;
69 if (content.size() > 0)
70 {
71 is.setBuffer(&content[0], content.size());
72 }
73 is.setEos();
74
75 file_.reset(new DcmFileFormat);
76 if (!file_->read(is).good())
77 {
78 throw OrthancException(ErrorCode_BadFileFormat);
79 }
80 }
81
82
83 static void SendPathValueForDictionary(RestApiOutput& output,
84 DcmItem& dicom)
85 {
86 Json::Value v = Json::arrayValue;
87
88 for (unsigned long i = 0; i < dicom.card(); i++)
89 {
90 DcmElement* element = dicom.getElement(i);
91 if (element)
92 {
93 char buf[16];
94 sprintf(buf, "%04x-%04x", element->getTag().getGTag(), element->getTag().getETag());
95 v.append(buf);
96 }
97 }
98
99 output.AnswerJson(v);
100 }
101
102 static inline uint16_t GetCharValue(char c)
103 {
104 if (c >= '0' && c <= '9')
105 return c - '0';
106 else if (c >= 'a' && c <= 'f')
107 return c - 'a' + 10;
108 else if (c >= 'A' && c <= 'F')
109 return c - 'A' + 10;
110 else
111 return 0;
112 }
113
114 static inline uint16_t GetTagValue(const char* c)
115 {
116 return ((GetCharValue(c[0]) << 12) +
117 (GetCharValue(c[1]) << 8) +
118 (GetCharValue(c[2]) << 4) +
119 GetCharValue(c[3]));
120 }
121
122 static bool ParseTagAndGroup(DcmTagKey& key,
123 const std::string& tag)
124 {
125 if (tag.size() != 9 ||
126 !isxdigit(tag[0]) ||
127 !isxdigit(tag[1]) ||
128 !isxdigit(tag[2]) ||
129 !isxdigit(tag[3]) ||
130 tag[4] != '-' ||
131 !isxdigit(tag[5]) ||
132 !isxdigit(tag[6]) ||
133 !isxdigit(tag[7]) ||
134 !isxdigit(tag[8]))
135 {
136 return false;
137 }
138
139 uint16_t group = GetTagValue(tag.c_str());
140 uint16_t element = GetTagValue(tag.c_str() + 5);
141
142 key = DcmTagKey(group, element);
143
144 return true;
145 }
146
147 static void SendPathValueForLeaf(RestApiOutput& output,
148 const std::string& tag,
149 DcmItem& dicom)
150 {
151 DcmTagKey k;
152 if (!ParseTagAndGroup(k, tag))
153 {
154 return;
155 }
156
157 DcmElement* element = NULL;
158 if (dicom.findAndGetElement(k, element).good() && element != NULL)
159 {
160 if (element->getVR() == EVR_SQ)
161 {
162 // This element is a sequence
163 Json::Value v = Json::arrayValue;
164 DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(*element);
165
166 for (unsigned long i = 0; i < sequence.card(); i++)
167 {
168 v.append(boost::lexical_cast<std::string>(i));
169 }
170
171 output.AnswerJson(v);
172 }
173 else
174 {
175 // This element is not a sequence
176 std::string buffer;
177 buffer.resize(65536);
178 Uint32 length = element->getLength();
179 Uint32 offset = 0;
180
181 output.GetLowLevelOutput().SendOkHeader("application/octet-stream", true, length, NULL);
182
183 while (offset < length)
184 {
185 Uint32 nbytes;
186 if (length - offset < buffer.size())
187 {
188 nbytes = length - offset;
189 }
190 else
191 {
192 nbytes = buffer.size();
193 }
194
195 if (element->getPartialValue(&buffer[0], offset, nbytes).good())
196 {
197 output.GetLowLevelOutput().Send(&buffer[0], nbytes);
198 offset += nbytes;
199 }
200 else
201 {
202 return;
203 }
204 }
205
206 output.MarkLowLevelOutputDone();
207 }
208 }
209 }
210
211 void ParsedDicomFile::SendPathValue(RestApiOutput& output,
212 const UriComponents& uri)
213 {
214 DcmItem* dicom = file_->getDataset();
215
216 // Go down in the tag hierarchy according to the URI
217 for (size_t pos = 0; pos < uri.size() / 2; pos++)
218 {
219 size_t index;
220 try
221 {
222 index = boost::lexical_cast<size_t>(uri[2 * pos + 1]);
223 }
224 catch (boost::bad_lexical_cast&)
225 {
226 return;
227 }
228
229 DcmTagKey k;
230 DcmItem *child = NULL;
231 if (!ParseTagAndGroup(k, uri[2 * pos]) ||
232 !dicom->findAndGetSequenceItem(k, child, index).good() ||
233 child == NULL)
234 {
235 return;
236 }
237
238 dicom = child;
239 }
240
241 // We have reached the end of the URI
242 if (uri.size() % 2 == 0)
243 {
244 SendPathValueForDictionary(output, *dicom);
245 }
246 else
247 {
248 SendPathValueForLeaf(output, uri.back(), *dicom);
249 }
250 }
251
252
66 void FromDcmtkBridge::Convert(DicomMap& target, DcmDataset& dataset) 253 void FromDcmtkBridge::Convert(DicomMap& target, DcmDataset& dataset)
67 { 254 {
68 target.Clear(); 255 target.Clear();
69 for (unsigned long i = 0; i < dataset.card(); i++) 256 for (unsigned long i = 0; i < dataset.card(); i++)
70 { 257 {