Mercurial > hg > orthanc
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 } |