comparison Plugins/Samples/GdcmDecoder/Plugin.cpp @ 3915:7e33516965f8 transcoding

merging sample GDCM decoder and Orthanc Web viewer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 11 May 2020 15:13:16 +0200
parents 6110a4995ace
children b99acc213937
comparison
equal deleted inserted replaced
3914:e14b5a7a0f75 3915:7e33516965f8
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/ 19 **/
20 20
21 21
22 #include "../../../Core/Compatibility.h" 22 #include "../../../Core/Compatibility.h"
23 #include "../../../Core/DicomFormat/DicomMap.h"
24 #include "../../../Core/Toolbox.h"
23 #include "GdcmDecoderCache.h" 25 #include "GdcmDecoderCache.h"
24 #include "OrthancImageWrapper.h" 26
25
26 #include <orthanc/OrthancCPlugin.h>
27
28 static OrthancPluginContext* context_ = NULL;
29 static OrthancPlugins::GdcmDecoderCache cache_; 27 static OrthancPlugins::GdcmDecoderCache cache_;
28 static bool restrictTransferSyntaxes_ = false;
29 static std::set<std::string> enabledTransferSyntaxes_;
30
31
32 static bool ExtractTransferSyntax(std::string& transferSyntax,
33 const void* dicom,
34 const uint32_t size)
35 {
36 Orthanc::DicomMap header;
37 if (!Orthanc::DicomMap::ParseDicomMetaInformation(header, reinterpret_cast<const char*>(dicom), size))
38 {
39 return false;
40 }
41
42 const Orthanc::DicomValue* tag = header.TestAndGetValue(0x0002, 0x0010);
43 if (tag == NULL ||
44 tag->IsNull() ||
45 tag->IsBinary())
46 {
47 return false;
48 }
49 else
50 {
51 // Stripping spaces should not be required, as this is a UI value
52 // representation whose stripping is supported by the Orthanc
53 // core, but let's be careful...
54 transferSyntax = Orthanc::Toolbox::StripSpaces(tag->GetContent());
55 return true;
56 }
57 }
58
59
60 static bool IsTransferSyntaxEnabled(const void* dicom,
61 const uint32_t size)
62 {
63 std::string formattedSize;
64
65 {
66 char tmp[16];
67 sprintf(tmp, "%0.1fMB", static_cast<float>(size) / (1024.0f * 1024.0f));
68 formattedSize.assign(tmp);
69 }
70
71 if (!restrictTransferSyntaxes_)
72 {
73 LOG(INFO) << "Decoding one DICOM instance of " << formattedSize << " using GDCM";
74 return true;
75 }
76
77 std::string transferSyntax;
78 if (!ExtractTransferSyntax(transferSyntax, dicom, size))
79 {
80 LOG(INFO) << "Cannot extract the transfer syntax of this instance of "
81 << formattedSize << ", will use GDCM to decode it";
82 return true;
83 }
84 else if (enabledTransferSyntaxes_.find(transferSyntax) != enabledTransferSyntaxes_.end())
85 {
86 // Decoding for this transfer syntax is enabled
87 LOG(INFO) << "Using GDCM to decode this instance of " << formattedSize
88 << " with transfer syntax " << transferSyntax;
89 return true;
90 }
91 else
92 {
93 LOG(INFO) << "Won't use GDCM to decode this instance of " << formattedSize
94 << ", as its transfer syntax " << transferSyntax << " is disabled";
95 return false;
96 }
97 }
30 98
31 99
32 static OrthancPluginErrorCode DecodeImageCallback(OrthancPluginImage** target, 100 static OrthancPluginErrorCode DecodeImageCallback(OrthancPluginImage** target,
33 const void* dicom, 101 const void* dicom,
34 const uint32_t size, 102 const uint32_t size,
35 uint32_t frameIndex) 103 uint32_t frameIndex)
36 { 104 {
37 try 105 try
38 { 106 {
39 std::unique_ptr<OrthancPlugins::OrthancImageWrapper> image; 107 if (!IsTransferSyntaxEnabled(dicom, size))
108 {
109 *target = NULL;
110 return OrthancPluginErrorCode_Success;
111 }
112
113 std::unique_ptr<OrthancPlugins::OrthancImage> image;
40 114
41 #if 0 115 #if 0
42 // Do not use the cache 116 // Do not use the cache
43 OrthancPlugins::GdcmImageDecoder decoder(dicom, size); 117 OrthancPlugins::GdcmImageDecoder decoder(dicom, size);
44 image.reset(new OrthancPlugins::OrthancImageWrapper(context_, decoder.Decode(context_, frameIndex))); 118 image.reset(new OrthancPlugins::OrthancImage(decoder.Decode(frameIndex)));
45 #else 119 #else
46 image.reset(cache_.Decode(context_, dicom, size, frameIndex)); 120 image.reset(cache_.Decode(dicom, size, frameIndex));
47 #endif 121 #endif
48 122
49 *target = image->Release(); 123 *target = image->Release();
50 124
51 return OrthancPluginErrorCode_Success; 125 return OrthancPluginErrorCode_Success;
52 } 126 }
127 catch (Orthanc::OrthancException& e)
128 {
129 *target = NULL;
130
131 LOG(WARNING) << "Cannot decode image using GDCM: " << e.What();
132 return OrthancPluginErrorCode_Plugin;
133 }
53 catch (std::runtime_error& e) 134 catch (std::runtime_error& e)
54 { 135 {
55 *target = NULL; 136 *target = NULL;
56 137
57 std::string s = "Cannot decode image using GDCM: " + std::string(e.what()); 138 LOG(WARNING) << "Cannot decode image using GDCM: " << e.what();
58 OrthancPluginLogInfo(context_, s.c_str());
59 return OrthancPluginErrorCode_Plugin; 139 return OrthancPluginErrorCode_Plugin;
60 } 140 }
61 } 141 catch (...)
62 142 {
143 *target = NULL;
144
145 LOG(WARNING) << "Native exception while decoding image using GDCM";
146 return OrthancPluginErrorCode_Plugin;
147 }
148 }
149
150
151
152 /**
153 * 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"
155 * visibility). This causes the version script, if run from "Holy
156 * Build Box", to make private the 4 global functions of the plugin.
157 **/
158
159 #undef ORTHANC_PLUGINS_API
160
161 #ifdef WIN32
162 # define ORTHANC_PLUGINS_API __declspec(dllexport)
163 #elif __GNUC__ >= 4
164 # define ORTHANC_PLUGINS_API __attribute__ ((visibility ("default")))
165 #else
166 # define ORTHANC_PLUGINS_API
167 #endif
63 168
64 169
65 extern "C" 170 extern "C"
66 { 171 {
67 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) 172 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context)
68 { 173 {
69 context_ = context; 174 static const char* const KEY_GDCM = "Gdcm";
70 OrthancPluginLogWarning(context_, "Initializing the advanced decoder of medical images using GDCM"); 175 static const char* const KEY_ENABLE_GDCM = "EnableGdcm";
176 static const char* const KEY_RESTRICT_TRANSFER_SYNTAXES = "RestrictTransferSyntaxes";
177
178 OrthancPlugins::SetGlobalContext(context);
179 LOG(INFO) << "Initializing the advanced decoder of medical images using GDCM";
71 180
72 181
73 /* Check the version of the Orthanc core */ 182 /* Check the version of the Orthanc core */
74 if (OrthancPluginCheckVersion(context_) == 0) 183 if (OrthancPluginCheckVersion(context) == 0)
75 { 184 {
76 char info[1024]; 185 char info[1024];
77 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", 186 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin",
78 context_->orthancVersion, 187 context->orthancVersion,
79 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, 188 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
80 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, 189 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
81 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); 190 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
82 OrthancPluginLogError(context_, info); 191 OrthancPluginLogError(context, info);
83 return -1; 192 return -1;
84 } 193 }
85 194
86 OrthancPluginSetDescription(context_, "Advanced decoder of medical images using GDCM."); 195 OrthancPluginSetDescription(context, "Advanced decoder of medical images using GDCM.");
87 OrthancPluginRegisterDecodeImageCallback(context_, DecodeImageCallback); 196
88 197 OrthancPlugins::OrthancConfiguration global;
198
199 bool enabled = true;
200
201 if (global.IsSection(KEY_GDCM))
202 {
203 OrthancPlugins::OrthancConfiguration config;
204 global.GetSection(config, KEY_GDCM);
205
206 enabled = config.GetBooleanValue(KEY_ENABLE_GDCM, true);
207
208 if (config.LookupSetOfStrings(enabledTransferSyntaxes_, KEY_RESTRICT_TRANSFER_SYNTAXES, false))
209 {
210 restrictTransferSyntaxes_ = true;
211
212 for (std::set<std::string>::const_iterator it = enabledTransferSyntaxes_.begin();
213 it != enabledTransferSyntaxes_.end(); ++it)
214 {
215 LOG(WARNING) << "Orthanc will use GDCM to decode transfer syntax: " << *it;
216 }
217 }
218 }
219
220 if (enabled)
221 {
222 OrthancPluginRegisterDecodeImageCallback(context, DecodeImageCallback);
223 }
224 else
225 {
226 LOG(WARNING) << "The advanced decoder of medical images using GDCM is disabled";
227 }
228
89 return 0; 229 return 0;
90 } 230 }
91 231
92 232
93 ORTHANC_PLUGINS_API void OrthancPluginFinalize() 233 ORTHANC_PLUGINS_API void OrthancPluginFinalize()
94 { 234 {
235 LOG(INFO) << "Finalizing the advanced decoder of medical images using GDCM";
95 } 236 }
96 237
97 238
98 ORTHANC_PLUGINS_API const char* OrthancPluginGetName() 239 ORTHANC_PLUGINS_API const char* OrthancPluginGetName()
99 { 240 {
101 } 242 }
102 243
103 244
104 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() 245 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion()
105 { 246 {
106 return GDCM_DECODER_VERSION; 247 return PLUGIN_VERSION;
107 } 248 }
108 } 249 }