Mercurial > hg > orthanc-stone
annotate Framework/Radiography/RadiographyScene.cpp @ 421:f87f28624b96 cache-in-radiography
tentative to make SmartLoader and RadiographyScene work together (not really working)
author | am@osimis.io |
---|---|
date | Tue, 20 Nov 2018 16:35:29 +0100 |
parents | c23df8b3433b |
children |
rev | line source |
---|---|
408 | 1 /** |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
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 "RadiographyScene.h" | |
23 | |
24 #include "../Toolbox/DicomFrameConverter.h" | |
25 | |
26 #include <Core/Images/Image.h> | |
27 #include <Core/Images/ImageProcessing.h> | |
28 #include <Core/Images/PamReader.h> | |
29 #include <Core/Images/PamWriter.h> | |
30 #include <Core/Images/PngWriter.h> | |
31 #include <Core/OrthancException.h> | |
32 #include <Core/Toolbox.h> | |
33 #include <Plugins/Samples/Common/DicomDatasetReader.h> | |
34 #include <Plugins/Samples/Common/FullOrthancDataset.h> | |
35 | |
412 | 36 #include <boost/math/special_functions/round.hpp> |
37 | |
408 | 38 |
39 namespace OrthancStone | |
40 { | |
41 RadiographyScene::LayerAccessor::LayerAccessor(RadiographyScene& scene, | |
42 size_t index) : | |
43 scene_(scene), | |
44 index_(index) | |
45 { | |
46 Layers::iterator layer = scene.layers_.find(index); | |
47 if (layer == scene.layers_.end()) | |
48 { | |
49 layer_ = NULL; | |
50 } | |
51 else | |
52 { | |
53 assert(layer->second != NULL); | |
54 layer_ = layer->second; | |
55 } | |
56 } | |
57 | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
58 |
408 | 59 RadiographyScene::LayerAccessor::LayerAccessor(RadiographyScene& scene, |
60 double x, | |
61 double y) : | |
62 scene_(scene), | |
63 index_(0) // Dummy initialization | |
64 { | |
65 if (scene.LookupLayer(index_, x, y)) | |
66 { | |
67 Layers::iterator layer = scene.layers_.find(index_); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
68 |
408 | 69 if (layer == scene.layers_.end()) |
70 { | |
71 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
72 } | |
73 else | |
74 { | |
75 assert(layer->second != NULL); | |
76 layer_ = layer->second; | |
77 } | |
78 } | |
79 else | |
80 { | |
81 layer_ = NULL; | |
82 } | |
83 } | |
84 | |
85 | |
86 RadiographyScene& RadiographyScene::LayerAccessor::GetScene() const | |
87 { | |
88 if (IsValid()) | |
89 { | |
90 return scene_; | |
91 } | |
92 else | |
93 { | |
94 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
95 } | |
96 } | |
97 | |
98 | |
99 size_t RadiographyScene::LayerAccessor::GetIndex() const | |
100 { | |
101 if (IsValid()) | |
102 { | |
103 return index_; | |
104 } | |
105 else | |
106 { | |
107 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
108 } | |
109 } | |
110 | |
111 | |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
112 RadiographyLayer& RadiographyScene::LayerAccessor::GetLayer() const |
408 | 113 { |
114 if (IsValid()) | |
115 { | |
116 return *layer_; | |
117 } | |
118 else | |
119 { | |
120 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
121 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
122 } |
408 | 123 |
124 | |
125 | |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
126 class RadiographyScene::AlphaLayer : public RadiographyLayer |
408 | 127 { |
128 private: | |
129 const RadiographyScene& scene_; | |
130 std::auto_ptr<Orthanc::ImageAccessor> alpha_; // Grayscale8 | |
131 bool useWindowing_; | |
132 float foreground_; | |
133 | |
134 public: | |
135 AlphaLayer(const RadiographyScene& scene) : | |
136 scene_(scene), | |
137 useWindowing_(true), | |
138 foreground_(0) | |
139 { | |
140 } | |
141 | |
142 | |
143 void SetForegroundValue(float foreground) | |
144 { | |
145 useWindowing_ = false; | |
146 foreground_ = foreground; | |
147 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
148 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
149 |
408 | 150 void SetAlpha(Orthanc::ImageAccessor* image) |
151 { | |
152 std::auto_ptr<Orthanc::ImageAccessor> raii(image); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
153 |
408 | 154 if (image == NULL) |
155 { | |
156 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
157 } | |
158 | |
159 if (image->GetFormat() != Orthanc::PixelFormat_Grayscale8) | |
160 { | |
161 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
162 } | |
163 | |
164 SetSize(image->GetWidth(), image->GetHeight()); | |
165 alpha_ = raii; | |
166 } | |
167 | |
168 | |
169 void LoadText(const Orthanc::Font& font, | |
170 const std::string& utf8) | |
171 { | |
172 SetAlpha(font.RenderAlpha(utf8)); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
173 } |
408 | 174 |
175 | |
176 virtual bool GetDefaultWindowing(float& center, | |
177 float& width) const | |
178 { | |
179 return false; | |
180 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
181 |
408 | 182 |
183 virtual void Render(Orthanc::ImageAccessor& buffer, | |
409 | 184 const AffineTransform2D& viewTransform, |
408 | 185 ImageInterpolation interpolation) const |
186 { | |
187 if (alpha_.get() == NULL) | |
188 { | |
189 return; | |
190 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
191 |
408 | 192 if (buffer.GetFormat() != Orthanc::PixelFormat_Float32) |
193 { | |
194 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
195 } | |
196 | |
197 unsigned int cropX, cropY, cropWidth, cropHeight; | |
198 GetCrop(cropX, cropY, cropWidth, cropHeight); | |
199 | |
409 | 200 const AffineTransform2D t = AffineTransform2D::Combine( |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
201 viewTransform, GetTransform(), |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
202 AffineTransform2D::CreateOffset(cropX, cropY)); |
408 | 203 |
204 Orthanc::ImageAccessor cropped; | |
205 alpha_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
206 |
408 | 207 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); |
409 | 208 |
209 t.Apply(tmp, cropped, interpolation, true /* clear */); | |
408 | 210 |
211 // Blit | |
212 const unsigned int width = buffer.GetWidth(); | |
213 const unsigned int height = buffer.GetHeight(); | |
214 | |
215 float value = foreground_; | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
216 |
408 | 217 if (useWindowing_) |
218 { | |
219 float center, width; | |
220 if (scene_.GetWindowing(center, width)) | |
221 { | |
222 value = center + width / 2.0f; | |
223 } | |
224 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
225 |
408 | 226 for (unsigned int y = 0; y < height; y++) |
227 { | |
228 float *q = reinterpret_cast<float*>(buffer.GetRow(y)); | |
229 const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y)); | |
230 | |
231 for (unsigned int x = 0; x < width; x++, p++, q++) | |
232 { | |
233 float a = static_cast<float>(*p) / 255.0f; | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
234 |
408 | 235 *q = (a * value + (1.0f - a) * (*q)); |
236 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
237 } |
408 | 238 } |
239 | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
240 |
408 | 241 virtual bool GetRange(float& minValue, |
242 float& maxValue) const | |
243 { | |
244 if (useWindowing_) | |
245 { | |
246 return false; | |
247 } | |
248 else | |
249 { | |
250 minValue = 0; | |
251 maxValue = 0; | |
252 | |
253 if (foreground_ < 0) | |
254 { | |
255 minValue = foreground_; | |
256 } | |
257 | |
258 if (foreground_ > 0) | |
259 { | |
260 maxValue = foreground_; | |
261 } | |
262 | |
263 return true; | |
264 } | |
265 } | |
266 }; | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
267 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
268 |
408 | 269 |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
270 class RadiographyScene::DicomLayer : public RadiographyLayer |
408 | 271 { |
272 private: | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
273 boost::shared_ptr<Orthanc::ImageAccessor> source_; // Content of PixelData |
408 | 274 std::auto_ptr<DicomFrameConverter> converter_; |
275 std::auto_ptr<Orthanc::ImageAccessor> converted_; // Float32 | |
276 | |
277 static OrthancPlugins::DicomTag ConvertTag(const Orthanc::DicomTag& tag) | |
278 { | |
279 return OrthancPlugins::DicomTag(tag.GetGroup(), tag.GetElement()); | |
280 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
281 |
408 | 282 |
283 void ApplyConverter() | |
284 { | |
285 if (source_.get() != NULL && | |
286 converter_.get() != NULL) | |
287 { | |
288 converted_.reset(converter_->ConvertFrame(*source_)); | |
289 } | |
290 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
291 |
408 | 292 public: |
293 void SetDicomTags(const OrthancPlugins::FullOrthancDataset& dataset) | |
294 { | |
295 converter_.reset(new DicomFrameConverter); | |
296 converter_->ReadParameters(dataset); | |
297 ApplyConverter(); | |
298 | |
299 std::string tmp; | |
300 Vector pixelSpacing; | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
301 |
408 | 302 if (dataset.GetStringValue(tmp, ConvertTag(Orthanc::DICOM_TAG_PIXEL_SPACING)) && |
303 LinearAlgebra::ParseVector(pixelSpacing, tmp) && | |
304 pixelSpacing.size() == 2) | |
305 { | |
306 SetPixelSpacing(pixelSpacing[0], pixelSpacing[1]); | |
307 } | |
308 | |
309 //SetPan(-0.5 * GetPixelSpacingX(), -0.5 * GetPixelSpacingY()); | |
310 | |
311 OrthancPlugins::DicomDatasetReader reader(dataset); | |
312 | |
313 unsigned int width, height; | |
314 if (!reader.GetUnsignedIntegerValue(width, ConvertTag(Orthanc::DICOM_TAG_COLUMNS)) || | |
315 !reader.GetUnsignedIntegerValue(height, ConvertTag(Orthanc::DICOM_TAG_ROWS))) | |
316 { | |
317 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
318 } | |
319 else | |
320 { | |
321 SetSize(width, height); | |
322 } | |
323 } | |
324 | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
325 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
326 void SetSourceImage(boost::shared_ptr<Orthanc::ImageAccessor> image) |
408 | 327 { |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
328 if (image.get() == NULL) |
408 | 329 { |
330 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
331 } | |
332 | |
333 SetSize(image->GetWidth(), image->GetHeight()); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
334 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
335 source_ = image; |
408 | 336 ApplyConverter(); |
337 } | |
338 | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
339 |
408 | 340 virtual void Render(Orthanc::ImageAccessor& buffer, |
409 | 341 const AffineTransform2D& viewTransform, |
408 | 342 ImageInterpolation interpolation) const |
343 { | |
344 if (converted_.get() != NULL) | |
345 { | |
346 if (converted_->GetFormat() != Orthanc::PixelFormat_Float32) | |
347 { | |
348 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
349 } | |
350 | |
351 unsigned int cropX, cropY, cropWidth, cropHeight; | |
352 GetCrop(cropX, cropY, cropWidth, cropHeight); | |
353 | |
409 | 354 AffineTransform2D t = AffineTransform2D::Combine( |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
355 viewTransform, GetTransform(), |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
356 AffineTransform2D::CreateOffset(cropX, cropY)); |
408 | 357 |
358 Orthanc::ImageAccessor cropped; | |
359 converted_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); | |
360 | |
409 | 361 t.Apply(buffer, cropped, interpolation, false); |
408 | 362 } |
363 } | |
364 | |
365 | |
366 virtual bool GetDefaultWindowing(float& center, | |
367 float& width) const | |
368 { | |
369 if (converter_.get() != NULL && | |
370 converter_->HasDefaultWindow()) | |
371 { | |
372 center = static_cast<float>(converter_->GetDefaultWindowCenter()); | |
373 width = static_cast<float>(converter_->GetDefaultWindowWidth()); | |
374 return true; | |
375 } | |
376 else | |
377 { | |
378 return false; | |
379 } | |
380 } | |
381 | |
382 | |
383 virtual bool GetRange(float& minValue, | |
384 float& maxValue) const | |
385 { | |
386 if (converted_.get() != NULL) | |
387 { | |
388 if (converted_->GetFormat() != Orthanc::PixelFormat_Float32) | |
389 { | |
390 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
391 } | |
392 | |
393 Orthanc::ImageProcessing::GetMinMaxFloatValue(minValue, maxValue, *converted_); | |
394 return true; | |
395 } | |
396 else | |
397 { | |
398 return false; | |
399 } | |
400 } | |
401 }; | |
402 | |
403 | |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
404 RadiographyLayer& RadiographyScene::RegisterLayer(RadiographyLayer* layer) |
408 | 405 { |
406 if (layer == NULL) | |
407 { | |
408 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
409 } | |
410 | |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
411 std::auto_ptr<RadiographyLayer> raii(layer); |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
412 |
408 | 413 size_t index = countLayers_++; |
414 raii->SetIndex(index); | |
415 layers_[index] = raii.release(); | |
416 | |
417 EmitMessage(GeometryChangedMessage(*this)); | |
418 EmitMessage(ContentChangedMessage(*this)); | |
419 | |
420 return *layer; | |
421 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
422 |
408 | 423 |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
424 RadiographyScene::RadiographyScene(MessageBroker& broker) : |
408 | 425 IObserver(broker), |
426 IObservable(broker), | |
427 countLayers_(0), | |
428 hasWindowing_(false), | |
429 windowingCenter_(0), // Dummy initialization | |
430 windowingWidth_(0) // Dummy initialization | |
431 { | |
432 } | |
433 | |
434 | |
435 RadiographyScene::~RadiographyScene() | |
436 { | |
437 for (Layers::iterator it = layers_.begin(); it != layers_.end(); it++) | |
438 { | |
439 assert(it->second != NULL); | |
440 delete it->second; | |
441 } | |
442 } | |
443 | |
444 | |
445 bool RadiographyScene::GetWindowing(float& center, | |
446 float& width) const | |
447 { | |
448 if (hasWindowing_) | |
449 { | |
450 center = windowingCenter_; | |
451 width = windowingWidth_; | |
452 return true; | |
453 } | |
454 else | |
455 { | |
456 return false; | |
457 } | |
458 } | |
459 | |
460 | |
461 void RadiographyScene::GetWindowingWithDefault(float& center, | |
462 float& width) const | |
463 { | |
464 if (!GetWindowing(center, width)) | |
465 { | |
466 center = 128; | |
467 width = 256; | |
468 } | |
469 } | |
470 | |
471 | |
472 void RadiographyScene::SetWindowing(float center, | |
473 float width) | |
474 { | |
475 hasWindowing_ = true; | |
476 windowingCenter_ = center; | |
477 windowingWidth_ = width; | |
478 } | |
479 | |
480 | |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
481 RadiographyLayer& RadiographyScene::LoadText(const Orthanc::Font& font, |
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
482 const std::string& utf8) |
408 | 483 { |
484 std::auto_ptr<AlphaLayer> alpha(new AlphaLayer(*this)); | |
485 alpha->LoadText(font, utf8); | |
486 | |
487 return RegisterLayer(alpha.release()); | |
488 } | |
489 | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
490 |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
491 RadiographyLayer& RadiographyScene::LoadTestBlock(unsigned int width, |
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
492 unsigned int height) |
408 | 493 { |
494 std::auto_ptr<Orthanc::Image> block(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, width, height, false)); | |
495 | |
496 for (unsigned int padding = 0; | |
497 (width > 2 * padding) && (height > 2 * padding); | |
498 padding++) | |
499 { | |
500 uint8_t color; | |
501 if (255 > 10 * padding) | |
502 { | |
503 color = 255 - 10 * padding; | |
504 } | |
505 else | |
506 { | |
507 color = 0; | |
508 } | |
509 | |
510 Orthanc::ImageAccessor region; | |
511 block->GetRegion(region, padding, padding, width - 2 * padding, height - 2 * padding); | |
512 Orthanc::ImageProcessing::Set(region, color); | |
513 } | |
514 | |
515 std::auto_ptr<AlphaLayer> alpha(new AlphaLayer(*this)); | |
516 alpha->SetAlpha(block.release()); | |
517 | |
518 return RegisterLayer(alpha.release()); | |
519 } | |
520 | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
521 |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
522 RadiographyLayer& RadiographyScene::LoadDicomFrame(OrthancApiClient& orthanc, |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
523 const std::string& instance, |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
524 unsigned int frame, |
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
525 bool httpCompression) |
408 | 526 { |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
527 RadiographyLayer& layer = RegisterLayer(new DicomLayer); |
408 | 528 |
529 { | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
530 IWebService::HttpHeaders headers; |
408 | 531 std::string uri = "/instances/" + instance + "/tags"; |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
532 |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
533 orthanc.GetBinaryAsync( |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
534 uri, headers, |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
535 new Callable<RadiographyScene, OrthancApiClient::BinaryResponseReadyMessage> |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
536 (*this, &RadiographyScene::OnTagsReceived), NULL, |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
537 new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); |
408 | 538 } |
539 | |
540 { | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
541 IWebService::HttpHeaders headers; |
408 | 542 headers["Accept"] = "image/x-portable-arbitrarymap"; |
543 | |
544 if (httpCompression) | |
545 { | |
546 headers["Accept-Encoding"] = "gzip"; | |
547 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
548 |
408 | 549 std::string uri = ("/instances/" + instance + "/frames/" + |
550 boost::lexical_cast<std::string>(frame) + "/image-uint16"); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
551 |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
552 orthanc.GetBinaryAsync( |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
553 uri, headers, |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
554 new Callable<RadiographyScene, OrthancApiClient::BinaryResponseReadyMessage> |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
555 (*this, &RadiographyScene::OnFrameReceived), NULL, |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
556 new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); |
408 | 557 } |
558 | |
559 return layer; | |
560 } | |
561 | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
562 |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
563 RadiographyLayer& RadiographyScene::LoadDicomWebFrame(IWebService& web) |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
564 { |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
565 RadiographyLayer& layer = RegisterLayer(new DicomLayer); |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
566 |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
567 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
568 return layer; |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
569 } |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
570 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
571 RadiographyLayer& RadiographyScene::SetFrame(IVolumeSlicer* slice) |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
572 { |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
573 RadiographyLayer& layer = RegisterLayer(new DicomLayer); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
574 layersIndexBySlice_[slice] = layer.GetIndex(); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
575 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
576 slice->RegisterObserverCallback(new Callable<RadiographyScene, IVolumeSlicer::TagsReadyMessage> |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
577 (*this, &RadiographyScene::OnTagsReady)); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
578 slice->RegisterObserverCallback(new Callable<RadiographyScene, IVolumeSlicer::FrameReadyMessage> |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
579 (*this, &RadiographyScene::OnImageReady)); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
580 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
581 // TODO: register failures |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
582 |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
583 return layer; |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
584 } |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
585 |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
586 void RadiographyScene::OnTagsReady(const IVolumeSlicer::TagsReadyMessage &message) |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
587 { |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
588 size_t layerIndex = layersIndexBySlice_[&(message.GetOrigin())]; |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
589 Layers::iterator layer = layers_.find(layerIndex); |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
590 |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
591 if (layer != layers_.end()) |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
592 { |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
593 assert(layer->second != NULL); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
594 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
595 const OrthancPlugins::FullOrthancDataset& dicom = message.GetDicomTags(); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
596 dynamic_cast<DicomLayer*>(layer->second)->SetDicomTags(dicom); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
597 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
598 float c, w; |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
599 if (!hasWindowing_ && |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
600 layer->second->GetDefaultWindowing(c, w)) |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
601 { |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
602 hasWindowing_ = true; |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
603 windowingCenter_ = c; |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
604 windowingWidth_ = w; |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
605 } |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
606 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
607 EmitMessage(GeometryChangedMessage(*this)); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
608 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
609 CoordinateSystem3D dummy; |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
610 message.GetOrigin().ScheduleLayerCreation(dummy); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
611 } |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
612 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
613 } |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
614 |
408 | 615 void RadiographyScene::OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) |
616 { | |
617 size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&> | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
618 (message.GetPayload()).GetValue(); |
408 | 619 |
620 LOG(INFO) << "JSON received: " << message.GetUri().c_str() | |
621 << " (" << message.GetAnswerSize() << " bytes) for layer " << index; | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
622 |
408 | 623 Layers::iterator layer = layers_.find(index); |
624 if (layer != layers_.end()) | |
625 { | |
626 assert(layer->second != NULL); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
627 |
408 | 628 OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer(), message.GetAnswerSize()); |
629 dynamic_cast<DicomLayer*>(layer->second)->SetDicomTags(dicom); | |
630 | |
631 float c, w; | |
632 if (!hasWindowing_ && | |
633 layer->second->GetDefaultWindowing(c, w)) | |
634 { | |
635 hasWindowing_ = true; | |
636 windowingCenter_ = c; | |
637 windowingWidth_ = w; | |
638 } | |
639 | |
640 EmitMessage(GeometryChangedMessage(*this)); | |
641 } | |
642 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
643 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
644 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
645 void RadiographyScene::OnImageReady(const IVolumeSlicer::FrameReadyMessage &message) |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
646 { |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
647 size_t layerIndex = layersIndexBySlice_[&(message.GetOrigin())]; |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
648 Layers::iterator layer = layers_.find(layerIndex); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
649 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
650 if (layer != layers_.end()) |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
651 { |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
652 assert(layer->second != NULL); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
653 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
654 dynamic_cast<DicomLayer*>(layer->second)->SetSourceImage(message.GetImage()); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
655 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
656 EmitMessage(ContentChangedMessage(*this)); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
657 } |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
658 } |
408 | 659 |
660 void RadiographyScene::OnFrameReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) | |
661 { | |
662 size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&>(message.GetPayload()).GetValue(); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
663 |
408 | 664 LOG(INFO) << "DICOM frame received: " << message.GetUri().c_str() |
665 << " (" << message.GetAnswerSize() << " bytes) for layer " << index; | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
666 |
408 | 667 Layers::iterator layer = layers_.find(index); |
668 if (layer != layers_.end()) | |
669 { | |
670 assert(layer->second != NULL); | |
671 | |
672 std::string content; | |
673 if (message.GetAnswerSize() > 0) | |
674 { | |
675 content.assign(reinterpret_cast<const char*>(message.GetAnswer()), message.GetAnswerSize()); | |
676 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
677 |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
678 boost::shared_ptr<Orthanc::PamReader> reader(new Orthanc::PamReader); |
408 | 679 reader->ReadFromMemory(content); |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
680 dynamic_cast<DicomLayer*>(layer->second)->SetSourceImage(reader); |
408 | 681 |
682 EmitMessage(ContentChangedMessage(*this)); | |
683 } | |
684 } | |
685 | |
686 | |
687 Extent2D RadiographyScene::GetSceneExtent() const | |
688 { | |
689 Extent2D extent; | |
690 | |
691 for (Layers::const_iterator it = layers_.begin(); | |
692 it != layers_.end(); ++it) | |
693 { | |
694 assert(it->second != NULL); | |
695 extent.Union(it->second->GetExtent()); | |
696 } | |
697 | |
698 return extent; | |
699 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
700 |
408 | 701 |
702 void RadiographyScene::Render(Orthanc::ImageAccessor& buffer, | |
409 | 703 const AffineTransform2D& viewTransform, |
408 | 704 ImageInterpolation interpolation) const |
705 { | |
706 Orthanc::ImageProcessing::Set(buffer, 0); | |
707 | |
708 // Render layers in the background-to-foreground order | |
709 for (size_t index = 0; index < countLayers_; index++) | |
710 { | |
711 Layers::const_iterator it = layers_.find(index); | |
712 if (it != layers_.end()) | |
713 { | |
714 assert(it->second != NULL); | |
715 it->second->Render(buffer, viewTransform, interpolation); | |
716 } | |
717 } | |
718 } | |
719 | |
720 | |
721 bool RadiographyScene::LookupLayer(size_t& index /* out */, | |
722 double x, | |
723 double y) const | |
724 { | |
725 // Render layers in the foreground-to-background order | |
726 for (size_t i = countLayers_; i > 0; i--) | |
727 { | |
728 index = i - 1; | |
729 Layers::const_iterator it = layers_.find(index); | |
730 if (it != layers_.end()) | |
731 { | |
732 assert(it->second != NULL); | |
733 if (it->second->Contains(x, y)) | |
734 { | |
735 return true; | |
736 } | |
737 } | |
738 } | |
739 | |
740 return false; | |
741 } | |
742 | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
743 |
408 | 744 void RadiographyScene::DrawBorder(CairoContext& context, |
745 unsigned int layer, | |
746 double zoom) | |
747 { | |
748 Layers::const_iterator found = layers_.find(layer); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
749 |
408 | 750 if (found != layers_.end()) |
751 { | |
752 context.SetSourceColor(255, 0, 0); | |
753 found->second->DrawBorders(context, zoom); | |
754 } | |
755 } | |
756 | |
757 | |
758 void RadiographyScene::GetRange(float& minValue, | |
759 float& maxValue) const | |
760 { | |
761 bool first = true; | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
762 |
408 | 763 for (Layers::const_iterator it = layers_.begin(); |
764 it != layers_.end(); it++) | |
765 { | |
766 assert(it->second != NULL); | |
767 | |
768 float a, b; | |
769 if (it->second->GetRange(a, b)) | |
770 { | |
771 if (first) | |
772 { | |
773 minValue = a; | |
774 maxValue = b; | |
775 first = false; | |
776 } | |
777 else | |
778 { | |
779 minValue = std::min(a, minValue); | |
780 maxValue = std::max(b, maxValue); | |
781 } | |
782 } | |
783 } | |
784 | |
785 if (first) | |
786 { | |
787 minValue = 0; | |
788 maxValue = 0; | |
789 } | |
790 } | |
791 | |
792 | |
793 // Export using PAM is faster than using PNG, but requires Orthanc | |
794 // core >= 1.4.3 | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
795 void RadiographyScene::ExportDicom(OrthancApiClient& orthanc, |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
796 const Orthanc::DicomMap& dicom, |
408 | 797 double pixelSpacingX, |
798 double pixelSpacingY, | |
799 bool invert, | |
800 ImageInterpolation interpolation, | |
801 bool usePam) | |
802 { | |
803 if (pixelSpacingX <= 0 || | |
804 pixelSpacingY <= 0) | |
805 { | |
806 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
807 } | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
808 |
408 | 809 LOG(INFO) << "Exporting DICOM"; |
810 | |
811 Extent2D extent = GetSceneExtent(); | |
812 | |
813 int w = std::ceil(extent.GetWidth() / pixelSpacingX); | |
814 int h = std::ceil(extent.GetHeight() / pixelSpacingY); | |
815 | |
816 if (w < 0 || h < 0) | |
817 { | |
818 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
819 } | |
820 | |
821 Orthanc::Image layers(Orthanc::PixelFormat_Float32, | |
822 static_cast<unsigned int>(w), | |
823 static_cast<unsigned int>(h), false); | |
824 | |
409 | 825 AffineTransform2D view = AffineTransform2D::Combine( |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
826 AffineTransform2D::CreateScaling(1.0 / pixelSpacingX, 1.0 / pixelSpacingY), |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
827 AffineTransform2D::CreateOffset(-extent.GetX1(), -extent.GetY1())); |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
828 |
408 | 829 Render(layers, view, interpolation); |
830 | |
831 Orthanc::Image rendered(Orthanc::PixelFormat_Grayscale16, | |
832 layers.GetWidth(), layers.GetHeight(), false); | |
833 Orthanc::ImageProcessing::Convert(rendered, layers); | |
834 | |
835 std::string base64; | |
836 | |
837 { | |
838 std::string content; | |
839 | |
840 if (usePam) | |
841 { | |
842 Orthanc::PamWriter writer; | |
843 writer.WriteToMemory(content, rendered); | |
844 } | |
845 else | |
846 { | |
847 Orthanc::PngWriter writer; | |
848 writer.WriteToMemory(content, rendered); | |
849 } | |
850 | |
851 Orthanc::Toolbox::EncodeBase64(base64, content); | |
852 } | |
853 | |
854 std::set<Orthanc::DicomTag> tags; | |
855 dicom.GetTags(tags); | |
856 | |
857 Json::Value json = Json::objectValue; | |
858 json["Tags"] = Json::objectValue; | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
859 |
408 | 860 for (std::set<Orthanc::DicomTag>::const_iterator |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
861 tag = tags.begin(); tag != tags.end(); ++tag) |
408 | 862 { |
863 const Orthanc::DicomValue& value = dicom.GetValue(*tag); | |
864 if (!value.IsNull() && | |
865 !value.IsBinary()) | |
866 { | |
867 json["Tags"][tag->Format()] = value.GetContent(); | |
868 } | |
869 } | |
870 | |
871 json["Tags"][Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION.Format()] = | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
872 (invert ? "MONOCHROME1" : "MONOCHROME2"); |
408 | 873 |
874 // WARNING: The order of PixelSpacing is Y/X. We use "%0.8f" to | |
875 // avoid floating-point numbers to grow over 16 characters, | |
876 // which would be invalid according to DICOM standard | |
877 // ("dciodvfy" would complain). | |
878 char buf[32]; | |
879 sprintf(buf, "%0.8f\\%0.8f", pixelSpacingY, pixelSpacingX); | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
880 |
408 | 881 json["Tags"][Orthanc::DICOM_TAG_PIXEL_SPACING.Format()] = buf; |
882 | |
883 float center, width; | |
884 if (GetWindowing(center, width)) | |
885 { | |
886 json["Tags"][Orthanc::DICOM_TAG_WINDOW_CENTER.Format()] = | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
887 boost::lexical_cast<std::string>(boost::math::iround(center)); |
408 | 888 |
889 json["Tags"][Orthanc::DICOM_TAG_WINDOW_WIDTH.Format()] = | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
890 boost::lexical_cast<std::string>(boost::math::iround(width)); |
408 | 891 } |
892 | |
893 // This is Data URI scheme: https://en.wikipedia.org/wiki/Data_URI_scheme | |
894 json["Content"] = ("data:" + | |
895 std::string(usePam ? Orthanc::MIME_PAM : Orthanc::MIME_PNG) + | |
896 ";base64," + base64); | |
897 | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
898 orthanc.PostJsonAsyncExpectJson( |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
899 "/tools/create-dicom", json, |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
900 new Callable<RadiographyScene, OrthancApiClient::JsonResponseReadyMessage> |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
901 (*this, &RadiographyScene::OnDicomExported), |
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
902 NULL, NULL); |
408 | 903 } |
904 | |
905 | |
906 void RadiographyScene::OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message) | |
907 { | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
908 LOG(INFO) << "DICOM export was successful: " |
408 | 909 << message.GetJson().toStyledString(); |
910 } | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
911 |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
912 |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
913 void RadiographyScene::OnDicomWebReceived(const IWebService::HttpRequestSuccessMessage& message) |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
914 { |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
915 LOG(INFO) << "DICOMweb WADO-RS received: " << message.GetAnswerSize() << " bytes"; |
418 | 916 |
917 const IWebService::HttpHeaders& h = message.GetAnswerHttpHeaders(); | |
918 for (IWebService::HttpHeaders::const_iterator | |
421
f87f28624b96
tentative to make SmartLoader and RadiographyScene work together (not really working)
am@osimis.io
parents:
418
diff
changeset
|
919 it = h.begin(); it != h.end(); ++it) |
418 | 920 { |
921 printf("[%s] = [%s]\n", it->first.c_str(), it->second.c_str()); | |
922 } | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
923 } |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
924 |
408 | 925 } |