Mercurial > hg > orthanc
comparison Plugins/Engine/OrthancPlugins.cpp @ 3958:596912ebab5f c-get
integration mainline->c-get
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 20 May 2020 17:03:24 +0200 |
parents | 5fe8c6d3212e |
children | 821715370890 |
comparison
equal
deleted
inserted
replaced
3955:66879215cbf3 | 3958:596912ebab5f |
---|---|
60 #include "../../Core/Logging.h" | 60 #include "../../Core/Logging.h" |
61 #include "../../Core/MetricsRegistry.h" | 61 #include "../../Core/MetricsRegistry.h" |
62 #include "../../Core/OrthancException.h" | 62 #include "../../Core/OrthancException.h" |
63 #include "../../Core/SerializationToolbox.h" | 63 #include "../../Core/SerializationToolbox.h" |
64 #include "../../Core/Toolbox.h" | 64 #include "../../Core/Toolbox.h" |
65 #include "../../OrthancServer/DefaultDicomImageDecoder.h" | |
66 #include "../../OrthancServer/OrthancConfiguration.h" | 65 #include "../../OrthancServer/OrthancConfiguration.h" |
67 #include "../../OrthancServer/OrthancFindRequestHandler.h" | 66 #include "../../OrthancServer/OrthancFindRequestHandler.h" |
68 #include "../../OrthancServer/Search/HierarchicalMatcher.h" | 67 #include "../../OrthancServer/Search/HierarchicalMatcher.h" |
69 #include "../../OrthancServer/ServerContext.h" | 68 #include "../../OrthancServer/ServerContext.h" |
70 #include "../../OrthancServer/ServerToolbox.h" | 69 #include "../../OrthancServer/ServerToolbox.h" |
71 #include "PluginsEnumerations.h" | 70 #include "PluginsEnumerations.h" |
72 #include "PluginsJob.h" | 71 #include "PluginsJob.h" |
73 | 72 |
74 #include <boost/regex.hpp> | 73 #include <boost/regex.hpp> |
75 #include <dcmtk/dcmdata/dcdict.h> | 74 #include <dcmtk/dcmdata/dcdict.h> |
76 #include <dcmtk/dcmdata/dcdicent.h> | 75 #include <dcmtk/dcmdata/dcdicent.h> |
77 | 76 |
78 #define ERROR_MESSAGE_64BIT "A 64bit version of the Orthanc API is necessary" | 77 #define ERROR_MESSAGE_64BIT "A 64bit version of the Orthanc API is necessary" |
78 | |
79 | 79 |
80 namespace Orthanc | 80 namespace Orthanc |
81 { | 81 { |
82 static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer& target, | 82 static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer& target, |
83 const void* data, | 83 const void* data, |
328 | 328 |
329 | 329 |
330 class DicomWebBinaryFormatter : public DicomWebJsonVisitor::IBinaryFormatter | 330 class DicomWebBinaryFormatter : public DicomWebJsonVisitor::IBinaryFormatter |
331 { | 331 { |
332 private: | 332 private: |
333 OrthancPluginDicomWebBinaryCallback callback_; | 333 OrthancPluginDicomWebBinaryCallback oldCallback_; |
334 DicomWebJsonVisitor::BinaryMode currentMode_; | 334 OrthancPluginDicomWebBinaryCallback2 newCallback_; // New in Orthanc 1.7.0 |
335 std::string currentBulkDataUri_; | 335 void* newPayload_; // New in Orthanc 1.7.0 |
336 DicomWebJsonVisitor::BinaryMode currentMode_; | |
337 std::string currentBulkDataUri_; | |
336 | 338 |
337 static void Setter(OrthancPluginDicomWebNode* node, | 339 static void Setter(OrthancPluginDicomWebNode* node, |
338 OrthancPluginDicomWebBinaryMode mode, | 340 OrthancPluginDicomWebBinaryMode mode, |
339 const char* bulkDataUri) | 341 const char* bulkDataUri) |
340 { | 342 { |
364 throw OrthancException(ErrorCode_ParameterOutOfRange); | 366 throw OrthancException(ErrorCode_ParameterOutOfRange); |
365 } | 367 } |
366 } | 368 } |
367 | 369 |
368 public: | 370 public: |
369 DicomWebBinaryFormatter(const _OrthancPluginEncodeDicomWeb& parameters) : | 371 DicomWebBinaryFormatter(OrthancPluginDicomWebBinaryCallback callback) : |
370 callback_(parameters.callback) | 372 oldCallback_(callback), |
373 newCallback_(NULL), | |
374 newPayload_(NULL) | |
375 { | |
376 } | |
377 | |
378 DicomWebBinaryFormatter(OrthancPluginDicomWebBinaryCallback2 callback, | |
379 void* payload) : | |
380 oldCallback_(NULL), | |
381 newCallback_(callback), | |
382 newPayload_(payload) | |
371 { | 383 { |
372 } | 384 } |
373 | 385 |
374 virtual DicomWebJsonVisitor::BinaryMode Format(std::string& bulkDataUri, | 386 virtual DicomWebJsonVisitor::BinaryMode Format(std::string& bulkDataUri, |
375 const std::vector<DicomTag>& parentTags, | 387 const std::vector<DicomTag>& parentTags, |
376 const std::vector<size_t>& parentIndexes, | 388 const std::vector<size_t>& parentIndexes, |
377 const DicomTag& tag, | 389 const DicomTag& tag, |
378 ValueRepresentation vr) | 390 ValueRepresentation vr) |
379 { | 391 { |
380 if (callback_ == NULL) | 392 if (oldCallback_ == NULL && |
393 newCallback_ == NULL) | |
381 { | 394 { |
382 return DicomWebJsonVisitor::BinaryMode_InlineBinary; | 395 return DicomWebJsonVisitor::BinaryMode_InlineBinary; |
383 } | 396 } |
384 else | 397 else |
385 { | 398 { |
396 } | 409 } |
397 bool empty = parentTags.empty(); | 410 bool empty = parentTags.empty(); |
398 | 411 |
399 currentMode_ = DicomWebJsonVisitor::BinaryMode_Ignore; | 412 currentMode_ = DicomWebJsonVisitor::BinaryMode_Ignore; |
400 | 413 |
401 callback_(reinterpret_cast<OrthancPluginDicomWebNode*>(this), | 414 if (oldCallback_ != NULL) |
402 DicomWebBinaryFormatter::Setter, | 415 { |
403 static_cast<uint32_t>(parentTags.size()), | 416 oldCallback_(reinterpret_cast<OrthancPluginDicomWebNode*>(this), |
404 (empty ? NULL : &groups[0]), | 417 DicomWebBinaryFormatter::Setter, |
405 (empty ? NULL : &elements[0]), | 418 static_cast<uint32_t>(parentTags.size()), |
406 (empty ? NULL : &indexes[0]), | 419 (empty ? NULL : &groups[0]), |
407 tag.GetGroup(), | 420 (empty ? NULL : &elements[0]), |
408 tag.GetElement(), | 421 (empty ? NULL : &indexes[0]), |
409 Plugins::Convert(vr)); | 422 tag.GetGroup(), |
423 tag.GetElement(), | |
424 Plugins::Convert(vr)); | |
425 } | |
426 else | |
427 { | |
428 assert(newCallback_ != NULL); | |
429 newCallback_(reinterpret_cast<OrthancPluginDicomWebNode*>(this), | |
430 DicomWebBinaryFormatter::Setter, | |
431 static_cast<uint32_t>(parentTags.size()), | |
432 (empty ? NULL : &groups[0]), | |
433 (empty ? NULL : &elements[0]), | |
434 (empty ? NULL : &indexes[0]), | |
435 tag.GetGroup(), | |
436 tag.GetElement(), | |
437 Plugins::Convert(vr), | |
438 newPayload_); | |
439 } | |
410 | 440 |
411 bulkDataUri = currentBulkDataUri_; | 441 bulkDataUri = currentBulkDataUri_; |
412 return currentMode_; | 442 return currentMode_; |
413 } | 443 } |
444 } | |
445 | |
446 void Apply(char** target, | |
447 bool isJson, | |
448 ParsedDicomFile& dicom) | |
449 { | |
450 DicomWebJsonVisitor visitor; | |
451 visitor.SetFormatter(*this); | |
452 | |
453 dicom.Apply(visitor); | |
454 | |
455 std::string s; | |
456 | |
457 if (isJson) | |
458 { | |
459 s = visitor.GetResult().toStyledString(); | |
460 } | |
461 else | |
462 { | |
463 visitor.FormatXml(s); | |
464 } | |
465 | |
466 *target = CopyString(s); | |
467 } | |
468 | |
469 | |
470 void Apply(char** target, | |
471 bool isJson, | |
472 const void* dicom, | |
473 size_t dicomSize) | |
474 { | |
475 ParsedDicomFile parsed(dicom, dicomSize); | |
476 Apply(target, isJson, parsed); | |
414 } | 477 } |
415 }; | 478 }; |
416 } | 479 } |
417 | 480 |
418 | 481 |
825 typedef std::list<OrthancPluginOnChangeCallback> OnChangeCallbacks; | 888 typedef std::list<OrthancPluginOnChangeCallback> OnChangeCallbacks; |
826 typedef std::list<OrthancPluginIncomingHttpRequestFilter> IncomingHttpRequestFilters; | 889 typedef std::list<OrthancPluginIncomingHttpRequestFilter> IncomingHttpRequestFilters; |
827 typedef std::list<OrthancPluginIncomingHttpRequestFilter2> IncomingHttpRequestFilters2; | 890 typedef std::list<OrthancPluginIncomingHttpRequestFilter2> IncomingHttpRequestFilters2; |
828 typedef std::list<OrthancPluginIncomingDicomInstanceFilter> IncomingDicomInstanceFilters; | 891 typedef std::list<OrthancPluginIncomingDicomInstanceFilter> IncomingDicomInstanceFilters; |
829 typedef std::list<OrthancPluginDecodeImageCallback> DecodeImageCallbacks; | 892 typedef std::list<OrthancPluginDecodeImageCallback> DecodeImageCallbacks; |
893 typedef std::list<OrthancPluginTranscoderCallback> TranscoderCallbacks; | |
830 typedef std::list<OrthancPluginJobsUnserializer> JobsUnserializers; | 894 typedef std::list<OrthancPluginJobsUnserializer> JobsUnserializers; |
831 typedef std::list<OrthancPluginRefreshMetricsCallback> RefreshMetricsCallbacks; | 895 typedef std::list<OrthancPluginRefreshMetricsCallback> RefreshMetricsCallbacks; |
832 typedef std::list<StorageCommitmentScp*> StorageCommitmentScpCallbacks; | 896 typedef std::list<StorageCommitmentScp*> StorageCommitmentScpCallbacks; |
833 typedef std::map<Property, std::string> Properties; | 897 typedef std::map<Property, std::string> Properties; |
834 | 898 |
839 OnStoredCallbacks onStoredCallbacks_; | 903 OnStoredCallbacks onStoredCallbacks_; |
840 OnChangeCallbacks onChangeCallbacks_; | 904 OnChangeCallbacks onChangeCallbacks_; |
841 OrthancPluginFindCallback findCallback_; | 905 OrthancPluginFindCallback findCallback_; |
842 OrthancPluginWorklistCallback worklistCallback_; | 906 OrthancPluginWorklistCallback worklistCallback_; |
843 DecodeImageCallbacks decodeImageCallbacks_; | 907 DecodeImageCallbacks decodeImageCallbacks_; |
908 TranscoderCallbacks transcoderCallbacks_; | |
844 JobsUnserializers jobsUnserializers_; | 909 JobsUnserializers jobsUnserializers_; |
845 _OrthancPluginMoveCallback moveCallbacks_; | 910 _OrthancPluginMoveCallback moveCallbacks_; |
846 IncomingHttpRequestFilters incomingHttpRequestFilters_; | 911 IncomingHttpRequestFilters incomingHttpRequestFilters_; |
847 IncomingHttpRequestFilters2 incomingHttpRequestFilters2_; | 912 IncomingHttpRequestFilters2 incomingHttpRequestFilters2_; |
848 IncomingDicomInstanceFilters incomingDicomInstanceFilters_; | 913 IncomingDicomInstanceFilters incomingDicomInstanceFilters_; |
853 boost::recursive_mutex restCallbackMutex_; | 918 boost::recursive_mutex restCallbackMutex_; |
854 boost::recursive_mutex storedCallbackMutex_; | 919 boost::recursive_mutex storedCallbackMutex_; |
855 boost::recursive_mutex changeCallbackMutex_; | 920 boost::recursive_mutex changeCallbackMutex_; |
856 boost::mutex findCallbackMutex_; | 921 boost::mutex findCallbackMutex_; |
857 boost::mutex worklistCallbackMutex_; | 922 boost::mutex worklistCallbackMutex_; |
858 boost::mutex decodeImageCallbackMutex_; | 923 boost::shared_mutex decoderTranscoderMutex_; // Changed from "boost::mutex" in Orthanc 1.7.0 |
859 boost::mutex jobsUnserializersMutex_; | 924 boost::mutex jobsUnserializersMutex_; |
860 boost::mutex refreshMetricsMutex_; | 925 boost::mutex refreshMetricsMutex_; |
861 boost::mutex storageCommitmentScpMutex_; | 926 boost::mutex storageCommitmentScpMutex_; |
862 boost::recursive_mutex invokeServiceMutex_; | 927 boost::recursive_mutex invokeServiceMutex_; |
863 | 928 |
1829 private: | 1894 private: |
1830 std::unique_ptr<ParsedDicomFile> parsed_; | 1895 std::unique_ptr<ParsedDicomFile> parsed_; |
1831 DicomInstanceToStore instance_; | 1896 DicomInstanceToStore instance_; |
1832 | 1897 |
1833 public: | 1898 public: |
1834 DicomInstanceFromTranscoded(IDicomTranscoder::TranscodedDicom& transcoded) : | 1899 DicomInstanceFromTranscoded(IDicomTranscoder::DicomImage& transcoded) : |
1835 parsed_(ParsedDicomFile::AcquireDcmtkObject(transcoded.ReleaseDicom())) | 1900 parsed_(transcoded.ReleaseAsParsedDicomFile()) |
1836 { | 1901 { |
1837 instance_.SetParsedDicomFile(*parsed_); | 1902 instance_.SetParsedDicomFile(*parsed_); |
1838 instance_.SetOrigin(DicomInstanceOrigin::FromPlugins()); | 1903 instance_.SetOrigin(DicomInstanceOrigin::FromPlugins()); |
1839 } | 1904 } |
1840 | 1905 |
2044 void OrthancPlugins::RegisterDecodeImageCallback(const void* parameters) | 2109 void OrthancPlugins::RegisterDecodeImageCallback(const void* parameters) |
2045 { | 2110 { |
2046 const _OrthancPluginDecodeImageCallback& p = | 2111 const _OrthancPluginDecodeImageCallback& p = |
2047 *reinterpret_cast<const _OrthancPluginDecodeImageCallback*>(parameters); | 2112 *reinterpret_cast<const _OrthancPluginDecodeImageCallback*>(parameters); |
2048 | 2113 |
2049 boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_); | 2114 boost::unique_lock<boost::shared_mutex> lock(pimpl_->decoderTranscoderMutex_); |
2050 | 2115 |
2051 pimpl_->decodeImageCallbacks_.push_back(p.callback); | 2116 pimpl_->decodeImageCallbacks_.push_back(p.callback); |
2052 LOG(INFO) << "Plugin has registered a callback to decode DICOM images (" | 2117 LOG(INFO) << "Plugin has registered a callback to decode DICOM images (" |
2053 << pimpl_->decodeImageCallbacks_.size() << " decoder(s) now active)"; | 2118 << pimpl_->decodeImageCallbacks_.size() << " decoder(s) now active)"; |
2119 } | |
2120 | |
2121 | |
2122 void OrthancPlugins::RegisterTranscoderCallback(const void* parameters) | |
2123 { | |
2124 const _OrthancPluginTranscoderCallback& p = | |
2125 *reinterpret_cast<const _OrthancPluginTranscoderCallback*>(parameters); | |
2126 | |
2127 boost::unique_lock<boost::shared_mutex> lock(pimpl_->decoderTranscoderMutex_); | |
2128 | |
2129 pimpl_->transcoderCallbacks_.push_back(p.callback); | |
2130 LOG(INFO) << "Plugin has registered a callback to transcode DICOM images (" | |
2131 << pimpl_->transcoderCallbacks_.size() << " transcoder(s) now active)"; | |
2054 } | 2132 } |
2055 | 2133 |
2056 | 2134 |
2057 void OrthancPlugins::RegisterJobsUnserializer(const void* parameters) | 2135 void OrthancPlugins::RegisterJobsUnserializer(const void* parameters) |
2058 { | 2136 { |
2691 static OrthancPluginImage* ReturnImage(std::unique_ptr<ImageAccessor>& image) | 2769 static OrthancPluginImage* ReturnImage(std::unique_ptr<ImageAccessor>& image) |
2692 { | 2770 { |
2693 // Images returned to plugins are assumed to be writeable. If the | 2771 // Images returned to plugins are assumed to be writeable. If the |
2694 // input image is read-only, we return a copy so that it can be modified. | 2772 // input image is read-only, we return a copy so that it can be modified. |
2695 | 2773 |
2774 if (image.get() == NULL) | |
2775 { | |
2776 throw OrthancException(ErrorCode_NullPointer); | |
2777 } | |
2778 | |
2696 if (image->IsReadOnly()) | 2779 if (image->IsReadOnly()) |
2697 { | 2780 { |
2698 std::unique_ptr<Image> copy(new Image(image->GetFormat(), image->GetWidth(), image->GetHeight(), false)); | 2781 std::unique_ptr<Image> copy(new Image(image->GetFormat(), image->GetWidth(), image->GetHeight(), false)); |
2699 ImageProcessing::Copy(*copy, *image); | 2782 ImageProcessing::Copy(*copy, *image); |
2700 image.reset(NULL); | 2783 image.reset(NULL); |
2744 return; | 2827 return; |
2745 } | 2828 } |
2746 | 2829 |
2747 case _OrthancPluginService_GetInstanceDecodedFrame: | 2830 case _OrthancPluginService_GetInstanceDecodedFrame: |
2748 { | 2831 { |
2749 bool hasDecoderPlugin; | 2832 if (p.targetImage == NULL) |
2750 | 2833 { |
2751 { | 2834 throw OrthancException(ErrorCode_NullPointer); |
2752 boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_); | |
2753 hasDecoderPlugin = !pimpl_->decodeImageCallbacks_.empty(); | |
2754 } | 2835 } |
2755 | 2836 |
2756 std::unique_ptr<ImageAccessor> decoded; | 2837 std::unique_ptr<ImageAccessor> decoded; |
2757 if (p.targetImage == NULL) | 2838 { |
2758 { | 2839 PImpl::ServerContextLock lock(*pimpl_); |
2759 throw OrthancException(ErrorCode_NullPointer); | 2840 decoded.reset(lock.GetContext().DecodeDicomFrame(instance, p.frameIndex)); |
2760 } | 2841 } |
2761 else if (hasDecoderPlugin) | 2842 |
2762 { | |
2763 // TODO - This call could be speeded up the future, if a | |
2764 // "decoding context" gets introduced in the decoder plugins | |
2765 | |
2766 decoded.reset(Decode(instance.GetBufferData(), instance.GetBufferSize(), p.frameIndex)); | |
2767 } | |
2768 else | |
2769 { | |
2770 decoded.reset(DicomImageDecoder::Decode(instance.GetParsedDicomFile(), p.frameIndex)); | |
2771 } | |
2772 | |
2773 *(p.targetImage) = ReturnImage(decoded); | 2843 *(p.targetImage) = ReturnImage(decoded); |
2774 return; | 2844 return; |
2775 } | 2845 } |
2776 | 2846 |
2777 case _OrthancPluginService_SerializeDicomInstance: | 2847 case _OrthancPluginService_SerializeDicomInstance: |
2787 std::string serialized; | 2857 std::string serialized; |
2788 instance.GetParsedDicomFile().SaveToMemoryBuffer(serialized); | 2858 instance.GetParsedDicomFile().SaveToMemoryBuffer(serialized); |
2789 CopyToMemoryBuffer(*p.targetBuffer, serialized); | 2859 CopyToMemoryBuffer(*p.targetBuffer, serialized); |
2790 return; | 2860 return; |
2791 } | 2861 } |
2862 | |
2863 case _OrthancPluginService_GetInstanceAdvancedJson: | |
2864 { | |
2865 if (p.targetStringToFree == NULL) | |
2866 { | |
2867 throw OrthancException(ErrorCode_NullPointer); | |
2868 } | |
2792 | 2869 |
2870 Json::Value json; | |
2871 instance.GetParsedDicomFile().DatasetToJson( | |
2872 json, Plugins::Convert(p.format), | |
2873 static_cast<DicomToJsonFlags>(p.flags), p.maxStringLength); | |
2874 | |
2875 Json::FastWriter writer; | |
2876 *p.targetStringToFree = CopyString(writer.write(json)); | |
2877 return; | |
2878 } | |
2879 | |
2880 case _OrthancPluginService_GetInstanceDicomWebJson: | |
2881 case _OrthancPluginService_GetInstanceDicomWebXml: | |
2882 { | |
2883 if (p.targetStringToFree == NULL) | |
2884 { | |
2885 throw OrthancException(ErrorCode_NullPointer); | |
2886 } | |
2887 | |
2888 DicomWebBinaryFormatter formatter(p.dicomWebCallback, p.dicomWebPayload); | |
2889 formatter.Apply(p.targetStringToFree, | |
2890 (service == _OrthancPluginService_GetInstanceDicomWebJson), | |
2891 instance.GetParsedDicomFile()); | |
2892 return; | |
2893 } | |
2894 | |
2793 default: | 2895 default: |
2794 throw OrthancException(ErrorCode_InternalError); | 2896 throw OrthancException(ErrorCode_InternalError); |
2795 } | 2897 } |
2796 } | 2898 } |
2797 | 2899 |
3673 | 3775 |
3674 case _OrthancPluginService_GetInstanceFramesCount: | 3776 case _OrthancPluginService_GetInstanceFramesCount: |
3675 case _OrthancPluginService_GetInstanceRawFrame: | 3777 case _OrthancPluginService_GetInstanceRawFrame: |
3676 case _OrthancPluginService_GetInstanceDecodedFrame: | 3778 case _OrthancPluginService_GetInstanceDecodedFrame: |
3677 case _OrthancPluginService_SerializeDicomInstance: | 3779 case _OrthancPluginService_SerializeDicomInstance: |
3780 case _OrthancPluginService_GetInstanceAdvancedJson: | |
3781 case _OrthancPluginService_GetInstanceDicomWebJson: | |
3782 case _OrthancPluginService_GetInstanceDicomWebXml: | |
3678 AccessDicomInstance2(service, parameters); | 3783 AccessDicomInstance2(service, parameters); |
3679 return true; | 3784 return true; |
3680 | 3785 |
3681 case _OrthancPluginService_SetGlobalProperty: | 3786 case _OrthancPluginService_SetGlobalProperty: |
3682 { | 3787 { |
4193 case _OrthancPluginService_EncodeDicomWebXml: | 4298 case _OrthancPluginService_EncodeDicomWebXml: |
4194 { | 4299 { |
4195 const _OrthancPluginEncodeDicomWeb& p = | 4300 const _OrthancPluginEncodeDicomWeb& p = |
4196 *reinterpret_cast<const _OrthancPluginEncodeDicomWeb*>(parameters); | 4301 *reinterpret_cast<const _OrthancPluginEncodeDicomWeb*>(parameters); |
4197 | 4302 |
4198 DicomWebBinaryFormatter formatter(p); | 4303 DicomWebBinaryFormatter formatter(p.callback); |
4199 | 4304 formatter.Apply(p.target, |
4200 DicomWebJsonVisitor visitor; | 4305 (service == _OrthancPluginService_EncodeDicomWebJson), |
4201 visitor.SetFormatter(formatter); | 4306 p.dicom, p.dicomSize); |
4202 | 4307 return true; |
4203 { | 4308 } |
4204 ParsedDicomFile dicom(p.dicom, p.dicomSize); | 4309 |
4205 dicom.Apply(visitor); | 4310 case _OrthancPluginService_EncodeDicomWebJson2: |
4206 } | 4311 case _OrthancPluginService_EncodeDicomWebXml2: |
4207 | 4312 { |
4208 std::string s; | 4313 const _OrthancPluginEncodeDicomWeb2& p = |
4209 | 4314 *reinterpret_cast<const _OrthancPluginEncodeDicomWeb2*>(parameters); |
4210 if (service == _OrthancPluginService_EncodeDicomWebJson) | 4315 |
4211 { | 4316 DicomWebBinaryFormatter formatter(p.callback, p.payload); |
4212 s = visitor.GetResult().toStyledString(); | 4317 formatter.Apply(p.target, |
4213 } | 4318 (service == _OrthancPluginService_EncodeDicomWebJson2), |
4214 else | 4319 p.dicom, p.dicomSize); |
4215 { | |
4216 visitor.FormatXml(s); | |
4217 } | |
4218 | |
4219 *p.target = CopyString(s); | |
4220 return true; | 4320 return true; |
4221 } | 4321 } |
4222 | 4322 |
4223 case _OrthancPluginService_GetTagName: | 4323 case _OrthancPluginService_GetTagName: |
4224 GetTagName(parameters); | 4324 GetTagName(parameters); |
4267 throw OrthancException(ErrorCode_ParameterOutOfRange, "Unsupported transfer syntax: " + | 4367 throw OrthancException(ErrorCode_ParameterOutOfRange, "Unsupported transfer syntax: " + |
4268 std::string(p.transferSyntax == NULL ? "(null)" : p.transferSyntax)); | 4368 std::string(p.transferSyntax == NULL ? "(null)" : p.transferSyntax)); |
4269 } | 4369 } |
4270 else | 4370 else |
4271 { | 4371 { |
4272 ParsedDicomFile dicom(p.buffer, p.size); | |
4273 | |
4274 std::set<DicomTransferSyntax> syntaxes; | 4372 std::set<DicomTransferSyntax> syntaxes; |
4275 syntaxes.insert(transferSyntax); | 4373 syntaxes.insert(transferSyntax); |
4276 | 4374 |
4277 std::unique_ptr<IDicomTranscoder::TranscodedDicom> transcoded; | 4375 IDicomTranscoder::DicomImage source; |
4376 source.SetExternalBuffer(p.buffer, p.size); | |
4377 | |
4378 IDicomTranscoder::DicomImage transcoded; | |
4379 bool success; | |
4278 | 4380 |
4279 { | 4381 { |
4280 PImpl::ServerContextLock lock(*pimpl_); | 4382 PImpl::ServerContextLock lock(*pimpl_); |
4281 transcoded.reset(lock.GetContext().GetTranscoder().TranscodeToParsed( | 4383 success = lock.GetContext().Transcode( |
4282 dicom.GetDcmtkObject(), p.buffer, p.size, | 4384 transcoded, source, syntaxes, true /* allow new sop */); |
4283 syntaxes, true /* allow new sop */)); | |
4284 } | 4385 } |
4285 | 4386 |
4286 if (transcoded.get() == NULL) | 4387 if (success) |
4388 { | |
4389 *(p.target) = reinterpret_cast<OrthancPluginDicomInstance*>( | |
4390 new DicomInstanceFromTranscoded(transcoded)); | |
4391 return true; | |
4392 } | |
4393 else | |
4287 { | 4394 { |
4288 throw OrthancException(ErrorCode_NotImplemented, "Cannot transcode image"); | 4395 throw OrthancException(ErrorCode_NotImplemented, "Cannot transcode image"); |
4289 } | 4396 } |
4290 else | 4397 } |
4291 { | 4398 } |
4292 *(p.target) = reinterpret_cast<OrthancPluginDicomInstance*>( | 4399 |
4293 new DicomInstanceFromTranscoded(*transcoded)); | 4400 case _OrthancPluginService_CreateMemoryBuffer: |
4294 return true; | 4401 { |
4295 } | 4402 const _OrthancPluginCreateMemoryBuffer& p = |
4296 } | 4403 *reinterpret_cast<const _OrthancPluginCreateMemoryBuffer*>(parameters); |
4404 | |
4405 p.target->size = p.size; | |
4406 | |
4407 if (p.size == 0) | |
4408 { | |
4409 p.target->data = NULL; | |
4410 } | |
4411 else | |
4412 { | |
4413 p.target->data = malloc(p.size); | |
4414 } | |
4415 | |
4416 return true; | |
4297 } | 4417 } |
4298 | 4418 |
4299 default: | 4419 default: |
4300 return false; | 4420 return false; |
4301 } | 4421 } |
4345 RegisterMoveCallback(parameters); | 4465 RegisterMoveCallback(parameters); |
4346 return true; | 4466 return true; |
4347 | 4467 |
4348 case _OrthancPluginService_RegisterDecodeImageCallback: | 4468 case _OrthancPluginService_RegisterDecodeImageCallback: |
4349 RegisterDecodeImageCallback(parameters); | 4469 RegisterDecodeImageCallback(parameters); |
4470 return true; | |
4471 | |
4472 case _OrthancPluginService_RegisterTranscoderCallback: | |
4473 RegisterTranscoderCallback(parameters); | |
4350 return true; | 4474 return true; |
4351 | 4475 |
4352 case _OrthancPluginService_RegisterJobsUnserializer: | 4476 case _OrthancPluginService_RegisterJobsUnserializer: |
4353 RegisterJobsUnserializer(parameters); | 4477 RegisterJobsUnserializer(parameters); |
4354 return true; | 4478 return true; |
4731 } | 4855 } |
4732 | 4856 |
4733 | 4857 |
4734 bool OrthancPlugins::HasCustomImageDecoder() | 4858 bool OrthancPlugins::HasCustomImageDecoder() |
4735 { | 4859 { |
4736 boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_); | 4860 boost::shared_lock<boost::shared_mutex> lock(pimpl_->decoderTranscoderMutex_); |
4737 return !pimpl_->decodeImageCallbacks_.empty(); | 4861 return !pimpl_->decodeImageCallbacks_.empty(); |
4738 } | 4862 } |
4739 | 4863 |
4740 | 4864 |
4741 ImageAccessor* OrthancPlugins::DecodeUnsafe(const void* dicom, | 4865 bool OrthancPlugins::HasCustomTranscoder() |
4742 size_t size, | 4866 { |
4743 unsigned int frame) | 4867 boost::shared_lock<boost::shared_mutex> lock(pimpl_->decoderTranscoderMutex_); |
4744 { | 4868 return !pimpl_->transcoderCallbacks_.empty(); |
4745 boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_); | 4869 } |
4870 | |
4871 | |
4872 ImageAccessor* OrthancPlugins::Decode(const void* dicom, | |
4873 size_t size, | |
4874 unsigned int frame) | |
4875 { | |
4876 boost::shared_lock<boost::shared_mutex> lock(pimpl_->decoderTranscoderMutex_); | |
4746 | 4877 |
4747 for (PImpl::DecodeImageCallbacks::const_iterator | 4878 for (PImpl::DecodeImageCallbacks::const_iterator |
4748 decoder = pimpl_->decodeImageCallbacks_.begin(); | 4879 decoder = pimpl_->decodeImageCallbacks_.begin(); |
4749 decoder != pimpl_->decodeImageCallbacks_.end(); ++decoder) | 4880 decoder != pimpl_->decodeImageCallbacks_.end(); ++decoder) |
4750 { | 4881 { |
4755 return reinterpret_cast<ImageAccessor*>(pluginImage); | 4886 return reinterpret_cast<ImageAccessor*>(pluginImage); |
4756 } | 4887 } |
4757 } | 4888 } |
4758 | 4889 |
4759 return NULL; | 4890 return NULL; |
4760 } | |
4761 | |
4762 | |
4763 ImageAccessor* OrthancPlugins::Decode(const void* dicom, | |
4764 size_t size, | |
4765 unsigned int frame) | |
4766 { | |
4767 ImageAccessor* result = DecodeUnsafe(dicom, size, frame); | |
4768 | |
4769 if (result != NULL) | |
4770 { | |
4771 return result; | |
4772 } | |
4773 else | |
4774 { | |
4775 LOG(INFO) << "The installed image decoding plugins cannot handle an image, fallback to the built-in decoder"; | |
4776 DefaultDicomImageDecoder defaultDecoder; | |
4777 return defaultDecoder.Decode(dicom, size, frame); | |
4778 } | |
4779 } | 4891 } |
4780 | 4892 |
4781 | 4893 |
4782 bool OrthancPlugins::IsAllowed(HttpMethod method, | 4894 bool OrthancPlugins::IsAllowed(HttpMethod method, |
4783 const char* uri, | 4895 const char* uri, |
5062 | 5174 |
5063 return NULL; | 5175 return NULL; |
5064 } | 5176 } |
5065 | 5177 |
5066 | 5178 |
5067 bool OrthancPlugins::Transcode(std::string& target, | 5179 class MemoryBufferRaii : public boost::noncopyable |
5068 DicomTransferSyntax& sourceSyntax /* out */, | 5180 { |
5069 DicomTransferSyntax& targetSyntax /* out */, | 5181 private: |
5070 bool& hasSopInstanceUidChanged /* out */, | 5182 OrthancPluginMemoryBuffer buffer_; |
5071 const void* buffer, | 5183 |
5072 size_t size, | 5184 public: |
5073 const std::set<DicomTransferSyntax>& allowedSyntaxes, | 5185 MemoryBufferRaii() |
5074 bool allowNewSopInstanceUid) | 5186 { |
5075 { | 5187 buffer_.size = 0; |
5076 // TODO | 5188 buffer_.data = NULL; |
5189 } | |
5190 | |
5191 ~MemoryBufferRaii() | |
5192 { | |
5193 if (buffer_.size != 0) | |
5194 { | |
5195 free(buffer_.data); | |
5196 } | |
5197 } | |
5198 | |
5199 OrthancPluginMemoryBuffer* GetObject() | |
5200 { | |
5201 return &buffer_; | |
5202 } | |
5203 | |
5204 void ToString(std::string& target) const | |
5205 { | |
5206 target.resize(buffer_.size); | |
5207 | |
5208 if (buffer_.size != 0) | |
5209 { | |
5210 memcpy(&target[0], buffer_.data, buffer_.size); | |
5211 } | |
5212 } | |
5213 }; | |
5214 | |
5215 | |
5216 bool OrthancPlugins::TranscodeBuffer(std::string& target, | |
5217 const void* buffer, | |
5218 size_t size, | |
5219 const std::set<DicomTransferSyntax>& allowedSyntaxes, | |
5220 bool allowNewSopInstanceUid) | |
5221 { | |
5222 boost::shared_lock<boost::shared_mutex> lock(pimpl_->decoderTranscoderMutex_); | |
5223 | |
5224 if (pimpl_->transcoderCallbacks_.empty()) | |
5225 { | |
5226 return NULL; | |
5227 } | |
5228 | |
5229 std::vector<const char*> uids; | |
5230 uids.reserve(allowedSyntaxes.size()); | |
5231 for (std::set<DicomTransferSyntax>::const_iterator | |
5232 it = allowedSyntaxes.begin(); it != allowedSyntaxes.end(); ++it) | |
5233 { | |
5234 uids.push_back(GetTransferSyntaxUid(*it)); | |
5235 } | |
5236 | |
5237 for (PImpl::TranscoderCallbacks::const_iterator | |
5238 transcoder = pimpl_->transcoderCallbacks_.begin(); | |
5239 transcoder != pimpl_->transcoderCallbacks_.end(); ++transcoder) | |
5240 { | |
5241 MemoryBufferRaii a; | |
5242 | |
5243 if ((*transcoder) (a.GetObject(), buffer, size, uids.empty() ? NULL : &uids[0], | |
5244 static_cast<uint32_t>(uids.size()), allowNewSopInstanceUid) == | |
5245 OrthancPluginErrorCode_Success) | |
5246 { | |
5247 a.ToString(target); | |
5248 return true; | |
5249 } | |
5250 } | |
5251 | |
5077 return false; | 5252 return false; |
5078 } | 5253 } |
5079 } | 5254 } |