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