Mercurial > hg > orthanc
comparison OrthancServer/ParsedDicomFile.cpp @ 794:437c4a83d2cc
refactoring
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 06 May 2014 10:52:20 +0200 |
parents | 145604a97914 |
children | 777b6b694da6 |
comparison
equal
deleted
inserted
replaced
793:145604a97914 | 794:437c4a83d2cc |
---|---|
136 | 136 |
137 | 137 |
138 | 138 |
139 namespace Orthanc | 139 namespace Orthanc |
140 { | 140 { |
141 struct ParsedDicomFile::PImpl | |
142 { | |
143 std::auto_ptr<DcmFileFormat> file_; | |
144 }; | |
145 | |
146 | |
147 // This method can only be called from the constructors! | |
141 void ParsedDicomFile::Setup(const char* buffer, size_t size) | 148 void ParsedDicomFile::Setup(const char* buffer, size_t size) |
142 { | 149 { |
143 DcmInputBufferStream is; | 150 DcmInputBufferStream is; |
144 if (size > 0) | 151 if (size > 0) |
145 { | 152 { |
146 is.setBuffer(buffer, size); | 153 is.setBuffer(buffer, size); |
147 } | 154 } |
148 is.setEos(); | 155 is.setEos(); |
149 | 156 |
150 file_.reset(new DcmFileFormat); | 157 pimpl_->file_.reset(new DcmFileFormat); |
151 file_->transferInit(); | 158 pimpl_->file_->transferInit(); |
152 if (!file_->read(is).good()) | 159 if (!pimpl_->file_->read(is).good()) |
153 { | 160 { |
161 delete pimpl_; // Avoid a memory leak due to exception | |
162 // throwing, as we are in the constructor | |
163 | |
154 throw OrthancException(ErrorCode_BadFileFormat); | 164 throw OrthancException(ErrorCode_BadFileFormat); |
155 } | 165 } |
156 file_->loadAllDataIntoMemory(); | 166 pimpl_->file_->loadAllDataIntoMemory(); |
157 file_->transferEnd(); | 167 pimpl_->file_->transferEnd(); |
158 } | 168 } |
159 | 169 |
160 | 170 |
161 static void SendPathValueForDictionary(RestApiOutput& output, | 171 static void SendPathValueForDictionary(RestApiOutput& output, |
162 DcmItem& dicom) | 172 DcmItem& dicom) |
391 } | 401 } |
392 | 402 |
393 void ParsedDicomFile::SendPathValue(RestApiOutput& output, | 403 void ParsedDicomFile::SendPathValue(RestApiOutput& output, |
394 const UriComponents& uri) | 404 const UriComponents& uri) |
395 { | 405 { |
396 DcmItem* dicom = file_->getDataset(); | 406 DcmItem* dicom = pimpl_->file_->getDataset(); |
397 E_TransferSyntax transferSyntax = file_->getDataset()->getOriginalXfer(); | 407 E_TransferSyntax transferSyntax = pimpl_->file_->getDataset()->getOriginalXfer(); |
398 | 408 |
399 // Special case: Accessing the pixel data | 409 // Special case: Accessing the pixel data |
400 if (uri.size() == 1 || | 410 if (uri.size() == 1 || |
401 uri.size() == 2) | 411 uri.size() == 2) |
402 { | 412 { |
727 | 737 |
728 | 738 |
729 void ParsedDicomFile::Remove(const DicomTag& tag) | 739 void ParsedDicomFile::Remove(const DicomTag& tag) |
730 { | 740 { |
731 DcmTagKey key(tag.GetGroup(), tag.GetElement()); | 741 DcmTagKey key(tag.GetGroup(), tag.GetElement()); |
732 DcmElement* element = file_->getDataset()->remove(key); | 742 DcmElement* element = pimpl_->file_->getDataset()->remove(key); |
733 if (element != NULL) | 743 if (element != NULL) |
734 { | 744 { |
735 delete element; | 745 delete element; |
736 } | 746 } |
737 } | 747 } |
742 { | 752 { |
743 typedef std::list<DcmElement*> Tags; | 753 typedef std::list<DcmElement*> Tags; |
744 | 754 |
745 Tags privateTags; | 755 Tags privateTags; |
746 | 756 |
747 DcmDataset& dataset = *file_->getDataset(); | 757 DcmDataset& dataset = *pimpl_->file_->getDataset(); |
748 for (unsigned long i = 0; i < dataset.card(); i++) | 758 for (unsigned long i = 0; i < dataset.card(); i++) |
749 { | 759 { |
750 DcmElement* element = dataset.getElement(i); | 760 DcmElement* element = dataset.getElement(i); |
751 DcmTag tag(element->getTag()); | 761 DcmTag tag(element->getTag()); |
752 if (!strcmp("PrivateCreator", tag.getTagName()) || // TODO - This may change with future versions of DCMTK | 762 if (!strcmp("PrivateCreator", tag.getTagName()) || // TODO - This may change with future versions of DCMTK |
773 const std::string& value) | 783 const std::string& value) |
774 { | 784 { |
775 std::auto_ptr<DcmElement> element(CreateElementForTag(tag)); | 785 std::auto_ptr<DcmElement> element(CreateElementForTag(tag)); |
776 FillElementWithString(*element, tag, value); | 786 FillElementWithString(*element, tag, value); |
777 | 787 |
778 if (!file_->getDataset()->insert(element.release(), false, false).good()) | 788 if (!pimpl_->file_->getDataset()->insert(element.release(), false, false).good()) |
779 { | 789 { |
780 // This field already exists | 790 // This field already exists |
781 throw OrthancException(ErrorCode_InternalError); | 791 throw OrthancException(ErrorCode_InternalError); |
782 } | 792 } |
783 } | 793 } |
788 DicomReplaceMode mode) | 798 DicomReplaceMode mode) |
789 { | 799 { |
790 DcmTagKey key(tag.GetGroup(), tag.GetElement()); | 800 DcmTagKey key(tag.GetGroup(), tag.GetElement()); |
791 DcmElement* element = NULL; | 801 DcmElement* element = NULL; |
792 | 802 |
793 if (!file_->getDataset()->findAndGetElement(key, element).good() || | 803 if (!pimpl_->file_->getDataset()->findAndGetElement(key, element).good() || |
794 element == NULL) | 804 element == NULL) |
795 { | 805 { |
796 // This field does not exist, act wrt. the specified "mode" | 806 // This field does not exist, act wrt. the specified "mode" |
797 switch (mode) | 807 switch (mode) |
798 { | 808 { |
835 | 845 |
836 | 846 |
837 void ParsedDicomFile::Answer(RestApiOutput& output) | 847 void ParsedDicomFile::Answer(RestApiOutput& output) |
838 { | 848 { |
839 std::string serialized; | 849 std::string serialized; |
840 if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, file_->getDataset())) | 850 if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, pimpl_->file_->getDataset())) |
841 { | 851 { |
842 output.AnswerBuffer(serialized, CONTENT_TYPE_OCTET_STREAM); | 852 output.AnswerBuffer(serialized, CONTENT_TYPE_OCTET_STREAM); |
843 } | 853 } |
844 } | 854 } |
845 | 855 |
847 | 857 |
848 bool ParsedDicomFile::GetTagValue(std::string& value, | 858 bool ParsedDicomFile::GetTagValue(std::string& value, |
849 const DicomTag& tag) | 859 const DicomTag& tag) |
850 { | 860 { |
851 DcmTagKey k(tag.GetGroup(), tag.GetElement()); | 861 DcmTagKey k(tag.GetGroup(), tag.GetElement()); |
852 DcmDataset& dataset = *file_->getDataset(); | 862 DcmDataset& dataset = *pimpl_->file_->getDataset(); |
853 DcmElement* element = NULL; | 863 DcmElement* element = NULL; |
854 if (!dataset.findAndGetElement(k, element).good() || | 864 if (!dataset.findAndGetElement(k, element).good() || |
855 element == NULL) | 865 element == NULL) |
856 { | 866 { |
857 return false; | 867 return false; |
1011 } | 1021 } |
1012 | 1022 |
1013 | 1023 |
1014 void ParsedDicomFile::SaveToMemoryBuffer(std::string& buffer) | 1024 void ParsedDicomFile::SaveToMemoryBuffer(std::string& buffer) |
1015 { | 1025 { |
1016 FromDcmtkBridge::SaveToMemoryBuffer(buffer, file_->getDataset()); | 1026 FromDcmtkBridge::SaveToMemoryBuffer(buffer, pimpl_->file_->getDataset()); |
1017 } | 1027 } |
1018 | 1028 |
1019 | 1029 |
1020 void ParsedDicomFile::SaveToFile(const std::string& path) | 1030 void ParsedDicomFile::SaveToFile(const std::string& path) |
1021 { | 1031 { |
1024 SaveToMemoryBuffer(content); | 1034 SaveToMemoryBuffer(content); |
1025 Toolbox::WriteFile(content, path); | 1035 Toolbox::WriteFile(content, path); |
1026 } | 1036 } |
1027 | 1037 |
1028 | 1038 |
1029 ParsedDicomFile::ParsedDicomFile() | 1039 ParsedDicomFile::ParsedDicomFile() : pimpl_(new PImpl) |
1030 { | 1040 { |
1031 file_.reset(new DcmFileFormat); | 1041 pimpl_->file_.reset(new DcmFileFormat); |
1032 Replace(DICOM_TAG_PATIENT_ID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient)); | 1042 Replace(DICOM_TAG_PATIENT_ID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient)); |
1033 Replace(DICOM_TAG_STUDY_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Study)); | 1043 Replace(DICOM_TAG_STUDY_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Study)); |
1034 Replace(DICOM_TAG_SERIES_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series)); | 1044 Replace(DICOM_TAG_SERIES_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series)); |
1035 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance)); | 1045 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance)); |
1036 } | 1046 } |
1037 | 1047 |
1038 | 1048 |
1039 ParsedDicomFile::ParsedDicomFile(const char* content, | 1049 ParsedDicomFile::ParsedDicomFile(const char* content, size_t size) : pimpl_(new PImpl) |
1040 size_t size) | |
1041 { | 1050 { |
1042 Setup(content, size); | 1051 Setup(content, size); |
1043 } | 1052 } |
1044 | 1053 |
1045 ParsedDicomFile::ParsedDicomFile(const std::string& content) | 1054 ParsedDicomFile::ParsedDicomFile(const std::string& content) : pimpl_(new PImpl) |
1046 { | 1055 { |
1047 if (content.size() == 0) | 1056 if (content.size() == 0) |
1048 { | 1057 { |
1049 Setup(NULL, 0); | 1058 Setup(NULL, 0); |
1050 } | 1059 } |
1053 Setup(&content[0], content.size()); | 1062 Setup(&content[0], content.size()); |
1054 } | 1063 } |
1055 } | 1064 } |
1056 | 1065 |
1057 | 1066 |
1058 ParsedDicomFile::ParsedDicomFile(DcmFileFormat& other) : | 1067 ParsedDicomFile::ParsedDicomFile(ParsedDicomFile& other) : |
1059 file_(dynamic_cast<DcmFileFormat*>(other.clone())) | 1068 pimpl_(new PImpl) |
1060 { | 1069 { |
1070 pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.pimpl_->file_->clone())); | |
1061 } | 1071 } |
1062 | 1072 |
1063 | 1073 |
1064 ParsedDicomFile::~ParsedDicomFile() | 1074 ParsedDicomFile::~ParsedDicomFile() |
1065 { | 1075 { |
1076 delete pimpl_; | |
1066 } | 1077 } |
1067 | 1078 |
1068 | 1079 |
1069 void* ParsedDicomFile::GetDcmtkObject() | 1080 void* ParsedDicomFile::GetDcmtkObject() |
1070 { | 1081 { |
1071 return file_.get(); | 1082 return pimpl_->file_.get(); |
1072 } | 1083 } |
1073 | 1084 |
1074 | 1085 |
1075 ParsedDicomFile* ParsedDicomFile::Clone() | 1086 ParsedDicomFile* ParsedDicomFile::Clone() |
1076 { | 1087 { |
1077 return new ParsedDicomFile(*file_); | 1088 return new ParsedDicomFile(*this); |
1078 } | 1089 } |
1079 } | 1090 } |