# HG changeset patch # User Sebastien Jodogne # Date 1465574066 -7200 # Node ID 50b9bc19dc627b5b613d34527bdc9cef34e9f8f7 # Parent 5b3b2de4e01891b2b223da1bd8baeee34e2380c3 More than one custom image decoder can be installed (e.g. to handle different transfer syntaxes) diff -r 5b3b2de4e018 -r 50b9bc19dc62 NEWS --- a/NEWS Fri Jun 10 09:26:26 2016 +0200 +++ b/NEWS Fri Jun 10 17:54:26 2016 +0200 @@ -25,6 +25,7 @@ * New callback to handle C-Move requests: OrthancPluginRegisterMoveCallback() * New function: "OrthancPluginHttpClient()" to do HTTP requests with full control * New function: "OrthancPluginGenerateUuid()" to generate a UUID +* More than one custom image decoder can be installed (e.g. to handle different transfer syntaxes) Lua --- diff -r 5b3b2de4e018 -r 50b9bc19dc62 OrthancServer/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Fri Jun 10 09:26:26 2016 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Fri Jun 10 17:54:26 2016 +0200 @@ -380,7 +380,14 @@ // TODO create a cache of file std::string dicomContent; context.ReadFile(dicomContent, publicId, FileContentType_Dicom); - decoded.reset(context.GetPlugins().Decode(dicomContent.c_str(), dicomContent.size(), frame)); + decoded.reset(context.GetPlugins().DecodeUnsafe(dicomContent.c_str(), dicomContent.size(), frame)); + + /** + * Note that we call "DecodeUnsafe()": We do not fallback to + * the builtin decoder if no installed decoder plugin is able + * to decode the image. This allows us to take advantage of + * the cache below. + **/ } #endif diff -r 5b3b2de4e018 -r 50b9bc19dc62 Plugins/Engine/OrthancPlugins.cpp --- a/Plugins/Engine/OrthancPlugins.cpp Fri Jun 10 09:26:26 2016 +0200 +++ b/Plugins/Engine/OrthancPlugins.cpp Fri Jun 10 17:54:26 2016 +0200 @@ -344,6 +344,7 @@ typedef std::list OnStoredCallbacks; typedef std::list OnChangeCallbacks; typedef std::list IncomingHttpRequestFilters; + typedef std::list DecodeImageCallbacks; typedef std::map Properties; PluginsManager manager_; @@ -353,7 +354,7 @@ OnChangeCallbacks onChangeCallbacks_; OrthancPluginFindCallback findCallback_; OrthancPluginWorklistCallback worklistCallback_; - OrthancPluginDecodeImageCallback decodeImageCallback_; + DecodeImageCallbacks decodeImageCallbacks_; _OrthancPluginMoveCallback moveCallbacks_; IncomingHttpRequestFilters incomingHttpRequestFilters_; std::auto_ptr storageArea_; @@ -376,7 +377,6 @@ context_(NULL), findCallback_(NULL), worklistCallback_(NULL), - decodeImageCallback_(NULL), argc_(1), argv_(NULL) { @@ -1104,16 +1104,9 @@ boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_); - if (pimpl_->decodeImageCallback_ != NULL) - { - LOG(ERROR) << "Can only register one plugin to handle the decompression of DICOM images"; - throw OrthancException(ErrorCode_Plugin); - } - else - { - LOG(INFO) << "Plugin has registered a callback to decode DICOM images"; - pimpl_->decodeImageCallback_ = p.callback; - } + pimpl_->decodeImageCallbacks_.push_back(p.callback); + LOG(INFO) << "Plugin has registered a callback to decode DICOM images (" + << pimpl_->decodeImageCallbacks_.size() << " decoder(s) now active)"; } @@ -2968,31 +2961,48 @@ bool OrthancPlugins::HasCustomImageDecoder() { boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_); - return (pimpl_->decodeImageCallback_ != NULL); + return !pimpl_->decodeImageCallbacks_.empty(); } - ImageAccessor* OrthancPlugins::Decode(const void* dicom, - size_t size, - unsigned int frame) + ImageAccessor* OrthancPlugins::DecodeUnsafe(const void* dicom, + size_t size, + unsigned int frame) { + boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_); + + for (PImpl::DecodeImageCallbacks::const_iterator + decoder = pimpl_->decodeImageCallbacks_.begin(); + decoder != pimpl_->decodeImageCallbacks_.end(); ++decoder) { - boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_); - if (pimpl_->decodeImageCallback_ != NULL) + OrthancPluginImage* pluginImage = NULL; + if ((*decoder) (&pluginImage, dicom, size, frame) == OrthancPluginErrorCode_Success && + pluginImage != NULL) { - OrthancPluginImage* pluginImage = NULL; - if (pimpl_->decodeImageCallback_(&pluginImage, dicom, size, frame) == OrthancPluginErrorCode_Success && - pluginImage != NULL) - { - return reinterpret_cast(pluginImage); - } - - LOG(INFO) << "The installed image decoding plugins cannot handle an image, fallback to the built-in decoder"; + return reinterpret_cast(pluginImage); } } - DefaultDicomImageDecoder defaultDecoder; - return defaultDecoder.Decode(dicom, size, frame); // TODO RETURN NULL ??? + return NULL; + } + + + ImageAccessor* OrthancPlugins::Decode(const void* dicom, + size_t size, + unsigned int frame) + { + ImageAccessor* result = DecodeUnsafe(dicom, size, frame); + + if (result != NULL) + { + return result; + } + else + { + LOG(INFO) << "The installed image decoding plugins cannot handle an image, fallback to the built-in decoder"; + DefaultDicomImageDecoder defaultDecoder; + return defaultDecoder.Decode(dicom, size, frame); + } } diff -r 5b3b2de4e018 -r 50b9bc19dc62 Plugins/Engine/OrthancPlugins.h --- a/Plugins/Engine/OrthancPlugins.h Fri Jun 10 09:26:26 2016 +0200 +++ b/Plugins/Engine/OrthancPlugins.h Fri Jun 10 17:54:26 2016 +0200 @@ -260,6 +260,13 @@ bool HasCustomImageDecoder(); + // Contrarily to "Decode()", this method does not fallback to the + // builtin image decoder, if no installed custom decoder can + // handle the image (it returns NULL in this case). + ImageAccessor* DecodeUnsafe(const void* dicom, + size_t size, + unsigned int frame); + virtual ImageAccessor* Decode(const void* dicom, size_t size, unsigned int frame);