Mercurial > hg > orthanc
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 |