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 }