Mercurial > hg > orthanc
comparison OrthancServer/FromDcmtkBridge.cpp @ 291:4d7469f72a0b
embedding of dicom dictionaries
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 14 Dec 2012 15:15:48 +0100 |
parents | 4031f73fe0e4 |
children | 238134081136 |
comparison
equal
deleted
inserted
replaced
290:b3322636b06d | 291:4d7469f72a0b |
---|---|
58 #include <dcmtk/dcmdata/dcvrul.h> | 58 #include <dcmtk/dcmdata/dcvrul.h> |
59 #include <dcmtk/dcmdata/dcvrus.h> | 59 #include <dcmtk/dcmdata/dcvrus.h> |
60 #include <dcmtk/dcmdata/dcuid.h> | 60 #include <dcmtk/dcmdata/dcuid.h> |
61 | 61 |
62 #include <boost/math/special_functions/round.hpp> | 62 #include <boost/math/special_functions/round.hpp> |
63 #include <glog/logging.h> | |
64 #include <dcmtk/dcmdata/dcostrmb.h> | |
63 | 65 |
64 namespace Orthanc | 66 namespace Orthanc |
65 { | 67 { |
66 ParsedDicomFile::ParsedDicomFile(const std::string& content) | 68 ParsedDicomFile::ParsedDicomFile(const std::string& content) |
67 { | 69 { |
71 is.setBuffer(&content[0], content.size()); | 73 is.setBuffer(&content[0], content.size()); |
72 } | 74 } |
73 is.setEos(); | 75 is.setEos(); |
74 | 76 |
75 file_.reset(new DcmFileFormat); | 77 file_.reset(new DcmFileFormat); |
78 file_->transferInit(); | |
76 if (!file_->read(is).good()) | 79 if (!file_->read(is).good()) |
77 { | 80 { |
78 throw OrthancException(ErrorCode_BadFileFormat); | 81 throw OrthancException(ErrorCode_BadFileFormat); |
79 } | 82 } |
83 file_->loadAllDataIntoMemory(); | |
84 file_->transferEnd(); | |
80 } | 85 } |
81 | 86 |
82 | 87 |
83 static void SendPathValueForDictionary(RestApiOutput& output, | 88 static void SendPathValueForDictionary(RestApiOutput& output, |
84 DcmItem& dicom) | 89 DcmItem& dicom) |
142 key = DcmTagKey(group, element); | 147 key = DcmTagKey(group, element); |
143 | 148 |
144 return true; | 149 return true; |
145 } | 150 } |
146 | 151 |
152 | |
153 static void SendSequence(RestApiOutput& output, | |
154 DcmSequenceOfItems& sequence) | |
155 { | |
156 // This element is a sequence | |
157 Json::Value v = Json::arrayValue; | |
158 | |
159 for (unsigned long i = 0; i < sequence.card(); i++) | |
160 { | |
161 v.append(boost::lexical_cast<std::string>(i)); | |
162 } | |
163 | |
164 output.AnswerJson(v); | |
165 } | |
166 | |
167 static void SendField(RestApiOutput& output, | |
168 DcmElement& element) | |
169 { | |
170 // This element is not a sequence | |
171 std::string buffer; | |
172 buffer.resize(65536); | |
173 Uint32 length = element.getLength(); | |
174 Uint32 offset = 0; | |
175 | |
176 output.GetLowLevelOutput().SendOkHeader("application/octet-stream", true, length, NULL); | |
177 | |
178 while (offset < length) | |
179 { | |
180 Uint32 nbytes; | |
181 if (length - offset < buffer.size()) | |
182 { | |
183 nbytes = length - offset; | |
184 } | |
185 else | |
186 { | |
187 nbytes = buffer.size(); | |
188 } | |
189 | |
190 if (element.getPartialValue(&buffer[0], offset, nbytes).good()) | |
191 { | |
192 output.GetLowLevelOutput().Send(&buffer[0], nbytes); | |
193 offset += nbytes; | |
194 } | |
195 else | |
196 { | |
197 return; | |
198 } | |
199 } | |
200 | |
201 output.MarkLowLevelOutputDone(); | |
202 } | |
203 | |
147 static void SendPathValueForLeaf(RestApiOutput& output, | 204 static void SendPathValueForLeaf(RestApiOutput& output, |
148 const std::string& tag, | 205 const std::string& tag, |
149 DcmItem& dicom) | 206 DcmItem& dicom) |
150 { | 207 { |
151 DcmTagKey k; | 208 DcmTagKey k; |
152 if (!ParseTagAndGroup(k, tag)) | 209 if (!ParseTagAndGroup(k, tag)) |
153 { | 210 { |
154 return; | 211 return; |
155 } | 212 } |
156 | 213 |
214 DcmSequenceOfItems* sequence = NULL; | |
215 if (dicom.findAndGetSequence(k, sequence).good() && | |
216 sequence != NULL && | |
217 sequence->getVR() == EVR_SQ) | |
218 { | |
219 SendSequence(output, *sequence); | |
220 return; | |
221 } | |
222 | |
157 DcmElement* element = NULL; | 223 DcmElement* element = NULL; |
158 if (dicom.findAndGetElement(k, element).good() && element != NULL) | 224 if (dicom.findAndGetElement(k, element).good() && |
159 { | 225 element != NULL && |
160 if (element->getVR() == EVR_SQ) | 226 element->getVR() != EVR_UNKNOWN && |
161 { | 227 element->getVR() != EVR_SQ) |
162 // This element is a sequence | 228 { |
163 Json::Value v = Json::arrayValue; | 229 SendField(output, *element); |
164 DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(*element); | |
165 | |
166 for (unsigned long i = 0; i < sequence.card(); i++) | |
167 { | |
168 v.append(boost::lexical_cast<std::string>(i)); | |
169 } | |
170 | |
171 output.AnswerJson(v); | |
172 } | |
173 else | |
174 { | |
175 // This element is not a sequence | |
176 std::string buffer; | |
177 buffer.resize(65536); | |
178 Uint32 length = element->getLength(); | |
179 Uint32 offset = 0; | |
180 | |
181 output.GetLowLevelOutput().SendOkHeader("application/octet-stream", true, length, NULL); | |
182 | |
183 while (offset < length) | |
184 { | |
185 Uint32 nbytes; | |
186 if (length - offset < buffer.size()) | |
187 { | |
188 nbytes = length - offset; | |
189 } | |
190 else | |
191 { | |
192 nbytes = buffer.size(); | |
193 } | |
194 | |
195 if (element->getPartialValue(&buffer[0], offset, nbytes).good()) | |
196 { | |
197 output.GetLowLevelOutput().Send(&buffer[0], nbytes); | |
198 offset += nbytes; | |
199 } | |
200 else | |
201 { | |
202 return; | |
203 } | |
204 } | |
205 | |
206 output.MarkLowLevelOutputDone(); | |
207 } | |
208 } | 230 } |
209 } | 231 } |
210 | 232 |
211 void ParsedDicomFile::SendPathValue(RestApiOutput& output, | 233 void ParsedDicomFile::SendPathValue(RestApiOutput& output, |
212 const UriComponents& uri) | 234 const UriComponents& uri) |
726 | 748 |
727 std::string FromDcmtkBridge::GetName(const DicomTag& t) | 749 std::string FromDcmtkBridge::GetName(const DicomTag& t) |
728 { | 750 { |
729 // Some patches for important tags because of different DICOM | 751 // Some patches for important tags because of different DICOM |
730 // dictionaries between DCMTK versions | 752 // dictionaries between DCMTK versions |
731 if (t == DICOM_TAG_PATIENT_NAME) | 753 std::string n = t.GetMainTagsName(); |
732 return "PatientName"; | 754 if (n.size() != 0) |
733 | 755 { |
734 if (t == DicomTag(0x0010, 0x0030)) | 756 return n; |
735 return "PatientBirthDate"; | 757 } |
736 | |
737 if (t == DicomTag(0x0010, 0x0040)) | |
738 return "PatientSex"; | |
739 | |
740 // End of patches | 758 // End of patches |
741 | 759 |
742 DcmTagKey tag(t.GetGroup(), t.GetElement()); | 760 DcmTagKey tag(t.GetGroup(), t.GetElement()); |
743 const DcmDataDictionary& dict = dcmDataDict.rdlock(); | 761 const DcmDataDictionary& dict = dcmDataDict.rdlock(); |
744 const DcmDictEntry* entry = dict.findEntry(tag, NULL); | 762 const DcmDictEntry* entry = dict.findEntry(tag, NULL); |
822 default: | 840 default: |
823 throw OrthancException(ErrorCode_ParameterOutOfRange); | 841 throw OrthancException(ErrorCode_ParameterOutOfRange); |
824 } | 842 } |
825 } | 843 } |
826 | 844 |
845 bool FromDcmtkBridge::SaveToMemoryBuffer(std::string& buffer, | |
846 DcmDataset* dataSet) | |
847 { | |
848 // Determine the transfer syntax which shall be used to write the | |
849 // information to the file. We always switch to the Little Endian | |
850 // syntax, with explicit length. | |
851 | |
852 // http://support.dcmtk.org/docs/dcxfer_8h-source.html | |
853 E_TransferSyntax xfer = EXS_LittleEndianExplicit; | |
854 E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength; | |
855 | |
856 uint32_t s = dataSet->getLength(xfer, encodingType); | |
857 | |
858 buffer.resize(s); | |
859 DcmOutputBufferStream ob(&buffer[0], s); | |
860 | |
861 dataSet->transferInit(); | |
862 | |
863 #if DCMTK_VERSION_NUMBER >= 360 | |
864 OFCondition c = dataSet->write(ob, xfer, encodingType, NULL, | |
865 /*opt_groupLength*/ EGL_recalcGL, | |
866 /*opt_paddingType*/ EPD_withoutPadding); | |
867 #else | |
868 OFCondition c = dataSet->write(ob, xfer, encodingType, NULL); | |
869 #endif | |
870 | |
871 dataSet->transferEnd(); | |
872 if (c.good()) | |
873 { | |
874 return true; | |
875 } | |
876 else | |
877 { | |
878 buffer.clear(); | |
879 return false; | |
880 } | |
881 | |
882 #if 0 | |
883 OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, | |
884 encodingType, | |
885 /*opt_groupLength*/ EGL_recalcGL, | |
886 /*opt_paddingType*/ EPD_withoutPadding, | |
887 OFstatic_cast(Uint32, /*opt_filepad*/ 0), | |
888 OFstatic_cast(Uint32, /*opt_itempad*/ 0), | |
889 (opt_useMetaheader) ? EWM_fileformat : EWM_dataset); | |
890 #endif | |
891 } | |
892 | |
893 | |
827 } | 894 } |