Mercurial > hg > orthanc
comparison OrthancServer/ParsedDicomFile.cpp @ 956:2fd5a163776d
primitives for proper encoding handling
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 25 Jun 2014 16:08:47 +0200 |
parents | 87791ebc1f50 |
children | 509e146c3cb3 2f76b92addd4 |
comparison
equal
deleted
inserted
replaced
950:8811abd6aec9 | 956:2fd5a163776d |
---|---|
144 namespace Orthanc | 144 namespace Orthanc |
145 { | 145 { |
146 struct ParsedDicomFile::PImpl | 146 struct ParsedDicomFile::PImpl |
147 { | 147 { |
148 std::auto_ptr<DcmFileFormat> file_; | 148 std::auto_ptr<DcmFileFormat> file_; |
149 Encoding encoding_; | |
149 }; | 150 }; |
150 | 151 |
151 | 152 |
152 // This method can only be called from the constructors! | 153 // This method can only be called from the constructors! |
153 void ParsedDicomFile::Setup(const char* buffer, size_t size) | 154 void ParsedDicomFile::Setup(const char* buffer, size_t size) |
168 | 169 |
169 throw OrthancException(ErrorCode_BadFileFormat); | 170 throw OrthancException(ErrorCode_BadFileFormat); |
170 } | 171 } |
171 pimpl_->file_->loadAllDataIntoMemory(); | 172 pimpl_->file_->loadAllDataIntoMemory(); |
172 pimpl_->file_->transferEnd(); | 173 pimpl_->file_->transferEnd(); |
174 | |
175 pimpl_->encoding_ = FromDcmtkBridge::DetectEncoding(*pimpl_->file_->getDataset()); | |
173 } | 176 } |
174 | 177 |
175 | 178 |
176 static void SendPathValueForDictionary(RestApiOutput& output, | 179 static void SendPathValueForDictionary(RestApiOutput& output, |
177 DcmItem& dicom) | 180 DcmItem& dicom) |
870 element == NULL) | 873 element == NULL) |
871 { | 874 { |
872 return false; | 875 return false; |
873 } | 876 } |
874 | 877 |
875 std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(*element)); | 878 std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(*element, pimpl_->encoding_)); |
876 | 879 |
877 if (v.get() == NULL) | 880 if (v.get() == NULL) |
878 { | 881 { |
879 value = ""; | 882 value = ""; |
880 } | 883 } |
883 value = v->AsString(); | 886 value = v->AsString(); |
884 } | 887 } |
885 | 888 |
886 return true; | 889 return true; |
887 } | 890 } |
888 | |
889 | 891 |
890 | 892 |
891 DicomInstanceHasher ParsedDicomFile::GetHasher() | 893 DicomInstanceHasher ParsedDicomFile::GetHasher() |
892 { | 894 { |
893 std::string patientId, studyUid, seriesUid, instanceUid; | 895 std::string patientId, studyUid, seriesUid, instanceUid; |
899 { | 901 { |
900 throw OrthancException(ErrorCode_BadFileFormat); | 902 throw OrthancException(ErrorCode_BadFileFormat); |
901 } | 903 } |
902 | 904 |
903 return DicomInstanceHasher(patientId, studyUid, seriesUid, instanceUid); | 905 return DicomInstanceHasher(patientId, studyUid, seriesUid, instanceUid); |
904 } | |
905 | |
906 | |
907 static void StoreElement(Json::Value& target, | |
908 DcmElement& element, | |
909 unsigned int maxStringLength); | |
910 | |
911 static void StoreItem(Json::Value& target, | |
912 DcmItem& item, | |
913 unsigned int maxStringLength) | |
914 { | |
915 target = Json::Value(Json::objectValue); | |
916 | |
917 for (unsigned long i = 0; i < item.card(); i++) | |
918 { | |
919 DcmElement* element = item.getElement(i); | |
920 StoreElement(target, *element, maxStringLength); | |
921 } | |
922 } | |
923 | |
924 | |
925 static void StoreElement(Json::Value& target, | |
926 DcmElement& element, | |
927 unsigned int maxStringLength) | |
928 { | |
929 assert(target.type() == Json::objectValue); | |
930 | |
931 DicomTag tag(FromDcmtkBridge::GetTag(element)); | |
932 const std::string formattedTag = tag.Format(); | |
933 | |
934 #if 0 | |
935 const std::string tagName = FromDcmtkBridge::GetName(tag); | |
936 #else | |
937 // This version of the code gives access to the name of the private tags | |
938 DcmTag tagbis(element.getTag()); | |
939 const std::string tagName(tagbis.getTagName()); | |
940 #endif | |
941 | |
942 if (element.isLeaf()) | |
943 { | |
944 Json::Value value(Json::objectValue); | |
945 value["Name"] = tagName; | |
946 | |
947 if (tagbis.getPrivateCreator() != NULL) | |
948 { | |
949 value["PrivateCreator"] = tagbis.getPrivateCreator(); | |
950 } | |
951 | |
952 std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(element)); | |
953 if (v->IsNull()) | |
954 { | |
955 value["Type"] = "Null"; | |
956 value["Value"] = Json::nullValue; | |
957 } | |
958 else | |
959 { | |
960 std::string s = v->AsString(); | |
961 if (maxStringLength == 0 || | |
962 s.size() <= maxStringLength) | |
963 { | |
964 value["Type"] = "String"; | |
965 value["Value"] = s; | |
966 } | |
967 else | |
968 { | |
969 value["Type"] = "TooLong"; | |
970 value["Value"] = Json::nullValue; | |
971 } | |
972 } | |
973 | |
974 target[formattedTag] = value; | |
975 } | |
976 else | |
977 { | |
978 Json::Value children(Json::arrayValue); | |
979 | |
980 // "All subclasses of DcmElement except for DcmSequenceOfItems | |
981 // are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset | |
982 // etc. are not." The following cast is thus OK. | |
983 DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(element); | |
984 | |
985 for (unsigned long i = 0; i < sequence.card(); i++) | |
986 { | |
987 DcmItem* child = sequence.getItem(i); | |
988 Json::Value& v = children.append(Json::objectValue); | |
989 StoreItem(v, *child, maxStringLength); | |
990 } | |
991 | |
992 target[formattedTag]["Name"] = tagName; | |
993 target[formattedTag]["Type"] = "Sequence"; | |
994 target[formattedTag]["Value"] = children; | |
995 } | |
996 } | 906 } |
997 | 907 |
998 | 908 |
999 template <typename T> | 909 template <typename T> |
1000 static void ExtractPngImageTruncate(std::string& result, | 910 static void ExtractPngImageTruncate(std::string& result, |
1042 | 952 |
1043 | 953 |
1044 ParsedDicomFile::ParsedDicomFile() : pimpl_(new PImpl) | 954 ParsedDicomFile::ParsedDicomFile() : pimpl_(new PImpl) |
1045 { | 955 { |
1046 pimpl_->file_.reset(new DcmFileFormat); | 956 pimpl_->file_.reset(new DcmFileFormat); |
957 pimpl_->encoding_ = Encoding_Ascii; | |
1047 Replace(DICOM_TAG_PATIENT_ID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient)); | 958 Replace(DICOM_TAG_PATIENT_ID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient)); |
1048 Replace(DICOM_TAG_STUDY_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Study)); | 959 Replace(DICOM_TAG_STUDY_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Study)); |
1049 Replace(DICOM_TAG_SERIES_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series)); | 960 Replace(DICOM_TAG_SERIES_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series)); |
1050 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance)); | 961 Replace(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance)); |
1051 } | 962 } |
1071 | 982 |
1072 ParsedDicomFile::ParsedDicomFile(ParsedDicomFile& other) : | 983 ParsedDicomFile::ParsedDicomFile(ParsedDicomFile& other) : |
1073 pimpl_(new PImpl) | 984 pimpl_(new PImpl) |
1074 { | 985 { |
1075 pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.pimpl_->file_->clone())); | 986 pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.pimpl_->file_->clone())); |
987 | |
988 pimpl_->encoding_ = other.pimpl_->encoding_; | |
1076 } | 989 } |
1077 | 990 |
1078 | 991 |
1079 ParsedDicomFile::~ParsedDicomFile() | 992 ParsedDicomFile::~ParsedDicomFile() |
1080 { | 993 { |
1277 ImageAccessor accessor(buffer.GetConstAccessor()); | 1190 ImageAccessor accessor(buffer.GetConstAccessor()); |
1278 PngWriter writer; | 1191 PngWriter writer; |
1279 writer.WriteToMemory(result, accessor); | 1192 writer.WriteToMemory(result, accessor); |
1280 } | 1193 } |
1281 | 1194 |
1195 | |
1196 Encoding ParsedDicomFile::GetEncoding() const | |
1197 { | |
1198 return pimpl_->encoding_; | |
1199 } | |
1282 } | 1200 } |