comparison OrthancServer/ParsedDicomFile.cpp @ 1693:558b25228a23

creation of tag hierarchy from json
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 08 Oct 2015 13:45:33 +0200
parents 26083d84d237
children 06d579e82bb8
comparison
equal deleted inserted replaced
1692:4eaf164dd574 1693:558b25228a23
135 #include <dcmtk/dcmdata/dcpxitem.h> 135 #include <dcmtk/dcmdata/dcpxitem.h>
136 136
137 137
138 #include <boost/math/special_functions/round.hpp> 138 #include <boost/math/special_functions/round.hpp>
139 #include <dcmtk/dcmdata/dcostrmb.h> 139 #include <dcmtk/dcmdata/dcostrmb.h>
140 #include <boost/algorithm/string/predicate.hpp>
140 141
141 142
142 static const char* CONTENT_TYPE_OCTET_STREAM = "application/octet-stream"; 143 static const char* CONTENT_TYPE_OCTET_STREAM = "application/octet-stream";
143 144
144 145
577 } 578 }
578 } 579 }
579 } 580 }
580 581
581 582
583 static void InsertInternal(DcmDataset& dicom,
584 DcmElement* element)
585 {
586 OFCondition cond = dicom.insert(element, false, false);
587 if (!cond.good())
588 {
589 // This field already exists
590 delete element;
591 throw OrthancException(ErrorCode_InternalError);
592 }
593 }
594
595
582 void ParsedDicomFile::Insert(const DicomTag& tag, 596 void ParsedDicomFile::Insert(const DicomTag& tag,
583 const std::string& value) 597 const std::string& value)
584 { 598 {
585 OFCondition cond; 599 std::auto_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag));
586 600 FromDcmtkBridge::FillElementWithString(*element, tag, value, false);
587 if (FromDcmtkBridge::IsPrivateTag(tag) || 601 InsertInternal(*pimpl_->file_->getDataset(), element.release());
588 FromDcmtkBridge::IsUnknownTag(tag)) 602 }
589 { 603
590 // This is a private tag 604
591 // http://support.dcmtk.org/redmine/projects/dcmtk/wiki/howto_addprivatedata 605 void ParsedDicomFile::Insert(const DicomTag& tag,
592 606 const Json::Value& value,
593 DcmTag key(tag.GetGroup(), tag.GetElement(), EVR_OB); 607 bool decodeBinaryTags)
594 cond = pimpl_->file_->getDataset()->putAndInsertUint8Array 608 {
595 (key, (const Uint8*) value.c_str(), value.size(), false); 609 std::auto_ptr<DcmElement> element(FromDcmtkBridge::FromJson(tag, value, decodeBinaryTags));
596 } 610 InsertInternal(*pimpl_->file_->getDataset(), element.release());
597 else 611 }
598 { 612
599 std::auto_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag)); 613
600 FromDcmtkBridge::FillElementWithString(*element, tag, value, false); 614 static void ReplaceInternal(DcmDataset& dicom,
601 615 std::auto_ptr<DcmElement>& element,
602 cond = pimpl_->file_->getDataset()->insert(element.release(), false, false); 616 DicomReplaceMode mode)
603 } 617 {
604 618 const DcmTagKey& tag = element->getTag();
605 if (!cond.good()) 619
606 { 620 if (!dicom.findAndDeleteElement(tag).good())
607 // This field already exists
608 throw OrthancException(ErrorCode_InternalError);
609 }
610 }
611
612
613 void ParsedDicomFile::Replace(const DicomTag& tag,
614 const std::string& value,
615 DicomReplaceMode mode)
616 {
617 DcmTagKey key(tag.GetGroup(), tag.GetElement());
618 DcmElement* element = NULL;
619
620 if (!pimpl_->file_->getDataset()->findAndGetElement(key, element).good() ||
621 element == NULL)
622 { 621 {
623 // This field does not exist, act wrt. the specified "mode" 622 // This field does not exist, act wrt. the specified "mode"
624 switch (mode) 623 switch (mode)
625 { 624 {
626 case DicomReplaceMode_InsertIfAbsent: 625 case DicomReplaceMode_InsertIfAbsent:
627 Insert(tag, value);
628 break; 626 break;
629 627
630 case DicomReplaceMode_ThrowIfAbsent: 628 case DicomReplaceMode_ThrowIfAbsent:
631 throw OrthancException(ErrorCode_InexistentItem); 629 throw OrthancException(ErrorCode_InexistentItem);
632 630
633 case DicomReplaceMode_IgnoreIfAbsent: 631 case DicomReplaceMode_IgnoreIfAbsent:
634 return; 632 return;
635 } 633 }
636 } 634 }
637 else 635
638 { 636 // Either the tag was not existing, or the replace mode was set to
639 FromDcmtkBridge::FillElementWithString(*element, tag, value, false); 637 // "InsertIfAbsent"
640 } 638 InsertInternal(dicom, element.release());
641 639 }
640
641
642 void ParsedDicomFile::UpdateStorageUid(const DicomTag& tag,
643 const std::string& value,
644 bool decodeBinaryTags)
645 {
646 if (tag != DICOM_TAG_SOP_CLASS_UID &&
647 tag != DICOM_TAG_SOP_INSTANCE_UID)
648 {
649 return;
650 }
651
652 std::string binary;
653 const std::string* decoded = &value;
654
655 if (decodeBinaryTags &&
656 boost::starts_with(value, "data:application/octet-stream;base64,"))
657 {
658 std::string mime;
659 Toolbox::DecodeDataUriScheme(mime, binary, value);
660 decoded = &binary;
661 }
642 662
643 /** 663 /**
644 * dcmodify will automatically correct 'Media Storage SOP Class 664 * dcmodify will automatically correct 'Media Storage SOP Class
645 * UID' and 'Media Storage SOP Instance UID' in the metaheader, if 665 * UID' and 'Media Storage SOP Instance UID' in the metaheader, if
646 * you make changes to the related tags in the dataset ('SOP Class 666 * you make changes to the related tags in the dataset ('SOP Class
649 * option. 669 * option.
650 **/ 670 **/
651 671
652 if (tag == DICOM_TAG_SOP_CLASS_UID) 672 if (tag == DICOM_TAG_SOP_CLASS_UID)
653 { 673 {
654 Replace(DICOM_TAG_MEDIA_STORAGE_SOP_CLASS_UID, value, DicomReplaceMode_InsertIfAbsent); 674 Replace(DICOM_TAG_MEDIA_STORAGE_SOP_CLASS_UID, *decoded, DicomReplaceMode_InsertIfAbsent);
655 } 675 }
656 676
657 if (tag == DICOM_TAG_SOP_INSTANCE_UID) 677 if (tag == DICOM_TAG_SOP_INSTANCE_UID)
658 { 678 {
659 Replace(DICOM_TAG_MEDIA_STORAGE_SOP_INSTANCE_UID, value, DicomReplaceMode_InsertIfAbsent); 679 Replace(DICOM_TAG_MEDIA_STORAGE_SOP_INSTANCE_UID, *decoded, DicomReplaceMode_InsertIfAbsent);
680 }
681 }
682
683
684 void ParsedDicomFile::Replace(const DicomTag& tag,
685 const std::string& value,
686 DicomReplaceMode mode)
687 {
688 std::auto_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag));
689 FromDcmtkBridge::FillElementWithString(*element, tag, value, false);
690 ReplaceInternal(*pimpl_->file_->getDataset(), element, mode);
691 UpdateStorageUid(tag, value, false);
692 }
693
694
695 void ParsedDicomFile::Replace(const DicomTag& tag,
696 const Json::Value& value,
697 bool decodeBinaryTags,
698 DicomReplaceMode mode)
699 {
700 std::auto_ptr<DcmElement> element(FromDcmtkBridge::FromJson(tag, value, decodeBinaryTags));
701 ReplaceInternal(*pimpl_->file_->getDataset(), element, mode);
702
703 if (tag == DICOM_TAG_SOP_CLASS_UID ||
704 tag == DICOM_TAG_SOP_INSTANCE_UID)
705 {
706 if (value.type() != Json::stringValue)
707 {
708 throw OrthancException(ErrorCode_BadParameterType);
709 }
710
711 UpdateStorageUid(tag, value.asString(), decodeBinaryTags);
660 } 712 }
661 } 713 }
662 714
663 715
664 void ParsedDicomFile::Answer(RestApiOutput& output) 716 void ParsedDicomFile::Answer(RestApiOutput& output)
863 { 915 {
864 EmbedPdf(content); 916 EmbedPdf(content);
865 } 917 }
866 else 918 else
867 { 919 {
868 LOG(ERROR) << "Unsupported MIME type for the content of a new DICOM file"; 920 LOG(ERROR) << "Unsupported MIME type for the content of a new DICOM file: " << mime;
869 throw OrthancException(ErrorCode_NotImplemented); 921 throw OrthancException(ErrorCode_NotImplemented);
870 } 922 }
871 } 923 }
872 924
873 925