Mercurial > hg > orthanc
comparison Plugins/Samples/GdcmDecoder/Plugin.cpp @ 3930:b99acc213937 transcoding
transcoder plugins and GDCM transcoding are working
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 14 May 2020 19:20:40 +0200 |
parents | 7e33516965f8 |
children | f67b48833a4f |
comparison
equal
deleted
inserted
replaced
3929:7dc5e7e0045d | 3930:b99acc213937 |
---|---|
22 #include "../../../Core/Compatibility.h" | 22 #include "../../../Core/Compatibility.h" |
23 #include "../../../Core/DicomFormat/DicomMap.h" | 23 #include "../../../Core/DicomFormat/DicomMap.h" |
24 #include "../../../Core/Toolbox.h" | 24 #include "../../../Core/Toolbox.h" |
25 #include "GdcmDecoderCache.h" | 25 #include "GdcmDecoderCache.h" |
26 | 26 |
27 #include <gdcmImageChangeTransferSyntax.h> | |
28 #include <gdcmImageReader.h> | |
29 #include <gdcmImageWriter.h> | |
30 #include <gdcmUIDGenerator.h> | |
31 #include <gdcmAttribute.h> | |
32 | |
33 | |
27 static OrthancPlugins::GdcmDecoderCache cache_; | 34 static OrthancPlugins::GdcmDecoderCache cache_; |
28 static bool restrictTransferSyntaxes_ = false; | 35 static bool restrictTransferSyntaxes_ = false; |
29 static std::set<std::string> enabledTransferSyntaxes_; | 36 static std::set<std::string> enabledTransferSyntaxes_; |
30 | 37 |
31 | 38 |
146 return OrthancPluginErrorCode_Plugin; | 153 return OrthancPluginErrorCode_Plugin; |
147 } | 154 } |
148 } | 155 } |
149 | 156 |
150 | 157 |
158 OrthancPluginErrorCode TranscoderCallback( | |
159 OrthancPluginMemoryBuffer* transcoded /* out */, | |
160 uint8_t* hasSopInstanceUidChanged /* out */, | |
161 const void* buffer, | |
162 uint64_t size, | |
163 const char* const* allowedSyntaxes, | |
164 uint32_t countSyntaxes, | |
165 uint8_t allowNewSopInstanceUid) | |
166 { | |
167 try | |
168 { | |
169 std::string dicom(reinterpret_cast<const char*>(buffer), size); | |
170 std::stringstream stream(dicom); | |
171 | |
172 gdcm::ImageReader reader; | |
173 reader.SetStream(stream); | |
174 if (!reader.Read()) | |
175 { | |
176 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, | |
177 "GDCM cannot decode the image"); | |
178 } | |
179 | |
180 // First check that transcoding is mandatory | |
181 for (uint32_t i = 0; i < countSyntaxes; i++) | |
182 { | |
183 gdcm::TransferSyntax syntax(gdcm::TransferSyntax::GetTSType(allowedSyntaxes[i])); | |
184 if (syntax.IsValid() && | |
185 reader.GetImage().GetTransferSyntax() == syntax) | |
186 { | |
187 // Same transfer syntax as in the source, return a copy of the | |
188 // source buffer | |
189 OrthancPlugins::MemoryBuffer orthancBuffer(buffer, size); | |
190 *transcoded = orthancBuffer.Release(); | |
191 *hasSopInstanceUidChanged = false; | |
192 return OrthancPluginErrorCode_Success; | |
193 } | |
194 } | |
195 | |
196 for (uint32_t i = 0; i < countSyntaxes; i++) | |
197 { | |
198 gdcm::TransferSyntax syntax(gdcm::TransferSyntax::GetTSType(allowedSyntaxes[i])); | |
199 if (syntax.IsValid()) | |
200 { | |
201 gdcm::ImageChangeTransferSyntax change; | |
202 change.SetTransferSyntax(syntax); | |
203 change.SetInput(reader.GetImage()); | |
204 | |
205 if (change.Change()) | |
206 { | |
207 if (syntax == gdcm::TransferSyntax::JPEGBaselineProcess1 || | |
208 syntax == gdcm::TransferSyntax::JPEGExtendedProcess2_4 || | |
209 syntax == gdcm::TransferSyntax::JPEGLSNearLossless || | |
210 syntax == gdcm::TransferSyntax::JPEG2000 || | |
211 syntax == gdcm::TransferSyntax::JPEG2000Part2) | |
212 { | |
213 // In the case of a lossy compression, generate new SOP instance UID | |
214 gdcm::UIDGenerator generator; | |
215 std::string uid = generator.Generate(); | |
216 if (uid.size() == 0) | |
217 { | |
218 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, | |
219 "GDCM cannot generate a UID"); | |
220 } | |
221 | |
222 gdcm::Attribute<0x0008,0x0018> sopInstanceUid; | |
223 sopInstanceUid.SetValue(uid); | |
224 reader.GetFile().GetDataSet().Replace(sopInstanceUid.GetAsDataElement()); | |
225 *hasSopInstanceUidChanged = 1; | |
226 } | |
227 else | |
228 { | |
229 *hasSopInstanceUidChanged = 0; | |
230 } | |
231 | |
232 // GDCM was able to change the transfer syntax, serialize it | |
233 // to the output buffer | |
234 gdcm::ImageWriter writer; | |
235 writer.SetImage(change.GetOutput()); | |
236 writer.SetFile(reader.GetFile()); | |
237 | |
238 std::stringstream ss; | |
239 writer.SetStream(ss); | |
240 if (writer.Write()) | |
241 { | |
242 std::string s = ss.str(); | |
243 OrthancPlugins::MemoryBuffer orthancBuffer(s.empty() ? NULL : s.c_str(), s.size()); | |
244 *transcoded = orthancBuffer.Release(); | |
245 | |
246 return OrthancPluginErrorCode_Success; | |
247 } | |
248 else | |
249 { | |
250 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, | |
251 "GDCM cannot serialize the image"); | |
252 } | |
253 } | |
254 } | |
255 } | |
256 | |
257 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
258 } | |
259 catch (Orthanc::OrthancException& e) | |
260 { | |
261 LOG(INFO) << "Cannot transcode image using GDCM: " << e.What(); | |
262 return OrthancPluginErrorCode_Plugin; | |
263 } | |
264 catch (std::runtime_error& e) | |
265 { | |
266 LOG(INFO) << "Cannot transcode image using GDCM: " << e.what(); | |
267 return OrthancPluginErrorCode_Plugin; | |
268 } | |
269 catch (...) | |
270 { | |
271 LOG(INFO) << "Native exception while decoding image using GDCM"; | |
272 return OrthancPluginErrorCode_Plugin; | |
273 } | |
274 } | |
275 | |
151 | 276 |
152 /** | 277 /** |
153 * We force the redefinition of the "ORTHANC_PLUGINS_API" macro, that | 278 * We force the redefinition of the "ORTHANC_PLUGINS_API" macro, that |
154 * was left empty with gcc until Orthanc SDK 1.5.7 (no "default" | 279 * was left empty with gcc until Orthanc SDK 1.5.7 (no "default" |
155 * visibility). This causes the version script, if run from "Holy | 280 * visibility). This causes the version script, if run from "Holy |
174 static const char* const KEY_GDCM = "Gdcm"; | 299 static const char* const KEY_GDCM = "Gdcm"; |
175 static const char* const KEY_ENABLE_GDCM = "EnableGdcm"; | 300 static const char* const KEY_ENABLE_GDCM = "EnableGdcm"; |
176 static const char* const KEY_RESTRICT_TRANSFER_SYNTAXES = "RestrictTransferSyntaxes"; | 301 static const char* const KEY_RESTRICT_TRANSFER_SYNTAXES = "RestrictTransferSyntaxes"; |
177 | 302 |
178 OrthancPlugins::SetGlobalContext(context); | 303 OrthancPlugins::SetGlobalContext(context); |
179 LOG(INFO) << "Initializing the advanced decoder of medical images using GDCM"; | 304 Orthanc::Logging::Initialize(context); |
180 | 305 LOG(INFO) << "Initializing the decoder/transcoder of medical images using GDCM"; |
181 | 306 |
182 /* Check the version of the Orthanc core */ | 307 /* Check the version of the Orthanc core */ |
183 if (OrthancPluginCheckVersion(context) == 0) | 308 if (!OrthancPlugins::CheckMinimalOrthancVersion(0, 9, 5)) |
184 { | 309 { |
185 char info[1024]; | 310 LOG(ERROR) << "Your version of Orthanc (" << std::string(context->orthancVersion) |
186 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", | 311 << ") must be above 0.9.5 to run this plugin"; |
187 context->orthancVersion, | |
188 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, | |
189 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, | |
190 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); | |
191 OrthancPluginLogError(context, info); | |
192 return -1; | 312 return -1; |
193 } | 313 } |
194 | 314 |
195 OrthancPluginSetDescription(context, "Advanced decoder of medical images using GDCM."); | 315 OrthancPluginSetDescription(context, "Decoder/transcoder of medical images using GDCM."); |
196 | 316 |
197 OrthancPlugins::OrthancConfiguration global; | 317 OrthancPlugins::OrthancConfiguration global; |
198 | 318 |
199 bool enabled = true; | 319 bool enabled = true; |
200 | 320 |
218 } | 338 } |
219 | 339 |
220 if (enabled) | 340 if (enabled) |
221 { | 341 { |
222 OrthancPluginRegisterDecodeImageCallback(context, DecodeImageCallback); | 342 OrthancPluginRegisterDecodeImageCallback(context, DecodeImageCallback); |
343 | |
344 if (OrthancPlugins::CheckMinimalOrthancVersion(1, 7, 0)) | |
345 { | |
346 OrthancPluginRegisterTranscoderCallback(context, TranscoderCallback); | |
347 } | |
348 else | |
349 { | |
350 LOG(ERROR) << "Your version of Orthanc (" << std::string(context->orthancVersion) | |
351 << ") must be above 1.7.0 to benefit from transcoding"; | |
352 } | |
223 } | 353 } |
224 else | 354 else |
225 { | 355 { |
226 LOG(WARNING) << "The advanced decoder of medical images using GDCM is disabled"; | 356 LOG(WARNING) << "The decoder/transcoder of medical images using GDCM is disabled"; |
227 } | 357 } |
228 | 358 |
229 return 0; | 359 return 0; |
230 } | 360 } |
231 | 361 |
232 | 362 |
233 ORTHANC_PLUGINS_API void OrthancPluginFinalize() | 363 ORTHANC_PLUGINS_API void OrthancPluginFinalize() |
234 { | 364 { |
235 LOG(INFO) << "Finalizing the advanced decoder of medical images using GDCM"; | 365 LOG(INFO) << "Finalizing the decoder/transcoder of medical images using GDCM"; |
236 } | 366 } |
237 | 367 |
238 | 368 |
239 ORTHANC_PLUGINS_API const char* OrthancPluginGetName() | 369 ORTHANC_PLUGINS_API const char* OrthancPluginGetName() |
240 { | 370 { |
241 return "gdcm-decoder"; | 371 return "gdcm"; |
242 } | 372 } |
243 | 373 |
244 | 374 |
245 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() | 375 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() |
246 { | 376 { |