Mercurial > hg > orthanc-webviewer
annotate Plugin/ViewerToolbox.cpp @ 321:705be6d59d9b default tip
fix build on tumbleweed
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 11 Jun 2024 12:57:30 +0200 |
parents | 553fa466835a |
children |
rev | line source |
---|---|
0 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
122 | 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
0 | 4 * Department, University Hospital of Liege, Belgium |
320
553fa466835a
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
316
diff
changeset
|
5 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
553fa466835a
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
316
diff
changeset
|
6 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium |
314
0a1ad7492050
update year to 2024
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
303
diff
changeset
|
7 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
0 | 8 * |
9 * This program is free software: you can redistribute it and/or | |
10 * modify it under the terms of the GNU Affero General Public License | |
11 * as published by the Free Software Foundation, either version 3 of | |
12 * the License, or (at your option) any later version. | |
13 * | |
14 * This program is distributed in the hope that it will be useful, but | |
15 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 * Affero General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU Affero General Public License | |
20 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 **/ | |
22 | |
23 | |
24 #include "ViewerToolbox.h" | |
25 | |
287 | 26 #include <Logging.h> |
266
4e9d30c19b4b
linking against orthanc framework library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
260
diff
changeset
|
27 #include <OrthancException.h> |
4e9d30c19b4b
linking against orthanc framework library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
260
diff
changeset
|
28 #include <Toolbox.h> |
0 | 29 |
275
3a9749b1dfce
link against system-wide Orthanc Framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
266
diff
changeset
|
30 // To gain access to ORTHANC_PLUGINS_VERSION_IS_ABOVE if Orthanc SDK <= 1.3.0 |
3a9749b1dfce
link against system-wide Orthanc Framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
266
diff
changeset
|
31 #include "../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h" |
172 | 32 |
0 | 33 #include <stdexcept> |
34 #include <boost/lexical_cast.hpp> | |
35 #include <sys/stat.h> | |
36 | |
37 namespace OrthancPlugins | |
38 { | |
39 bool GetStringFromOrthanc(std::string& content, | |
40 OrthancPluginContext* context, | |
41 const std::string& uri) | |
42 { | |
43 OrthancPluginMemoryBuffer answer; | |
44 | |
45 if (OrthancPluginRestApiGet(context, &answer, uri.c_str())) | |
46 { | |
47 return false; | |
48 } | |
49 | |
50 if (answer.size) | |
51 { | |
52 try | |
53 { | |
54 content.assign(reinterpret_cast<const char*>(answer.data), answer.size); | |
55 } | |
56 catch (std::bad_alloc&) | |
57 { | |
58 OrthancPluginFreeMemoryBuffer(context, &answer); | |
79 | 59 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); |
0 | 60 } |
61 } | |
62 | |
63 OrthancPluginFreeMemoryBuffer(context, &answer); | |
64 return true; | |
65 } | |
66 | |
67 | |
68 bool GetJsonFromOrthanc(Json::Value& json, | |
69 OrthancPluginContext* context, | |
70 const std::string& uri) | |
71 { | |
72 OrthancPluginMemoryBuffer answer; | |
73 | |
74 if (OrthancPluginRestApiGet(context, &answer, uri.c_str())) | |
75 { | |
76 return false; | |
77 } | |
78 | |
79 if (answer.size) | |
80 { | |
81 try | |
82 { | |
292
aadbffcee805
remove calls to deprecated classes of JsonCpp
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
287
diff
changeset
|
83 if (!Orthanc::Toolbox::ReadJsonWithoutComments(json, answer.data, answer.size)) |
0 | 84 { |
85 return false; | |
86 } | |
87 } | |
88 catch (std::runtime_error&) | |
89 { | |
90 OrthancPluginFreeMemoryBuffer(context, &answer); | |
91 return false; | |
92 } | |
93 } | |
94 | |
95 OrthancPluginFreeMemoryBuffer(context, &answer); | |
96 return true; | |
97 } | |
98 | |
99 | |
100 | |
101 | |
102 bool TokenizeVector(std::vector<float>& result, | |
103 const std::string& value, | |
104 unsigned int expectedSize) | |
105 { | |
106 std::vector<std::string> tokens; | |
107 Orthanc::Toolbox::TokenizeString(tokens, value, '\\'); | |
108 | |
109 if (tokens.size() != expectedSize) | |
110 { | |
111 return false; | |
112 } | |
113 | |
114 result.resize(tokens.size()); | |
115 | |
116 for (size_t i = 0; i < tokens.size(); i++) | |
117 { | |
118 try | |
119 { | |
120 result[i] = boost::lexical_cast<float>(tokens[i]); | |
121 } | |
122 catch (boost::bad_lexical_cast&) | |
123 { | |
124 return false; | |
125 } | |
126 } | |
127 | |
128 return true; | |
129 } | |
130 | |
131 | |
79 | 132 void CompressUsingDeflate(std::string& compressed, |
133 OrthancPluginContext* context, | |
0 | 134 const void* uncompressed, |
79 | 135 size_t uncompressedSize) |
0 | 136 { |
79 | 137 OrthancPluginMemoryBuffer tmp; |
138 | |
139 OrthancPluginErrorCode code = OrthancPluginBufferCompression( | |
140 context, &tmp, uncompressed, uncompressedSize, | |
141 OrthancPluginCompressionType_Zlib, 0 /*compress*/); | |
142 | |
143 if (code != OrthancPluginErrorCode_Success) | |
0 | 144 { |
79 | 145 throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(code)); |
0 | 146 } |
147 | |
79 | 148 try |
149 { | |
150 compressed.assign(reinterpret_cast<const char*>(tmp.data), tmp.size); | |
151 } | |
152 catch (...) | |
153 { | |
154 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); | |
155 } | |
0 | 156 |
79 | 157 OrthancPluginFreeMemoryBuffer(context, &tmp); |
0 | 158 } |
159 | |
160 | |
161 const char* GetMimeType(const std::string& path) | |
162 { | |
163 size_t dot = path.find_last_of('.'); | |
164 | |
165 std::string extension = (dot == std::string::npos) ? "" : path.substr(dot); | |
166 std::transform(extension.begin(), extension.end(), extension.begin(), tolower); | |
167 | |
168 if (extension == ".html") | |
169 { | |
170 return "text/html"; | |
171 } | |
172 else if (extension == ".css") | |
173 { | |
174 return "text/css"; | |
175 } | |
176 else if (extension == ".js") | |
177 { | |
178 return "application/javascript"; | |
179 } | |
180 else if (extension == ".gif") | |
181 { | |
182 return "image/gif"; | |
183 } | |
184 else if (extension == ".svg") | |
185 { | |
186 return "image/svg+xml"; | |
187 } | |
188 else if (extension == ".json") | |
189 { | |
190 return "application/json"; | |
191 } | |
192 else if (extension == ".xml") | |
193 { | |
194 return "application/xml"; | |
195 } | |
196 else if (extension == ".png") | |
197 { | |
198 return "image/png"; | |
199 } | |
200 else if (extension == ".jpg" || extension == ".jpeg") | |
201 { | |
202 return "image/jpeg"; | |
203 } | |
204 else | |
205 { | |
206 return "application/octet-stream"; | |
207 } | |
208 } | |
209 | |
210 | |
211 bool ReadConfiguration(Json::Value& configuration, | |
212 OrthancPluginContext* context) | |
213 { | |
33
d7bd116777eb
Use of OrthancPluginGetConfiguration
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
214 std::string s; |
0 | 215 |
216 { | |
33
d7bd116777eb
Use of OrthancPluginGetConfiguration
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
217 char* tmp = OrthancPluginGetConfiguration(context); |
d7bd116777eb
Use of OrthancPluginGetConfiguration
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
218 if (tmp == NULL) |
0 | 219 { |
260
620ed85fb514
replacing OrthancPluginLog...() by LOG(...)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
229
diff
changeset
|
220 LOG(ERROR) << "Error while retrieving the configuration from Orthanc"; |
0 | 221 return false; |
222 } | |
223 | |
33
d7bd116777eb
Use of OrthancPluginGetConfiguration
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
224 s.assign(tmp); |
d7bd116777eb
Use of OrthancPluginGetConfiguration
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
225 OrthancPluginFreeString(context, tmp); |
0 | 226 } |
227 | |
292
aadbffcee805
remove calls to deprecated classes of JsonCpp
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
287
diff
changeset
|
228 if (Orthanc::Toolbox::ReadJson(configuration, s)) |
0 | 229 { |
33
d7bd116777eb
Use of OrthancPluginGetConfiguration
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
230 return true; |
d7bd116777eb
Use of OrthancPluginGetConfiguration
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
231 } |
d7bd116777eb
Use of OrthancPluginGetConfiguration
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
232 else |
d7bd116777eb
Use of OrthancPluginGetConfiguration
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
233 { |
260
620ed85fb514
replacing OrthancPluginLog...() by LOG(...)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
229
diff
changeset
|
234 LOG(ERROR) << "Unable to parse the configuration"; |
0 | 235 return false; |
236 } | |
237 } | |
238 | |
239 | |
240 std::string GetStringValue(const Json::Value& configuration, | |
241 const std::string& key, | |
242 const std::string& defaultValue) | |
243 { | |
244 if (configuration.type() != Json::objectValue || | |
245 !configuration.isMember(key) || | |
246 configuration[key].type() != Json::stringValue) | |
247 { | |
248 return defaultValue; | |
249 } | |
250 else | |
251 { | |
252 return configuration[key].asString(); | |
253 } | |
254 } | |
255 | |
256 | |
257 int GetIntegerValue(const Json::Value& configuration, | |
258 const std::string& key, | |
259 int defaultValue) | |
260 { | |
261 if (configuration.type() != Json::objectValue || | |
262 !configuration.isMember(key) || | |
263 configuration[key].type() != Json::intValue) | |
264 { | |
265 return defaultValue; | |
266 } | |
267 else | |
268 { | |
269 return configuration[key].asInt(); | |
270 } | |
271 } | |
272 | |
273 | |
79 | 274 OrthancPluginPixelFormat Convert(Orthanc::PixelFormat format) |
0 | 275 { |
79 | 276 switch (format) |
277 { | |
278 case Orthanc::PixelFormat_Grayscale16: | |
279 return OrthancPluginPixelFormat_Grayscale16; | |
280 | |
281 case Orthanc::PixelFormat_Grayscale8: | |
282 return OrthancPluginPixelFormat_Grayscale8; | |
283 | |
284 case Orthanc::PixelFormat_RGB24: | |
285 return OrthancPluginPixelFormat_RGB24; | |
286 | |
172 | 287 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 3, 1) |
288 case Orthanc::PixelFormat_RGB48: | |
289 return OrthancPluginPixelFormat_RGB48; | |
290 #endif | |
291 | |
79 | 292 case Orthanc::PixelFormat_RGBA32: |
293 return OrthancPluginPixelFormat_RGBA32; | |
294 | |
295 case Orthanc::PixelFormat_SignedGrayscale16: | |
296 return OrthancPluginPixelFormat_SignedGrayscale16; | |
297 | |
298 default: | |
299 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
300 } | |
301 } | |
302 | |
303 | |
304 Orthanc::PixelFormat Convert(OrthancPluginPixelFormat format) | |
305 { | |
306 switch (format) | |
0 | 307 { |
79 | 308 case OrthancPluginPixelFormat_Grayscale16: |
309 return Orthanc::PixelFormat_Grayscale16; | |
310 | |
311 case OrthancPluginPixelFormat_Grayscale8: | |
312 return Orthanc::PixelFormat_Grayscale8; | |
313 | |
314 case OrthancPluginPixelFormat_RGB24: | |
315 return Orthanc::PixelFormat_RGB24; | |
316 | |
172 | 317 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 3, 1) |
318 case OrthancPluginPixelFormat_RGB48: | |
319 return Orthanc::PixelFormat_RGB48; | |
320 #endif | |
321 | |
79 | 322 case OrthancPluginPixelFormat_RGBA32: |
323 return Orthanc::PixelFormat_RGBA32; | |
324 | |
325 case OrthancPluginPixelFormat_SignedGrayscale16: | |
326 return Orthanc::PixelFormat_SignedGrayscale16; | |
0 | 327 |
79 | 328 default: |
329 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
330 } | |
331 } | |
332 | |
333 | |
334 void WriteJpegToMemory(std::string& result, | |
335 OrthancPluginContext* context, | |
336 const Orthanc::ImageAccessor& accessor, | |
337 uint8_t quality) | |
338 { | |
339 OrthancPluginMemoryBuffer tmp; | |
340 | |
341 OrthancPluginErrorCode code = OrthancPluginCompressJpegImage | |
342 (context, &tmp, Convert(accessor.GetFormat()), | |
343 accessor.GetWidth(), accessor.GetHeight(), accessor.GetPitch(), | |
99
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
79
diff
changeset
|
344 accessor.GetConstBuffer(), quality); |
79 | 345 |
346 if (code != OrthancPluginErrorCode_Success) | |
0 | 347 { |
79 | 348 throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(code)); |
0 | 349 } |
350 | |
79 | 351 try |
0 | 352 { |
79 | 353 result.assign(reinterpret_cast<const char*>(tmp.data), tmp.size); |
354 } | |
355 catch (...) | |
356 { | |
357 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); | |
0 | 358 } |
359 | |
79 | 360 OrthancPluginFreeMemoryBuffer(context, &tmp); |
361 } | |
362 | |
363 | |
364 | |
365 ImageReader::ImageReader(OrthancPluginContext* context, | |
366 const std::string& image, | |
367 OrthancPluginImageFormat format) : context_(context) | |
368 { | |
369 image_ = OrthancPluginUncompressImage(context_, image.c_str(), image.size(), format); | |
370 | |
371 if (image_ == NULL) | |
0 | 372 { |
79 | 373 throw Orthanc::OrthancException(Orthanc::ErrorCode_CorruptedFile); |
0 | 374 } |
79 | 375 } |
0 | 376 |
377 | |
79 | 378 ImageReader::~ImageReader() |
379 { | |
380 OrthancPluginFreeImage(context_, image_); | |
381 } | |
382 | |
0 | 383 |
207
3d3d00e3e715
fix for new ImageAccessor API
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
191
diff
changeset
|
384 void ImageReader::GetAccessor(Orthanc::ImageAccessor& target) const |
79 | 385 { |
207
3d3d00e3e715
fix for new ImageAccessor API
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
191
diff
changeset
|
386 target.AssignReadOnly(Convert(OrthancPluginGetImagePixelFormat(context_, image_)), |
3d3d00e3e715
fix for new ImageAccessor API
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
191
diff
changeset
|
387 OrthancPluginGetImageWidth(context_, image_), |
3d3d00e3e715
fix for new ImageAccessor API
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
191
diff
changeset
|
388 OrthancPluginGetImageHeight(context_, image_), |
3d3d00e3e715
fix for new ImageAccessor API
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
191
diff
changeset
|
389 OrthancPluginGetImagePitch(context_, image_), |
3d3d00e3e715
fix for new ImageAccessor API
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
191
diff
changeset
|
390 OrthancPluginGetImageBuffer(context_, image_)); |
0 | 391 } |
392 } |