Mercurial > hg > orthanc
comparison OrthancServer/FromDcmtkBridge.cpp @ 676:aa5ca7a2166f
experiments with pixel data
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 03 Jan 2014 17:49:31 +0100 |
parents | d233b5090105 |
children | 27acbc5985f5 |
comparison
equal
deleted
inserted
replaced
675:9a8716686f18 | 676:aa5ca7a2166f |
---|---|
119 #include <dcmtk/dcmdata/dcvrtm.h> | 119 #include <dcmtk/dcmdata/dcvrtm.h> |
120 #include <dcmtk/dcmdata/dcvrui.h> | 120 #include <dcmtk/dcmdata/dcvrui.h> |
121 #include <dcmtk/dcmdata/dcvrul.h> | 121 #include <dcmtk/dcmdata/dcvrul.h> |
122 #include <dcmtk/dcmdata/dcvrus.h> | 122 #include <dcmtk/dcmdata/dcvrus.h> |
123 #include <dcmtk/dcmdata/dcvrut.h> | 123 #include <dcmtk/dcmdata/dcvrut.h> |
124 #include <dcmtk/dcmdata/dcpixel.h> | |
125 #include <dcmtk/dcmdata/dcpixseq.h> | |
126 #include <dcmtk/dcmdata/dcpxitem.h> | |
127 | |
124 | 128 |
125 #include <boost/math/special_functions/round.hpp> | 129 #include <boost/math/special_functions/round.hpp> |
126 #include <glog/logging.h> | 130 #include <glog/logging.h> |
127 #include <dcmtk/dcmdata/dcostrmb.h> | 131 #include <dcmtk/dcmdata/dcostrmb.h> |
128 | 132 |
207 } | 211 } |
208 | 212 |
209 output.AnswerJson(v); | 213 output.AnswerJson(v); |
210 } | 214 } |
211 | 215 |
216 | |
217 static void AnswerPixelData(RestApiOutput& output, | |
218 DcmPixelData& pixelData, | |
219 E_TransferSyntax transferSyntax) | |
220 { | |
221 DcmPixelSequence* pixelSequence = NULL; | |
222 if (pixelData.getEncapsulatedRepresentation | |
223 (transferSyntax, NULL, pixelSequence).good() && pixelSequence) | |
224 { | |
225 for (unsigned long i = 0; i < pixelSequence->card(); i++) | |
226 { | |
227 DcmPixelItem* pixelItem = NULL; | |
228 if (pixelSequence->getItem(pixelItem, i).good() && pixelItem) | |
229 { | |
230 Uint8* b = NULL; | |
231 if (pixelItem->getUint8Array(b).good() && b) | |
232 { | |
233 // JPEG-LS (lossless) | |
234 // http://gdcm.sourceforge.net/wiki/index.php/Tools/ffmpeg#JPEG_LS | |
235 // http://www.stat.columbia.edu/~jakulin/jpeg-ls/ | |
236 // http://itohws03.ee.noda.sut.ac.jp/~matsuda/mrp/ | |
237 | |
238 printf("ITEM: %d\n", pixelItem->getLength()); | |
239 char buf[64]; | |
240 sprintf(buf, "/tmp/toto-%06ld.jpg", i); | |
241 FILE* fp = fopen(buf, "wb"); | |
242 fwrite(b, pixelItem->getLength(), 1, fp); | |
243 fclose(fp); | |
244 } | |
245 } | |
246 } | |
247 } | |
248 } | |
249 | |
250 | |
212 static void AnswerDicomField(RestApiOutput& output, | 251 static void AnswerDicomField(RestApiOutput& output, |
213 DcmElement& element) | 252 DcmElement& element, |
214 { | 253 E_TransferSyntax transferSyntax) |
215 // This element is not a sequence | 254 { |
255 // This element is not a sequence. Test if it is pixel data. | |
256 if (element.getTag().getGTag() == DICOM_TAG_PIXEL_DATA.GetGroup() && | |
257 element.getTag().getETag() == DICOM_TAG_PIXEL_DATA.GetElement()) | |
258 { | |
259 try | |
260 { | |
261 DcmPixelData& pixelData = dynamic_cast<DcmPixelData&>(element); | |
262 AnswerPixelData(output, pixelData, transferSyntax); | |
263 return; | |
264 } | |
265 catch (std::bad_cast&) | |
266 { | |
267 } | |
268 } | |
269 | |
270 | |
271 // This element is nor a sequence, neither a pixel-data | |
216 std::string buffer; | 272 std::string buffer; |
217 buffer.resize(65536); | 273 buffer.resize(65536); |
218 Uint32 length = element.getLength(); | 274 Uint32 length = element.getLength(transferSyntax); |
219 Uint32 offset = 0; | 275 Uint32 offset = 0; |
220 | 276 |
221 output.GetLowLevelOutput().SendOkHeader("application/octet-stream", true, length, NULL); | 277 output.GetLowLevelOutput().SendOkHeader("application/octet-stream", true, length, NULL); |
222 | 278 |
223 while (offset < length) | 279 while (offset < length) |
230 else | 286 else |
231 { | 287 { |
232 nbytes = buffer.size(); | 288 nbytes = buffer.size(); |
233 } | 289 } |
234 | 290 |
235 if (element.getPartialValue(&buffer[0], offset, nbytes).good()) | 291 OFCondition cond = element.getPartialValue(&buffer[0], offset, nbytes); |
292 | |
293 if (cond.good()) | |
236 { | 294 { |
237 output.GetLowLevelOutput().Send(&buffer[0], nbytes); | 295 output.GetLowLevelOutput().Send(&buffer[0], nbytes); |
238 offset += nbytes; | 296 offset += nbytes; |
239 } | 297 } |
240 else | 298 else |
241 { | 299 { |
242 LOG(ERROR) << "Error while sending a DICOM field"; | 300 LOG(ERROR) << "Error while sending a DICOM field: " << cond.text(); |
243 return; | 301 return; |
244 } | 302 } |
245 } | 303 } |
246 | 304 |
247 output.MarkLowLevelOutputDone(); | 305 output.MarkLowLevelOutputDone(); |
248 } | 306 } |
249 | 307 |
250 static void SendPathValueForLeaf(RestApiOutput& output, | 308 static void SendPathValueForLeaf(RestApiOutput& output, |
251 const std::string& tag, | 309 const std::string& tag, |
252 DcmItem& dicom) | 310 DcmItem& dicom, |
311 E_TransferSyntax transferSyntax) | |
253 { | 312 { |
254 DcmTagKey k; | 313 DcmTagKey k; |
255 ParseTagAndGroup(k, tag); | 314 ParseTagAndGroup(k, tag); |
256 | 315 |
257 DcmSequenceOfItems* sequence = NULL; | 316 DcmSequenceOfItems* sequence = NULL; |
267 if (dicom.findAndGetElement(k, element).good() && | 326 if (dicom.findAndGetElement(k, element).good() && |
268 element != NULL && | 327 element != NULL && |
269 //element->getVR() != EVR_UNKNOWN && // This would forbid private tags | 328 //element->getVR() != EVR_UNKNOWN && // This would forbid private tags |
270 element->getVR() != EVR_SQ) | 329 element->getVR() != EVR_SQ) |
271 { | 330 { |
272 AnswerDicomField(output, *element); | 331 AnswerDicomField(output, *element, transferSyntax); |
273 } | 332 } |
274 } | 333 } |
275 | 334 |
276 void ParsedDicomFile::SendPathValue(RestApiOutput& output, | 335 void ParsedDicomFile::SendPathValue(RestApiOutput& output, |
277 const UriComponents& uri) | 336 const UriComponents& uri) |
308 { | 367 { |
309 SendPathValueForDictionary(output, *dicom); | 368 SendPathValueForDictionary(output, *dicom); |
310 } | 369 } |
311 else | 370 else |
312 { | 371 { |
313 SendPathValueForLeaf(output, uri.back(), *dicom); | 372 SendPathValueForLeaf(output, uri.back(), *dicom, file_->getDataset()->getOriginalXfer()); |
314 } | 373 } |
315 } | 374 } |
316 | 375 |
317 | 376 |
318 | 377 |