comparison OrthancServer/FromDcmtkBridge.cpp @ 302:238134081136

modification of dicom files
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 18 Dec 2012 17:29:30 +0100
parents 4d7469f72a0b
children c76a35a85c69
comparison
equal deleted inserted replaced
301:be378326f50b 302:238134081136
45 45
46 #include <limits> 46 #include <limits>
47 47
48 #include <boost/lexical_cast.hpp> 48 #include <boost/lexical_cast.hpp>
49 49
50 #include <dcmtk/dcmdata/dcchrstr.h>
50 #include <dcmtk/dcmdata/dcdicent.h> 51 #include <dcmtk/dcmdata/dcdicent.h>
51 #include <dcmtk/dcmdata/dcdict.h> 52 #include <dcmtk/dcmdata/dcdict.h>
52 #include <dcmtk/dcmdata/dcfilefo.h> 53 #include <dcmtk/dcmdata/dcfilefo.h>
53 #include <dcmtk/dcmdata/dcistrmb.h> 54 #include <dcmtk/dcmdata/dcistrmb.h>
55 #include <dcmtk/dcmdata/dcuid.h>
56
57 #include <dcmtk/dcmdata/dcvrae.h>
58 #include <dcmtk/dcmdata/dcvras.h>
59 #include <dcmtk/dcmdata/dcvrcs.h>
60 #include <dcmtk/dcmdata/dcvrda.h>
61 #include <dcmtk/dcmdata/dcvrds.h>
62 #include <dcmtk/dcmdata/dcvrdt.h>
54 #include <dcmtk/dcmdata/dcvrfd.h> 63 #include <dcmtk/dcmdata/dcvrfd.h>
55 #include <dcmtk/dcmdata/dcvrfl.h> 64 #include <dcmtk/dcmdata/dcvrfl.h>
65 #include <dcmtk/dcmdata/dcvris.h>
66 #include <dcmtk/dcmdata/dcvrlo.h>
67 #include <dcmtk/dcmdata/dcvrlt.h>
68 #include <dcmtk/dcmdata/dcvrpn.h>
69 #include <dcmtk/dcmdata/dcvrsh.h>
56 #include <dcmtk/dcmdata/dcvrsl.h> 70 #include <dcmtk/dcmdata/dcvrsl.h>
57 #include <dcmtk/dcmdata/dcvrss.h> 71 #include <dcmtk/dcmdata/dcvrss.h>
72 #include <dcmtk/dcmdata/dcvrst.h>
73 #include <dcmtk/dcmdata/dcvrtm.h>
74 #include <dcmtk/dcmdata/dcvrui.h>
58 #include <dcmtk/dcmdata/dcvrul.h> 75 #include <dcmtk/dcmdata/dcvrul.h>
59 #include <dcmtk/dcmdata/dcvrus.h> 76 #include <dcmtk/dcmdata/dcvrus.h>
60 #include <dcmtk/dcmdata/dcuid.h> 77 #include <dcmtk/dcmdata/dcvrut.h>
61 78
62 #include <boost/math/special_functions/round.hpp> 79 #include <boost/math/special_functions/round.hpp>
63 #include <glog/logging.h> 80 #include <glog/logging.h>
64 #include <dcmtk/dcmdata/dcostrmb.h> 81 #include <dcmtk/dcmdata/dcostrmb.h>
65 82
84 file_->transferEnd(); 101 file_->transferEnd();
85 } 102 }
86 103
87 104
88 static void SendPathValueForDictionary(RestApiOutput& output, 105 static void SendPathValueForDictionary(RestApiOutput& output,
89 DcmItem& dicom) 106 DcmItem& dicom)
90 { 107 {
91 Json::Value v = Json::arrayValue; 108 Json::Value v = Json::arrayValue;
92 109
93 for (unsigned long i = 0; i < dicom.card(); i++) 110 for (unsigned long i = 0; i < dicom.card(); i++)
94 { 111 {
162 } 179 }
163 180
164 output.AnswerJson(v); 181 output.AnswerJson(v);
165 } 182 }
166 183
167 static void SendField(RestApiOutput& output, 184 static void AnswerDicomField(RestApiOutput& output,
168 DcmElement& element) 185 DcmElement& element)
169 { 186 {
170 // This element is not a sequence 187 // This element is not a sequence
171 std::string buffer; 188 std::string buffer;
172 buffer.resize(65536); 189 buffer.resize(65536);
173 Uint32 length = element.getLength(); 190 Uint32 length = element.getLength();
192 output.GetLowLevelOutput().Send(&buffer[0], nbytes); 209 output.GetLowLevelOutput().Send(&buffer[0], nbytes);
193 offset += nbytes; 210 offset += nbytes;
194 } 211 }
195 else 212 else
196 { 213 {
214 LOG(ERROR) << "Error while sending a DICOM field";
197 return; 215 return;
198 } 216 }
199 } 217 }
200 218
201 output.MarkLowLevelOutputDone(); 219 output.MarkLowLevelOutputDone();
224 if (dicom.findAndGetElement(k, element).good() && 242 if (dicom.findAndGetElement(k, element).good() &&
225 element != NULL && 243 element != NULL &&
226 element->getVR() != EVR_UNKNOWN && 244 element->getVR() != EVR_UNKNOWN &&
227 element->getVR() != EVR_SQ) 245 element->getVR() != EVR_SQ)
228 { 246 {
229 SendField(output, *element); 247 AnswerDicomField(output, *element);
230 } 248 }
231 } 249 }
232 250
233 void ParsedDicomFile::SendPathValue(RestApiOutput& output, 251 void ParsedDicomFile::SendPathValue(RestApiOutput& output,
234 const UriComponents& uri) 252 const UriComponents& uri)
270 SendPathValueForLeaf(output, uri.back(), *dicom); 288 SendPathValueForLeaf(output, uri.back(), *dicom);
271 } 289 }
272 } 290 }
273 291
274 292
275 void FromDcmtkBridge::Convert(DicomMap& target, DcmDataset& dataset) 293
276 { 294
277 target.Clear(); 295
278 for (unsigned long i = 0; i < dataset.card(); i++) 296 static DcmElement* CreateElementForTag(const DicomTag& tag)
279 { 297 {
280 DcmElement* element = dataset.getElement(i); 298 DcmTag key(tag.GetGroup(), tag.GetElement());
281 if (element && element->isLeaf()) 299
282 { 300 switch (key.getEVR())
283 target.SetValue(element->getTag().getGTag(),
284 element->getTag().getETag(),
285 ConvertLeafElement(*element));
286 }
287 }
288 }
289
290
291 DicomTag FromDcmtkBridge::GetTag(const DcmElement& element)
292 {
293 return DicomTag(element.getGTag(), element.getETag());
294 }
295
296
297 DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element)
298 {
299 if (!element.isLeaf())
300 {
301 throw OrthancException("Only applicable to leaf elements");
302 }
303
304 if (element.isaString())
305 {
306 char *c;
307 if (element.getString(c).good() &&
308 c != NULL)
309 {
310 std::string s(c);
311 std::string utf8 = Toolbox::ConvertToUtf8(s, "ISO-8859-1"); // TODO Parameter?
312 return new DicomString(utf8);
313 }
314 else
315 {
316 return new DicomNullValue;
317 }
318 }
319
320 try
321 { 301 {
322 // http://support.dcmtk.org/docs/dcvr_8h-source.html 302 // http://support.dcmtk.org/docs/dcvr_8h-source.html
323 switch (element.getVR()) 303
324 { 304 /**
325 305 * TODO.
326 /** 306 **/
327 * TODO.
328 **/
329 307
330 case EVR_DS: // decimal string
331 case EVR_IS: // integer string
332 case EVR_OB: // other byte 308 case EVR_OB: // other byte
333 case EVR_OF: // other float 309 case EVR_OF: // other float
334 case EVR_OW: // other word 310 case EVR_OW: // other word
311 case EVR_AT: // attribute tag
312 throw OrthancException(ErrorCode_NotImplemented);
313
314 case EVR_UN: // unknown value representation
315 throw OrthancException(ErrorCode_ParameterOutOfRange);
316
317
318 /**
319 * String types.
320 * http://support.dcmtk.org/docs/classDcmByteString.html
321 **/
322
335 case EVR_AS: // age string 323 case EVR_AS: // age string
336 case EVR_AT: // attribute tag 324 return new DcmAgeString(key);
325
326 case EVR_AE: // application entity title
327 return new DcmApplicationEntity(key);
328
329 case EVR_CS: // code string
330 return new DcmCodeString(key);
331
337 case EVR_DA: // date string 332 case EVR_DA: // date string
333 return new DcmDate(key);
334
338 case EVR_DT: // date time string 335 case EVR_DT: // date time string
336 return new DcmDateTime(key);
337
338 case EVR_DS: // decimal string
339 return new DcmDecimalString(key);
340
341 case EVR_IS: // integer string
342 return new DcmIntegerString(key);
343
339 case EVR_TM: // time string 344 case EVR_TM: // time string
340 case EVR_UN: // unknown value representation 345 return new DcmTime(key);
341 return new DicomNullValue(); 346
342 347 case EVR_UI: // unique identifier
343 348 return new DcmUniqueIdentifier(key);
344 /** 349
345 * String types, should never happen at this point because of 350 case EVR_ST: // short text
346 * "element.isaString()". 351 return new DcmShortText(key);
347 **/ 352
348 353 case EVR_LO: // long string
349 case EVR_AE: // application entity title 354 return new DcmLongString(key);
350 case EVR_CS: // code string 355
356 case EVR_LT: // long text
357 return new DcmLongText(key);
358
359 case EVR_UT: // unlimited text
360 return new DcmUnlimitedText(key);
361
351 case EVR_SH: // short string 362 case EVR_SH: // short string
352 case EVR_LO: // long string 363 return new DcmShortString(key);
353 case EVR_ST: // short text 364
354 case EVR_LT: // long text
355 case EVR_UT: // unlimited text
356 case EVR_PN: // person name 365 case EVR_PN: // person name
357 case EVR_UI: // unique identifier 366 return new DcmPersonName(key);
358 return new DicomNullValue(); 367
359 368
360 369 /**
361 /** 370 * Numerical types
362 * Numerical types 371 **/
363 **/
364 372
365 case EVR_SL: // signed long 373 case EVR_SL: // signed long
366 { 374 return new DcmSignedLong(key);
367 Sint32 f;
368 if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good())
369 {
370 return new DicomString(boost::lexical_cast<std::string>(f));
371 }
372 else
373 {
374 return new DicomNullValue();
375 }
376 }
377 375
378 case EVR_SS: // signed short 376 case EVR_SS: // signed short
379 { 377 return new DcmSignedShort(key);
380 Sint16 f;
381 if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good())
382 {
383 return new DicomString(boost::lexical_cast<std::string>(f));
384 }
385 else
386 {
387 return new DicomNullValue();
388 }
389 }
390 378
391 case EVR_UL: // unsigned long 379 case EVR_UL: // unsigned long
392 { 380 return new DcmUnsignedLong(key);
393 Uint32 f;
394 if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good())
395 {
396 return new DicomString(boost::lexical_cast<std::string>(f));
397 }
398 else
399 {
400 return new DicomNullValue();
401 }
402 }
403 381
404 case EVR_US: // unsigned short 382 case EVR_US: // unsigned short
405 { 383 return new DcmUnsignedShort(key);
406 Uint16 f;
407 if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good())
408 {
409 return new DicomString(boost::lexical_cast<std::string>(f));
410 }
411 else
412 {
413 return new DicomNullValue();
414 }
415 }
416 384
417 case EVR_FL: // float single-precision 385 case EVR_FL: // float single-precision
418 { 386 return new DcmFloatingPointSingle(key);
419 Float32 f;
420 if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good())
421 {
422 return new DicomString(boost::lexical_cast<std::string>(f));
423 }
424 else
425 {
426 return new DicomNullValue();
427 }
428 }
429 387
430 case EVR_FD: // float double-precision 388 case EVR_FD: // float double-precision
431 { 389 return new DcmFloatingPointDouble(key);
432 Float64 f;
433 if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good())
434 {
435 return new DicomString(boost::lexical_cast<std::string>(f));
436 }
437 else
438 {
439 return new DicomNullValue();
440 }
441 }
442 390
443 391
444 /** 392 /**
445 * Sequence types, should never occur at this point because of 393 * Sequence types, should never occur at this point.
446 * "element.isLeaf()".
447 **/ 394 **/
448 395
449 case EVR_SQ: // sequence of items 396 case EVR_SQ: // sequence of items
450 return new DicomNullValue; 397 throw OrthancException(ErrorCode_ParameterOutOfRange);
451 398
452 399
453 /** 400 /**
454 * Internal to DCMTK. 401 * Internal to DCMTK.
455 **/ 402 **/
456 403
457 case EVR_ox: // OB or OW depending on context 404 case EVR_ox: // OB or OW depending on context
458 case EVR_xs: // SS or US depending on context 405 case EVR_xs: // SS or US depending on context
459 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name) 406 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name)
460 case EVR_na: // na="not applicable", for data which has no VR 407 case EVR_na: // na="not applicable", for data which has no VR
469 case EVR_pixelItem: // used internally for pixel items in a compressed image 416 case EVR_pixelItem: // used internally for pixel items in a compressed image
470 case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR) 417 case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR)
471 case EVR_PixelData: // used internally for uncompressed pixeld data 418 case EVR_PixelData: // used internally for uncompressed pixeld data
472 case EVR_OverlayData: // used internally for overlay data 419 case EVR_OverlayData: // used internally for overlay data
473 case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR 420 case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR
421 default:
422 break;
423 }
424
425 throw OrthancException(ErrorCode_InternalError);
426 }
427
428
429
430 static void FillElementWithString(DcmElement& element,
431 const DicomTag& tag,
432 const std::string& value)
433 {
434 DcmTag key(tag.GetGroup(), tag.GetElement());
435 bool ok = false;
436
437 try
438 {
439 switch (key.getEVR())
440 {
441 // http://support.dcmtk.org/docs/dcvr_8h-source.html
442
443 /**
444 * TODO.
445 **/
446
447 case EVR_OB: // other byte
448 case EVR_OF: // other float
449 case EVR_OW: // other word
450 case EVR_AT: // attribute tag
451 throw OrthancException(ErrorCode_NotImplemented);
452
453 case EVR_UN: // unknown value representation
454 throw OrthancException(ErrorCode_ParameterOutOfRange);
455
456
457 /**
458 * String types.
459 **/
460
461 case EVR_DS: // decimal string
462 case EVR_IS: // integer string
463 case EVR_AS: // age string
464 case EVR_DA: // date string
465 case EVR_DT: // date time string
466 case EVR_TM: // time string
467 case EVR_AE: // application entity title
468 case EVR_CS: // code string
469 case EVR_SH: // short string
470 case EVR_LO: // long string
471 case EVR_ST: // short text
472 case EVR_LT: // long text
473 case EVR_UT: // unlimited text
474 case EVR_PN: // person name
475 case EVR_UI: // unique identifier
476 {
477 ok = element.putString(value.c_str()).good();
478 break;
479 }
480
481
482 /**
483 * Numerical types
484 **/
485
486 case EVR_SL: // signed long
487 {
488 ok = element.putSint32(boost::lexical_cast<Sint32>(value)).good();
489 break;
490 }
491
492 case EVR_SS: // signed short
493 {
494 ok = element.putSint16(boost::lexical_cast<Sint16>(value)).good();
495 break;
496 }
497
498 case EVR_UL: // unsigned long
499 {
500 ok = element.putUint32(boost::lexical_cast<Uint32>(value)).good();
501 break;
502 }
503
504 case EVR_US: // unsigned short
505 {
506 ok = element.putUint16(boost::lexical_cast<Uint16>(value)).good();
507 break;
508 }
509
510 case EVR_FL: // float single-precision
511 {
512 ok = element.putFloat32(boost::lexical_cast<float>(value)).good();
513 break;
514 }
515
516 case EVR_FD: // float double-precision
517 {
518 ok = element.putFloat64(boost::lexical_cast<double>(value)).good();
519 break;
520 }
521
522
523 /**
524 * Sequence types, should never occur at this point.
525 **/
526
527 case EVR_SQ: // sequence of items
528 {
529 ok = false;
530 break;
531 }
532
533
534 /**
535 * Internal to DCMTK.
536 **/
537
538 case EVR_ox: // OB or OW depending on context
539 case EVR_xs: // SS or US depending on context
540 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name)
541 case EVR_na: // na="not applicable", for data which has no VR
542 case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor
543 case EVR_item: // used internally for items
544 case EVR_metainfo: // used internally for meta info datasets
545 case EVR_dataset: // used internally for datasets
546 case EVR_fileFormat: // used internally for DICOM files
547 case EVR_dicomDir: // used internally for DICOMDIR objects
548 case EVR_dirRecord: // used internally for DICOMDIR records
549 case EVR_pixelSQ: // used internally for pixel sequences in a compressed image
550 case EVR_pixelItem: // used internally for pixel items in a compressed image
551 case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR)
552 case EVR_PixelData: // used internally for uncompressed pixeld data
553 case EVR_OverlayData: // used internally for overlay data
554 case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR
555 default:
556 break;
557 }
558 }
559 catch (boost::bad_lexical_cast&)
560 {
561 ok = false;
562 }
563
564 if (!ok)
565 {
566 throw OrthancException(ErrorCode_InternalError);
567 }
568 }
569
570
571 void ParsedDicomFile::Remove(const DicomTag& tag)
572 {
573 DcmTagKey key(tag.GetGroup(), tag.GetElement());
574
575 // TODO This call results in memory leaks inside DCMTK
576 file_->getDataset()->remove(key);
577 }
578
579
580
581 void ParsedDicomFile::Insert(const DicomTag& tag,
582 const std::string& value)
583 {
584 std::auto_ptr<DcmElement> element(CreateElementForTag(tag));
585 FillElementWithString(*element, tag, value);
586
587 if (!file_->getDataset()->insert(element.release(), false, false).good())
588 {
589 // This field already exists
590 throw OrthancException(ErrorCode_InternalError);
591 }
592 }
593
594
595 void ParsedDicomFile::ReplaceInternal(const DicomTag& tag,
596 const std::string& value,
597 bool insertOnAbsent)
598 {
599 DcmTagKey key(tag.GetGroup(), tag.GetElement());
600 DcmElement* element = NULL;
601
602 if (!file_->getDataset()->findAndGetElement(key, element).good() ||
603 element == NULL)
604 {
605 if (insertOnAbsent)
606 {
607 // This field does not exist, use "Insert()" instead
608 Insert(tag, value);
609 }
610 else
611 {
612 throw OrthancException(ErrorCode_InternalError);
613 }
614 }
615 else
616 {
617 FillElementWithString(*element, tag, value);
618 }
619 }
620
621
622 void ParsedDicomFile::Replace(const DicomTag& tag,
623 const std::string& value)
624 {
625 return ReplaceInternal(tag, value, false);
626 }
627
628 void ParsedDicomFile::InsertOrReplace(const DicomTag& tag,
629 const std::string& value)
630 {
631 return ReplaceInternal(tag, value, true);
632 }
633
634
635
636 void ParsedDicomFile::Answer(RestApiOutput& output)
637 {
638 std::string serialized;
639 if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, file_->getDataset()))
640 {
641 output.AnswerBuffer(serialized, "application/octet-stream");
642 }
643 }
644
645
646 void FromDcmtkBridge::Convert(DicomMap& target, DcmDataset& dataset)
647 {
648 target.Clear();
649 for (unsigned long i = 0; i < dataset.card(); i++)
650 {
651 DcmElement* element = dataset.getElement(i);
652 if (element && element->isLeaf())
653 {
654 target.SetValue(element->getTag().getGTag(),
655 element->getTag().getETag(),
656 ConvertLeafElement(*element));
657 }
658 }
659 }
660
661
662 DicomTag FromDcmtkBridge::GetTag(const DcmElement& element)
663 {
664 return DicomTag(element.getGTag(), element.getETag());
665 }
666
667
668 DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element)
669 {
670 if (!element.isLeaf())
671 {
672 throw OrthancException("Only applicable to leaf elements");
673 }
674
675 if (element.isaString())
676 {
677 char *c;
678 if (element.getString(c).good() &&
679 c != NULL)
680 {
681 std::string s(c);
682 std::string utf8 = Toolbox::ConvertToUtf8(s, "ISO-8859-1"); // TODO Parameter?
683 return new DicomString(utf8);
684 }
685 else
686 {
474 return new DicomNullValue; 687 return new DicomNullValue;
475 688 }
689 }
690
691 try
692 {
693 // http://support.dcmtk.org/docs/dcvr_8h-source.html
694 switch (element.getVR())
695 {
476 696
477 /** 697 /**
478 * Default case. 698 * TODO.
479 **/ 699 **/
480 700
481 default: 701 case EVR_DS: // decimal string
482 return new DicomNullValue; 702 case EVR_IS: // integer string
703 case EVR_OB: // other byte
704 case EVR_OF: // other float
705 case EVR_OW: // other word
706 case EVR_AS: // age string
707 case EVR_AT: // attribute tag
708 case EVR_DA: // date string
709 case EVR_DT: // date time string
710 case EVR_TM: // time string
711 case EVR_UN: // unknown value representation
712 return new DicomNullValue();
713
714
715 /**
716 * String types, should never happen at this point because of
717 * "element.isaString()".
718 **/
719
720 case EVR_AE: // application entity title
721 case EVR_CS: // code string
722 case EVR_SH: // short string
723 case EVR_LO: // long string
724 case EVR_ST: // short text
725 case EVR_LT: // long text
726 case EVR_UT: // unlimited text
727 case EVR_PN: // person name
728 case EVR_UI: // unique identifier
729 return new DicomNullValue();
730
731
732 /**
733 * Numerical types
734 **/
735
736 case EVR_SL: // signed long
737 {
738 Sint32 f;
739 if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good())
740 {
741 return new DicomString(boost::lexical_cast<std::string>(f));
742 }
743 else
744 {
745 return new DicomNullValue();
746 }
747 }
748
749 case EVR_SS: // signed short
750 {
751 Sint16 f;
752 if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good())
753 {
754 return new DicomString(boost::lexical_cast<std::string>(f));
755 }
756 else
757 {
758 return new DicomNullValue();
759 }
760 }
761
762 case EVR_UL: // unsigned long
763 {
764 Uint32 f;
765 if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good())
766 {
767 return new DicomString(boost::lexical_cast<std::string>(f));
768 }
769 else
770 {
771 return new DicomNullValue();
772 }
773 }
774
775 case EVR_US: // unsigned short
776 {
777 Uint16 f;
778 if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good())
779 {
780 return new DicomString(boost::lexical_cast<std::string>(f));
781 }
782 else
783 {
784 return new DicomNullValue();
785 }
786 }
787
788 case EVR_FL: // float single-precision
789 {
790 Float32 f;
791 if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good())
792 {
793 return new DicomString(boost::lexical_cast<std::string>(f));
794 }
795 else
796 {
797 return new DicomNullValue();
798 }
799 }
800
801 case EVR_FD: // float double-precision
802 {
803 Float64 f;
804 if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good())
805 {
806 return new DicomString(boost::lexical_cast<std::string>(f));
807 }
808 else
809 {
810 return new DicomNullValue();
811 }
812 }
813
814
815 /**
816 * Sequence types, should never occur at this point because of
817 * "element.isLeaf()".
818 **/
819
820 case EVR_SQ: // sequence of items
821 return new DicomNullValue;
822
823
824 /**
825 * Internal to DCMTK.
826 **/
827
828 case EVR_ox: // OB or OW depending on context
829 case EVR_xs: // SS or US depending on context
830 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name)
831 case EVR_na: // na="not applicable", for data which has no VR
832 case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor
833 case EVR_item: // used internally for items
834 case EVR_metainfo: // used internally for meta info datasets
835 case EVR_dataset: // used internally for datasets
836 case EVR_fileFormat: // used internally for DICOM files
837 case EVR_dicomDir: // used internally for DICOMDIR objects
838 case EVR_dirRecord: // used internally for DICOMDIR records
839 case EVR_pixelSQ: // used internally for pixel sequences in a compressed image
840 case EVR_pixelItem: // used internally for pixel items in a compressed image
841 case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR)
842 case EVR_PixelData: // used internally for uncompressed pixeld data
843 case EVR_OverlayData: // used internally for overlay data
844 case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR
845 return new DicomNullValue;
846
847
848 /**
849 * Default case.
850 **/
851
852 default:
853 return new DicomNullValue;
483 } 854 }
484 } 855 }
485 catch (boost::bad_lexical_cast) 856 catch (boost::bad_lexical_cast)
486 { 857 {
487 return new DicomNullValue; 858 return new DicomNullValue;
676 } 1047 }
677 1048
678 PixelFormat format; 1049 PixelFormat format;
679 switch (mode) 1050 switch (mode)
680 { 1051 {
681 case ImageExtractionMode_Preview: 1052 case ImageExtractionMode_Preview:
682 case ImageExtractionMode_UInt8: 1053 case ImageExtractionMode_UInt8:
683 format = PixelFormat_Grayscale8; 1054 format = PixelFormat_Grayscale8;
684 break; 1055 break;
685 1056
686 case ImageExtractionMode_UInt16: 1057 case ImageExtractionMode_UInt16:
687 format = PixelFormat_Grayscale16; 1058 format = PixelFormat_Grayscale16;
688 break; 1059 break;
689 1060
690 default: 1061 default:
691 throw OrthancException(ErrorCode_NotImplemented); 1062 throw OrthancException(ErrorCode_NotImplemented);
692 } 1063 }
693 1064
694 if (accessor.get() == NULL || 1065 if (accessor.get() == NULL ||
695 accessor->GetWidth() == 0 || 1066 accessor->GetWidth() == 0 ||
696 accessor->GetHeight() == 0) 1067 accessor->GetHeight() == 0)
700 } 1071 }
701 else 1072 else
702 { 1073 {
703 switch (mode) 1074 switch (mode)
704 { 1075 {
705 case ImageExtractionMode_Preview: 1076 case ImageExtractionMode_Preview:
706 ExtractPngImagePreview(result, *accessor); 1077 ExtractPngImagePreview(result, *accessor);
707 break; 1078 break;
708 1079
709 case ImageExtractionMode_UInt8: 1080 case ImageExtractionMode_UInt8:
710 ExtractPngImageTruncate<uint8_t>(result, *accessor, format); 1081 ExtractPngImageTruncate<uint8_t>(result, *accessor, format);
711 break; 1082 break;
712 1083
713 case ImageExtractionMode_UInt16: 1084 case ImageExtractionMode_UInt16:
714 ExtractPngImageTruncate<uint16_t>(result, *accessor, format); 1085 ExtractPngImageTruncate<uint16_t>(result, *accessor, format);
715 break; 1086 break;
716 1087
717 default: 1088 default:
718 throw OrthancException(ErrorCode_NotImplemented); 1089 throw OrthancException(ErrorCode_NotImplemented);
719 } 1090 }
720 } 1091 }
721 } 1092 }
722 1093
723 1094
826 { 1197 {
827 char uid[100]; 1198 char uid[100];
828 1199
829 switch (level) 1200 switch (level)
830 { 1201 {
831 case DicomRootLevel_Instance: 1202 case DicomRootLevel_Instance:
832 return dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT); 1203 return dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT);
833 1204
834 case DicomRootLevel_Series: 1205 case DicomRootLevel_Series:
835 return dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT); 1206 return dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT);
836 1207
837 case DicomRootLevel_Study: 1208 case DicomRootLevel_Study:
838 return dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT); 1209 return dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT);
839 1210
840 default: 1211 default:
841 throw OrthancException(ErrorCode_ParameterOutOfRange); 1212 throw OrthancException(ErrorCode_ParameterOutOfRange);
842 } 1213 }
843 } 1214 }
844 1215
845 bool FromDcmtkBridge::SaveToMemoryBuffer(std::string& buffer, 1216 bool FromDcmtkBridge::SaveToMemoryBuffer(std::string& buffer,
846 DcmDataset* dataSet) 1217 DcmDataset* dataSet)
887 OFstatic_cast(Uint32, /*opt_filepad*/ 0), 1258 OFstatic_cast(Uint32, /*opt_filepad*/ 0),
888 OFstatic_cast(Uint32, /*opt_itempad*/ 0), 1259 OFstatic_cast(Uint32, /*opt_itempad*/ 0),
889 (opt_useMetaheader) ? EWM_fileformat : EWM_dataset); 1260 (opt_useMetaheader) ? EWM_fileformat : EWM_dataset);
890 #endif 1261 #endif
891 } 1262 }
892
893
894 } 1263 }