comparison OrthancServer/ParsedDicomFile.cpp @ 1695:18c02c6987d5

fix for encodings
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 08 Oct 2015 14:34:19 +0200
parents 06d579e82bb8
children 8ca0e89798b2
comparison
equal deleted inserted replaced
1694:06d579e82bb8 1695:18c02c6987d5
147 namespace Orthanc 147 namespace Orthanc
148 { 148 {
149 struct ParsedDicomFile::PImpl 149 struct ParsedDicomFile::PImpl
150 { 150 {
151 std::auto_ptr<DcmFileFormat> file_; 151 std::auto_ptr<DcmFileFormat> file_;
152 Encoding encoding_;
153 }; 152 };
154 153
155 154
156 // This method can only be called from the constructors! 155 // This method can only be called from the constructors!
157 void ParsedDicomFile::Setup(const char* buffer, size_t size) 156 void ParsedDicomFile::Setup(const char* buffer, size_t size)
172 171
173 throw OrthancException(ErrorCode_BadFileFormat); 172 throw OrthancException(ErrorCode_BadFileFormat);
174 } 173 }
175 pimpl_->file_->loadAllDataIntoMemory(); 174 pimpl_->file_->loadAllDataIntoMemory();
176 pimpl_->file_->transferEnd(); 175 pimpl_->file_->transferEnd();
177
178 pimpl_->encoding_ = FromDcmtkBridge::DetectEncoding(*pimpl_->file_->getDataset());
179 } 176 }
180 177
181 178
182 static void SendPathValueForDictionary(RestApiOutput& output, 179 static void SendPathValueForDictionary(RestApiOutput& output,
183 DcmItem& dicom) 180 DcmItem& dicom)
592 } 589 }
593 } 590 }
594 591
595 592
596 void ParsedDicomFile::Insert(const DicomTag& tag, 593 void ParsedDicomFile::Insert(const DicomTag& tag,
597 const std::string& value) 594 const std::string& utf8Value)
598 { 595 {
599 std::auto_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag)); 596 std::auto_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag));
600 FromDcmtkBridge::FillElementWithString(*element, tag, value, false); 597 FromDcmtkBridge::FillElementWithString(*element, tag, utf8Value, false, GetEncoding());
601 InsertInternal(*pimpl_->file_->getDataset(), element.release()); 598 InsertInternal(*pimpl_->file_->getDataset(), element.release());
602 } 599 }
603 600
604 601
605 void ParsedDicomFile::Insert(const DicomTag& tag, 602 void ParsedDicomFile::Insert(const DicomTag& tag,
606 const Json::Value& value, 603 const Json::Value& value,
607 bool decodeBinaryTags) 604 bool decodeBinaryTags)
608 { 605 {
609 std::auto_ptr<DcmElement> element(FromDcmtkBridge::FromJson(tag, value, decodeBinaryTags)); 606 std::auto_ptr<DcmElement> element(FromDcmtkBridge::FromJson(tag, value, decodeBinaryTags, GetEncoding()));
610 InsertInternal(*pimpl_->file_->getDataset(), element.release()); 607 InsertInternal(*pimpl_->file_->getDataset(), element.release());
611 } 608 }
612 609
613 610
614 static void ReplaceInternal(DcmDataset& dicom, 611 static void ReplaceInternal(DcmDataset& dicom,
638 InsertInternal(dicom, element.release()); 635 InsertInternal(dicom, element.release());
639 } 636 }
640 637
641 638
642 void ParsedDicomFile::UpdateStorageUid(const DicomTag& tag, 639 void ParsedDicomFile::UpdateStorageUid(const DicomTag& tag,
643 const std::string& value, 640 const std::string& utf8Value,
644 bool decodeBinaryTags) 641 bool decodeBinaryTags)
645 { 642 {
646 if (tag != DICOM_TAG_SOP_CLASS_UID && 643 if (tag != DICOM_TAG_SOP_CLASS_UID &&
647 tag != DICOM_TAG_SOP_INSTANCE_UID) 644 tag != DICOM_TAG_SOP_INSTANCE_UID)
648 { 645 {
649 return; 646 return;
650 } 647 }
651 648
652 std::string binary; 649 std::string binary;
653 const std::string* decoded = &value; 650 const std::string* decoded = &utf8Value;
654 651
655 if (decodeBinaryTags && 652 if (decodeBinaryTags &&
656 boost::starts_with(value, "data:application/octet-stream;base64,")) 653 boost::starts_with(utf8Value, "data:application/octet-stream;base64,"))
657 { 654 {
658 std::string mime; 655 std::string mime;
659 Toolbox::DecodeDataUriScheme(mime, binary, value); 656 Toolbox::DecodeDataUriScheme(mime, binary, utf8Value);
660 decoded = &binary; 657 decoded = &binary;
658 }
659 else
660 {
661 Encoding encoding = GetEncoding();
662 if (GetEncoding() != Encoding_Utf8)
663 {
664 binary = Toolbox::ConvertFromUtf8(utf8Value, encoding);
665 decoded = &binary;
666 }
661 } 667 }
662 668
663 /** 669 /**
664 * dcmodify will automatically correct 'Media Storage SOP Class 670 * dcmodify will automatically correct 'Media Storage SOP Class
665 * UID' and 'Media Storage SOP Instance UID' in the metaheader, if 671 * UID' and 'Media Storage SOP Instance UID' in the metaheader, if
680 } 686 }
681 } 687 }
682 688
683 689
684 void ParsedDicomFile::Replace(const DicomTag& tag, 690 void ParsedDicomFile::Replace(const DicomTag& tag,
685 const std::string& value, 691 const std::string& utf8Value,
686 DicomReplaceMode mode) 692 DicomReplaceMode mode)
687 { 693 {
688 std::auto_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag)); 694 std::auto_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag));
689 FromDcmtkBridge::FillElementWithString(*element, tag, value, false); 695 FromDcmtkBridge::FillElementWithString(*element, tag, utf8Value, false, GetEncoding());
690 ReplaceInternal(*pimpl_->file_->getDataset(), element, mode); 696 ReplaceInternal(*pimpl_->file_->getDataset(), element, mode);
691 UpdateStorageUid(tag, value, false); 697 UpdateStorageUid(tag, utf8Value, false);
692 } 698 }
693 699
694 700
695 void ParsedDicomFile::Replace(const DicomTag& tag, 701 void ParsedDicomFile::Replace(const DicomTag& tag,
696 const Json::Value& value, 702 const Json::Value& value,
697 bool decodeBinaryTags, 703 bool decodeBinaryTags,
698 DicomReplaceMode mode) 704 DicomReplaceMode mode)
699 { 705 {
700 std::auto_ptr<DcmElement> element(FromDcmtkBridge::FromJson(tag, value, decodeBinaryTags)); 706 std::auto_ptr<DcmElement> element(FromDcmtkBridge::FromJson(tag, value, decodeBinaryTags, GetEncoding()));
701 ReplaceInternal(*pimpl_->file_->getDataset(), element, mode); 707 ReplaceInternal(*pimpl_->file_->getDataset(), element, mode);
702 708
703 if (tag == DICOM_TAG_SOP_CLASS_UID || 709 if (tag == DICOM_TAG_SOP_CLASS_UID ||
704 tag == DICOM_TAG_SOP_INSTANCE_UID) 710 tag == DICOM_TAG_SOP_INSTANCE_UID)
705 { 711 {
764 element == NULL) 770 element == NULL)
765 { 771 {
766 return false; 772 return false;
767 } 773 }
768 774
769 std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(*element, pimpl_->encoding_)); 775 std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(*element, GetEncoding()));
770 776
771 if (v.get() == NULL) 777 if (v.get() == NULL)
772 { 778 {
773 value = ""; 779 value = "";
774 } 780 }
844 850
845 851
846 ParsedDicomFile::ParsedDicomFile() : pimpl_(new PImpl) 852 ParsedDicomFile::ParsedDicomFile() : pimpl_(new PImpl)
847 { 853 {
848 pimpl_->file_.reset(new DcmFileFormat); 854 pimpl_->file_.reset(new DcmFileFormat);
849 pimpl_->encoding_ = Encoding_Ascii;
850 Replace(DICOM_TAG_PATIENT_ID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient)); 855 Replace(DICOM_TAG_PATIENT_ID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient));
851 Replace(DICOM_TAG_STUDY_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Study)); 856 Replace(DICOM_TAG_STUDY_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Study));
852 Replace(DICOM_TAG_SERIES_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series)); 857 Replace(DICOM_TAG_SERIES_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series));
853 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance)); 858 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance));
854 } 859 }
874 879
875 ParsedDicomFile::ParsedDicomFile(ParsedDicomFile& other) : 880 ParsedDicomFile::ParsedDicomFile(ParsedDicomFile& other) :
876 pimpl_(new PImpl) 881 pimpl_(new PImpl)
877 { 882 {
878 pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.pimpl_->file_->clone())); 883 pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.pimpl_->file_->clone()));
879 pimpl_->encoding_ = other.pimpl_->encoding_;
880 884
881 // Create a new instance-level identifier 885 // Create a new instance-level identifier
882 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance)); 886 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance));
883 } 887 }
884 888
1104 } 1108 }
1105 1109
1106 1110
1107 Encoding ParsedDicomFile::GetEncoding() const 1111 Encoding ParsedDicomFile::GetEncoding() const
1108 { 1112 {
1109 return pimpl_->encoding_; 1113 return FromDcmtkBridge::DetectEncoding(*pimpl_->file_->getDataset());
1110 } 1114 }
1111 1115
1112 1116
1113 void ParsedDicomFile::SetEncoding(Encoding encoding) 1117 void ParsedDicomFile::SetEncoding(Encoding encoding)
1114 { 1118 {
1116 { 1120 {
1117 // This Cyrillic codepage is not officially supported by the 1121 // This Cyrillic codepage is not officially supported by the
1118 // DICOM standard. Do not set the SpecificCharacterSet tag. 1122 // DICOM standard. Do not set the SpecificCharacterSet tag.
1119 return; 1123 return;
1120 } 1124 }
1121
1122 pimpl_->encoding_ = encoding;
1123 1125
1124 std::string s = GetDicomSpecificCharacterSet(encoding); 1126 std::string s = GetDicomSpecificCharacterSet(encoding);
1125 Replace(DICOM_TAG_SPECIFIC_CHARACTER_SET, s, DicomReplaceMode_InsertIfAbsent); 1127 Replace(DICOM_TAG_SPECIFIC_CHARACTER_SET, s, DicomReplaceMode_InsertIfAbsent);
1126 } 1128 }
1127 1129