Mercurial > hg > orthanc
comparison OrthancServer/FromDcmtkBridge.cpp @ 286:727a6d766dde
merge
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 13 Dec 2012 14:52:57 +0100 |
parents | 4031f73fe0e4 |
children | 4d7469f72a0b |
comparison
equal
deleted
inserted
replaced
281:e5402c368b21 | 286:727a6d766dde |
---|---|
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 { |