Mercurial > hg > orthanc
comparison OrthancServer/FromDcmtkBridge.cpp @ 1744:b3de74dec2d5 db-changes
integration mainline->db-changes
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 26 Oct 2015 12:30:34 +0100 |
parents | df331354cea2 |
children | 57b9e6890482 |
comparison
equal
deleted
inserted
replaced
1729:54d78925cbb6 | 1744:b3de74dec2d5 |
---|---|
45 #include "../Core/Logging.h" | 45 #include "../Core/Logging.h" |
46 #include "../Core/Toolbox.h" | 46 #include "../Core/Toolbox.h" |
47 #include "../Core/OrthancException.h" | 47 #include "../Core/OrthancException.h" |
48 #include "../Core/Images/PngWriter.h" | 48 #include "../Core/Images/PngWriter.h" |
49 #include "../Core/Uuid.h" | 49 #include "../Core/Uuid.h" |
50 #include "../Core/DicomFormat/DicomString.h" | |
51 #include "../Core/DicomFormat/DicomNullValue.h" | |
52 #include "../Core/DicomFormat/DicomIntegerPixelAccessor.h" | 50 #include "../Core/DicomFormat/DicomIntegerPixelAccessor.h" |
53 | 51 |
54 #include <list> | 52 #include <list> |
55 #include <limits> | 53 #include <limits> |
56 | 54 |
330 DcmElement* element = dataset.getElement(i); | 328 DcmElement* element = dataset.getElement(i); |
331 if (element && element->isLeaf()) | 329 if (element && element->isLeaf()) |
332 { | 330 { |
333 target.SetValue(element->getTag().getGTag(), | 331 target.SetValue(element->getTag().getGTag(), |
334 element->getTag().getETag(), | 332 element->getTag().getETag(), |
335 ConvertLeafElement(*element, encoding)); | 333 ConvertLeafElement(*element, DicomToJsonFlags_Default, encoding)); |
336 } | 334 } |
337 } | 335 } |
338 } | 336 } |
339 | 337 |
340 | 338 |
362 #endif | 360 #endif |
363 } | 361 } |
364 | 362 |
365 | 363 |
366 DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element, | 364 DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element, |
365 DicomToJsonFlags flags, | |
367 Encoding encoding) | 366 Encoding encoding) |
368 { | 367 { |
369 if (!element.isLeaf()) | 368 if (!element.isLeaf()) |
370 { | 369 { |
371 // This function is only applicable to leaf elements | 370 // This function is only applicable to leaf elements |
377 char *c; | 376 char *c; |
378 if (element.getString(c).good()) | 377 if (element.getString(c).good()) |
379 { | 378 { |
380 if (c == NULL) // This case corresponds to the empty string | 379 if (c == NULL) // This case corresponds to the empty string |
381 { | 380 { |
382 return new DicomString(""); | 381 return new DicomValue("", false); |
383 } | 382 } |
384 else | 383 else |
385 { | 384 { |
386 std::string s(c); | 385 std::string s(c); |
387 std::string utf8 = Toolbox::ConvertToUtf8(s, encoding); | 386 std::string utf8 = Toolbox::ConvertToUtf8(s, encoding); |
388 return new DicomString(utf8); | 387 return new DicomValue(utf8, false); |
389 } | 388 } |
390 } | 389 } |
391 else | 390 else |
392 { | 391 { |
393 return new DicomNullValue; | 392 return new DicomValue; |
394 } | 393 } |
395 } | 394 } |
396 | 395 |
397 try | 396 try |
398 { | 397 { |
399 // http://support.dcmtk.org/docs/dcvr_8h-source.html | 398 // http://support.dcmtk.org/docs/dcvr_8h-source.html |
400 switch (element.getVR()) | 399 switch (element.getVR()) |
401 { | 400 { |
402 | 401 |
403 /** | 402 /** |
404 * TODO. | 403 * Deal with binary data (including PixelData). |
405 **/ | 404 **/ |
406 | 405 |
407 case EVR_OB: // other byte | 406 case EVR_OB: // other byte |
408 case EVR_OF: // other float | 407 case EVR_OF: // other float |
409 case EVR_OW: // other word | 408 case EVR_OW: // other word |
410 case EVR_UN: // unknown value representation | 409 case EVR_UN: // unknown value representation |
411 return new DicomNullValue; | 410 case EVR_ox: // OB or OW depending on context |
411 { | |
412 if (!(flags & DicomToJsonFlags_ConvertBinaryToNull)) | |
413 { | |
414 Uint8* data = NULL; | |
415 if (element.getUint8Array(data) == EC_Normal) | |
416 { | |
417 return new DicomValue(reinterpret_cast<const char*>(data), element.getLength(), true); | |
418 } | |
419 } | |
420 | |
421 return new DicomValue; | |
422 } | |
412 | 423 |
413 /** | 424 /** |
414 * String types, should never happen at this point because of | 425 * String types, should never happen at this point because of |
415 * "element.isaString()". | 426 * "element.isaString()". |
416 **/ | 427 **/ |
428 case EVR_ST: // short text | 439 case EVR_ST: // short text |
429 case EVR_LT: // long text | 440 case EVR_LT: // long text |
430 case EVR_UT: // unlimited text | 441 case EVR_UT: // unlimited text |
431 case EVR_PN: // person name | 442 case EVR_PN: // person name |
432 case EVR_UI: // unique identifier | 443 case EVR_UI: // unique identifier |
433 return new DicomNullValue; | 444 return new DicomValue; |
434 | 445 |
435 | 446 |
436 /** | 447 /** |
437 * Numberic types | 448 * Numberic types |
438 **/ | 449 **/ |
439 | 450 |
440 case EVR_SL: // signed long | 451 case EVR_SL: // signed long |
441 { | 452 { |
442 Sint32 f; | 453 Sint32 f; |
443 if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good()) | 454 if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good()) |
444 return new DicomString(boost::lexical_cast<std::string>(f)); | 455 return new DicomValue(boost::lexical_cast<std::string>(f), false); |
445 else | 456 else |
446 return new DicomNullValue; | 457 return new DicomValue; |
447 } | 458 } |
448 | 459 |
449 case EVR_SS: // signed short | 460 case EVR_SS: // signed short |
450 { | 461 { |
451 Sint16 f; | 462 Sint16 f; |
452 if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good()) | 463 if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good()) |
453 return new DicomString(boost::lexical_cast<std::string>(f)); | 464 return new DicomValue(boost::lexical_cast<std::string>(f), false); |
454 else | 465 else |
455 return new DicomNullValue; | 466 return new DicomValue; |
456 } | 467 } |
457 | 468 |
458 case EVR_UL: // unsigned long | 469 case EVR_UL: // unsigned long |
459 { | 470 { |
460 Uint32 f; | 471 Uint32 f; |
461 if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good()) | 472 if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good()) |
462 return new DicomString(boost::lexical_cast<std::string>(f)); | 473 return new DicomValue(boost::lexical_cast<std::string>(f), false); |
463 else | 474 else |
464 return new DicomNullValue; | 475 return new DicomValue; |
465 } | 476 } |
466 | 477 |
467 case EVR_US: // unsigned short | 478 case EVR_US: // unsigned short |
468 { | 479 { |
469 Uint16 f; | 480 Uint16 f; |
470 if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good()) | 481 if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good()) |
471 return new DicomString(boost::lexical_cast<std::string>(f)); | 482 return new DicomValue(boost::lexical_cast<std::string>(f), false); |
472 else | 483 else |
473 return new DicomNullValue; | 484 return new DicomValue; |
474 } | 485 } |
475 | 486 |
476 case EVR_FL: // float single-precision | 487 case EVR_FL: // float single-precision |
477 { | 488 { |
478 Float32 f; | 489 Float32 f; |
479 if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good()) | 490 if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good()) |
480 return new DicomString(boost::lexical_cast<std::string>(f)); | 491 return new DicomValue(boost::lexical_cast<std::string>(f), false); |
481 else | 492 else |
482 return new DicomNullValue; | 493 return new DicomValue; |
483 } | 494 } |
484 | 495 |
485 case EVR_FD: // float double-precision | 496 case EVR_FD: // float double-precision |
486 { | 497 { |
487 Float64 f; | 498 Float64 f; |
488 if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good()) | 499 if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good()) |
489 return new DicomString(boost::lexical_cast<std::string>(f)); | 500 return new DicomValue(boost::lexical_cast<std::string>(f), false); |
490 else | 501 else |
491 return new DicomNullValue; | 502 return new DicomValue; |
492 } | 503 } |
493 | 504 |
494 | 505 |
495 /** | 506 /** |
496 * Attribute tag. | 507 * Attribute tag. |
500 { | 511 { |
501 DcmTagKey tag; | 512 DcmTagKey tag; |
502 if (dynamic_cast<DcmAttributeTag&>(element).getTagVal(tag, 0).good()) | 513 if (dynamic_cast<DcmAttributeTag&>(element).getTagVal(tag, 0).good()) |
503 { | 514 { |
504 DicomTag t(tag.getGroup(), tag.getElement()); | 515 DicomTag t(tag.getGroup(), tag.getElement()); |
505 return new DicomString(t.Format()); | 516 return new DicomValue(t.Format(), false); |
506 } | 517 } |
507 else | 518 else |
508 { | 519 { |
509 return new DicomNullValue; | 520 return new DicomValue; |
510 } | 521 } |
511 } | 522 } |
512 | 523 |
513 | 524 |
514 /** | 525 /** |
515 * Sequence types, should never occur at this point because of | 526 * Sequence types, should never occur at this point because of |
516 * "element.isLeaf()". | 527 * "element.isLeaf()". |
517 **/ | 528 **/ |
518 | 529 |
519 case EVR_SQ: // sequence of items | 530 case EVR_SQ: // sequence of items |
520 return new DicomNullValue; | 531 return new DicomValue; |
521 | 532 |
522 | 533 |
523 /** | 534 /** |
524 * Internal to DCMTK. | 535 * Internal to DCMTK. |
525 **/ | 536 **/ |
526 | 537 |
527 case EVR_ox: // OB or OW depending on context | |
528 case EVR_xs: // SS or US depending on context | 538 case EVR_xs: // SS or US depending on context |
529 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name) | 539 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name) |
530 case EVR_na: // na="not applicable", for data which has no VR | 540 case EVR_na: // na="not applicable", for data which has no VR |
531 case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor | 541 case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor |
532 case EVR_item: // used internally for items | 542 case EVR_item: // used internally for items |
539 case EVR_pixelItem: // used internally for pixel items in a compressed image | 549 case EVR_pixelItem: // used internally for pixel items in a compressed image |
540 case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR) | 550 case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR) |
541 case EVR_PixelData: // used internally for uncompressed pixeld data | 551 case EVR_PixelData: // used internally for uncompressed pixeld data |
542 case EVR_OverlayData: // used internally for overlay data | 552 case EVR_OverlayData: // used internally for overlay data |
543 case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR | 553 case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR |
544 return new DicomNullValue; | 554 return new DicomValue; |
545 | 555 |
546 | 556 |
547 /** | 557 /** |
548 * Default case. | 558 * Default case. |
549 **/ | 559 **/ |
550 | 560 |
551 default: | 561 default: |
552 return new DicomNullValue; | 562 return new DicomValue; |
553 } | 563 } |
554 } | 564 } |
555 catch (boost::bad_lexical_cast) | 565 catch (boost::bad_lexical_cast) |
556 { | 566 { |
557 return new DicomNullValue; | 567 return new DicomValue; |
558 } | 568 } |
559 catch (std::bad_cast) | 569 catch (std::bad_cast) |
560 { | 570 { |
561 return new DicomNullValue; | 571 return new DicomValue; |
562 } | 572 } |
563 } | 573 } |
564 | 574 |
565 | 575 |
566 static Json::Value& PrepareNode(Json::Value& parent, | 576 static Json::Value& PrepareNode(Json::Value& parent, |
620 | 630 |
621 | 631 |
622 static void LeafValueToJson(Json::Value& target, | 632 static void LeafValueToJson(Json::Value& target, |
623 const DicomValue& value, | 633 const DicomValue& value, |
624 DicomToJsonFormat format, | 634 DicomToJsonFormat format, |
635 DicomToJsonFlags flags, | |
625 unsigned int maxStringLength) | 636 unsigned int maxStringLength) |
626 { | 637 { |
627 std::string content = value.AsString(); | 638 Json::Value* targetValue = NULL; |
639 Json::Value* targetType = NULL; | |
628 | 640 |
629 switch (format) | 641 switch (format) |
630 { | 642 { |
631 case DicomToJsonFormat_Short: | 643 case DicomToJsonFormat_Short: |
632 case DicomToJsonFormat_Simple: | 644 case DicomToJsonFormat_Simple: |
633 { | 645 { |
634 assert(target.type() == Json::nullValue); | 646 assert(target.type() == Json::nullValue); |
635 | 647 targetValue = ⌖ |
636 if (!value.IsNull() && | |
637 (maxStringLength == 0 || | |
638 content.size() <= maxStringLength)) | |
639 { | |
640 target = content; | |
641 } | |
642 | |
643 break; | 648 break; |
644 } | 649 } |
645 | 650 |
646 case DicomToJsonFormat_Full: | 651 case DicomToJsonFormat_Full: |
647 { | 652 { |
648 assert(target.type() == Json::objectValue); | 653 assert(target.type() == Json::objectValue); |
649 | 654 target["Value"] = Json::nullValue; |
650 if (value.IsNull()) | 655 target["Type"] = Json::nullValue; |
651 { | 656 targetType = &target["Type"]; |
652 target["Type"] = "Null"; | 657 targetValue = &target["Value"]; |
653 target["Value"] = Json::nullValue; | |
654 } | |
655 else | |
656 { | |
657 if (maxStringLength == 0 || | |
658 content.size() <= maxStringLength) | |
659 { | |
660 target["Type"] = "String"; | |
661 target["Value"] = content; | |
662 } | |
663 else | |
664 { | |
665 target["Type"] = "TooLong"; | |
666 target["Value"] = Json::nullValue; | |
667 } | |
668 } | |
669 break; | 658 break; |
670 } | 659 } |
671 | 660 |
672 default: | 661 default: |
673 throw OrthancException(ErrorCode_ParameterOutOfRange); | 662 throw OrthancException(ErrorCode_ParameterOutOfRange); |
663 } | |
664 | |
665 assert(targetValue != NULL); | |
666 assert(targetValue->type() == Json::nullValue); | |
667 assert(targetType == NULL || targetType->type() == Json::nullValue); | |
668 | |
669 if (value.IsNull()) | |
670 { | |
671 if (targetType != NULL) | |
672 { | |
673 *targetType = "Null"; | |
674 } | |
675 } | |
676 else if (value.IsBinary()) | |
677 { | |
678 if (flags & DicomToJsonFlags_ConvertBinaryToAscii) | |
679 { | |
680 *targetValue = Toolbox::ConvertToAscii(value.GetContent()); | |
681 } | |
682 else | |
683 { | |
684 std::string s; | |
685 value.FormatDataUriScheme(s); | |
686 *targetValue = s; | |
687 } | |
688 | |
689 if (targetType != NULL) | |
690 { | |
691 *targetType = "Binary"; | |
692 } | |
693 } | |
694 else if (maxStringLength == 0 || | |
695 value.GetContent().size() <= maxStringLength) | |
696 { | |
697 *targetValue = value.GetContent(); | |
698 | |
699 if (targetType != NULL) | |
700 { | |
701 *targetType = "String"; | |
702 } | |
703 } | |
704 else | |
705 { | |
706 if (targetType != NULL) | |
707 { | |
708 *targetType = "TooLong"; | |
709 } | |
674 } | 710 } |
675 } | 711 } |
676 | 712 |
677 | 713 |
678 static void DatasetToJson(Json::Value& parent, | 714 static void DatasetToJson(Json::Value& parent, |
679 DcmItem& item, | 715 DcmItem& item, |
680 DicomToJsonFormat format, | 716 DicomToJsonFormat format, |
717 DicomToJsonFlags flags, | |
681 unsigned int maxStringLength, | 718 unsigned int maxStringLength, |
682 Encoding encoding); | 719 Encoding encoding); |
683 | 720 |
684 | 721 |
685 void FromDcmtkBridge::ToJson(Json::Value& parent, | 722 void FromDcmtkBridge::ToJson(Json::Value& parent, |
686 DcmElement& element, | 723 DcmElement& element, |
687 DicomToJsonFormat format, | 724 DicomToJsonFormat format, |
725 DicomToJsonFlags flags, | |
688 unsigned int maxStringLength, | 726 unsigned int maxStringLength, |
689 Encoding encoding) | 727 Encoding encoding) |
690 { | 728 { |
691 if (parent.type() == Json::nullValue) | 729 if (parent.type() == Json::nullValue) |
692 { | 730 { |
696 assert(parent.type() == Json::objectValue); | 734 assert(parent.type() == Json::objectValue); |
697 Json::Value& target = PrepareNode(parent, element, format); | 735 Json::Value& target = PrepareNode(parent, element, format); |
698 | 736 |
699 if (element.isLeaf()) | 737 if (element.isLeaf()) |
700 { | 738 { |
701 std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(element, encoding)); | 739 std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(element, flags, encoding)); |
702 LeafValueToJson(target, *v, format, maxStringLength); | 740 LeafValueToJson(target, *v, format, flags, maxStringLength); |
703 } | 741 } |
704 else | 742 else |
705 { | 743 { |
706 assert(target.type() == Json::nullValue); | 744 assert(target.type() == Json::nullValue); |
707 target = Json::arrayValue; | 745 target = Json::arrayValue; |
713 | 751 |
714 for (unsigned long i = 0; i < sequence.card(); i++) | 752 for (unsigned long i = 0; i < sequence.card(); i++) |
715 { | 753 { |
716 DcmItem* child = sequence.getItem(i); | 754 DcmItem* child = sequence.getItem(i); |
717 Json::Value& v = target.append(Json::objectValue); | 755 Json::Value& v = target.append(Json::objectValue); |
718 DatasetToJson(v, *child, format, maxStringLength, encoding); | 756 DatasetToJson(v, *child, format, flags, maxStringLength, encoding); |
719 } | 757 } |
720 } | 758 } |
721 } | 759 } |
722 | 760 |
723 | 761 |
724 static void DatasetToJson(Json::Value& parent, | 762 static void DatasetToJson(Json::Value& parent, |
725 DcmItem& item, | 763 DcmItem& item, |
726 DicomToJsonFormat format, | 764 DicomToJsonFormat format, |
765 DicomToJsonFlags flags, | |
727 unsigned int maxStringLength, | 766 unsigned int maxStringLength, |
728 Encoding encoding) | 767 Encoding encoding) |
729 { | 768 { |
730 assert(parent.type() == Json::objectValue); | 769 assert(parent.type() == Json::objectValue); |
731 | 770 |
732 for (unsigned long i = 0; i < item.card(); i++) | 771 for (unsigned long i = 0; i < item.card(); i++) |
733 { | 772 { |
734 DcmElement* element = item.getElement(i); | 773 DcmElement* element = item.getElement(i); |
735 FromDcmtkBridge::ToJson(parent, *element, format, maxStringLength, encoding); | 774 if (element == NULL) |
775 { | |
776 throw OrthancException(ErrorCode_InternalError); | |
777 } | |
778 | |
779 if (!(flags & DicomToJsonFlags_IncludePrivateTags) && | |
780 element->getTag().isPrivate()) | |
781 { | |
782 continue; | |
783 } | |
784 | |
785 if (!(flags & DicomToJsonFlags_IncludeUnknownTags)) | |
786 { | |
787 DictionaryLocker locker; | |
788 if (locker->findEntry(element->getTag(), NULL) == NULL) | |
789 { | |
790 continue; | |
791 } | |
792 } | |
793 | |
794 DcmEVR evr = element->getTag().getEVR(); | |
795 if (evr == EVR_OB || | |
796 evr == EVR_OF || | |
797 evr == EVR_OW || | |
798 evr == EVR_UN || | |
799 evr == EVR_ox) | |
800 { | |
801 // This is a binary tag | |
802 DicomTag tag(FromDcmtkBridge::Convert(element->getTag())); | |
803 | |
804 if ((tag == DICOM_TAG_PIXEL_DATA && !(flags & DicomToJsonFlags_IncludePixelData)) || | |
805 (tag != DICOM_TAG_PIXEL_DATA && !(flags & DicomToJsonFlags_IncludeBinary))) | |
806 { | |
807 continue; | |
808 } | |
809 } | |
810 | |
811 FromDcmtkBridge::ToJson(parent, *element, format, flags, maxStringLength, encoding); | |
736 } | 812 } |
737 } | 813 } |
738 | 814 |
739 | 815 |
740 void FromDcmtkBridge::ToJson(Json::Value& target, | 816 void FromDcmtkBridge::ToJson(Json::Value& target, |
741 DcmDataset& dataset, | 817 DcmDataset& dataset, |
742 DicomToJsonFormat format, | 818 DicomToJsonFormat format, |
819 DicomToJsonFlags flags, | |
743 unsigned int maxStringLength) | 820 unsigned int maxStringLength) |
744 { | 821 { |
745 target = Json::objectValue; | 822 target = Json::objectValue; |
746 DatasetToJson(target, dataset, format, maxStringLength, DetectEncoding(dataset)); | 823 DatasetToJson(target, dataset, format, flags, maxStringLength, DetectEncoding(dataset)); |
747 } | 824 } |
748 | 825 |
749 | 826 |
750 std::string FromDcmtkBridge::GetName(const DicomTag& t) | 827 std::string FromDcmtkBridge::GetName(const DicomTag& t) |
751 { | 828 { |
839 DcmTag tmp(tag.GetGroup(), tag.GetElement()); | 916 DcmTag tmp(tag.GetGroup(), tag.GetElement()); |
840 return tmp.isUnknownVR(); | 917 return tmp.isUnknownVR(); |
841 } | 918 } |
842 | 919 |
843 | 920 |
844 void FromDcmtkBridge::Print(FILE* fp, const DicomMap& m) | |
845 { | |
846 for (DicomMap::Map::const_iterator | |
847 it = m.map_.begin(); it != m.map_.end(); ++it) | |
848 { | |
849 DicomTag t = it->first; | |
850 std::string s = it->second->AsString(); | |
851 fprintf(fp, "0x%04x 0x%04x (%s) [%s]\n", t.GetGroup(), t.GetElement(), GetName(t).c_str(), s.c_str()); | |
852 } | |
853 } | |
854 | |
855 | |
856 void FromDcmtkBridge::ToJson(Json::Value& result, | 921 void FromDcmtkBridge::ToJson(Json::Value& result, |
857 const DicomMap& values, | 922 const DicomMap& values, |
858 bool simplify) | 923 bool simplify) |
859 { | 924 { |
860 if (result.type() != Json::objectValue) | 925 if (result.type() != Json::objectValue) |
867 for (DicomMap::Map::const_iterator | 932 for (DicomMap::Map::const_iterator |
868 it = values.map_.begin(); it != values.map_.end(); ++it) | 933 it = values.map_.begin(); it != values.map_.end(); ++it) |
869 { | 934 { |
870 if (simplify) | 935 if (simplify) |
871 { | 936 { |
872 result[GetName(it->first)] = it->second->AsString(); | 937 if (it->second->IsNull()) |
938 { | |
939 result[GetName(it->first)] = Json::nullValue; | |
940 } | |
941 else | |
942 { | |
943 // TODO IsBinary | |
944 result[GetName(it->first)] = it->second->GetContent(); | |
945 } | |
873 } | 946 } |
874 else | 947 else |
875 { | 948 { |
876 Json::Value value = Json::objectValue; | 949 Json::Value value = Json::objectValue; |
877 | 950 |
882 value["Type"] = "Null"; | 955 value["Type"] = "Null"; |
883 value["Value"] = Json::nullValue; | 956 value["Value"] = Json::nullValue; |
884 } | 957 } |
885 else | 958 else |
886 { | 959 { |
960 // TODO IsBinary | |
887 value["Type"] = "String"; | 961 value["Type"] = "String"; |
888 value["Value"] = it->second->AsString(); | 962 value["Value"] = it->second->GetContent(); |
889 } | 963 } |
890 | 964 |
891 result[it->first.Format()] = value; | 965 result[it->first.Format()] = value; |
892 } | 966 } |
893 } | 967 } |
999 } | 1073 } |
1000 | 1074 |
1001 | 1075 |
1002 static bool IsBinaryTag(const DcmTag& key) | 1076 static bool IsBinaryTag(const DcmTag& key) |
1003 { | 1077 { |
1004 return key.isPrivate() || key.isUnknownVR(); | 1078 return (key.isPrivate() || |
1079 key.isUnknownVR() || | |
1080 key.getEVR() == EVR_OB || | |
1081 key.getEVR() == EVR_OF || | |
1082 key.getEVR() == EVR_OW || | |
1083 key.getEVR() == EVR_UN || | |
1084 key.getEVR() == EVR_ox); | |
1005 } | 1085 } |
1006 | 1086 |
1007 | 1087 |
1008 DcmElement* FromDcmtkBridge::CreateElementForTag(const DicomTag& tag) | 1088 DcmElement* FromDcmtkBridge::CreateElementForTag(const DicomTag& tag) |
1009 { | 1089 { |
1017 switch (key.getEVR()) | 1097 switch (key.getEVR()) |
1018 { | 1098 { |
1019 // http://support.dcmtk.org/docs/dcvr_8h-source.html | 1099 // http://support.dcmtk.org/docs/dcvr_8h-source.html |
1020 | 1100 |
1021 /** | 1101 /** |
1022 * TODO. | 1102 * Binary types, handled above |
1023 **/ | 1103 **/ |
1024 | 1104 |
1025 case EVR_OB: // other byte | 1105 case EVR_OB: // other byte |
1026 case EVR_OF: // other float | 1106 case EVR_OF: // other float |
1027 case EVR_OW: // other word | 1107 case EVR_OW: // other word |
1028 case EVR_AT: // attribute tag | |
1029 throw OrthancException(ErrorCode_NotImplemented); | |
1030 | |
1031 case EVR_UN: // unknown value representation | 1108 case EVR_UN: // unknown value representation |
1032 throw OrthancException(ErrorCode_ParameterOutOfRange); | 1109 case EVR_ox: // OB or OW depending on context |
1110 throw OrthancException(ErrorCode_InternalError); | |
1033 | 1111 |
1034 | 1112 |
1035 /** | 1113 /** |
1036 * String types. | 1114 * String types. |
1037 * http://support.dcmtk.org/docs/classDcmByteString.html | 1115 * http://support.dcmtk.org/docs/classDcmByteString.html |
1113 case EVR_SQ: // sequence of items | 1191 case EVR_SQ: // sequence of items |
1114 throw OrthancException(ErrorCode_ParameterOutOfRange); | 1192 throw OrthancException(ErrorCode_ParameterOutOfRange); |
1115 | 1193 |
1116 | 1194 |
1117 /** | 1195 /** |
1196 * TODO | |
1197 **/ | |
1198 | |
1199 case EVR_AT: // attribute tag | |
1200 throw OrthancException(ErrorCode_NotImplemented); | |
1201 | |
1202 | |
1203 /** | |
1118 * Internal to DCMTK. | 1204 * Internal to DCMTK. |
1119 **/ | 1205 **/ |
1120 | 1206 |
1121 case EVR_ox: // OB or OW depending on context | |
1122 case EVR_xs: // SS or US depending on context | 1207 case EVR_xs: // SS or US depending on context |
1123 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name) | 1208 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name) |
1124 case EVR_na: // na="not applicable", for data which has no VR | 1209 case EVR_na: // na="not applicable", for data which has no VR |
1125 case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor | 1210 case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor |
1126 case EVR_item: // used internally for items | 1211 case EVR_item: // used internally for items |