Mercurial > hg > orthanc-stone
annotate Framework/Radiography/RadiographyScene.cpp @ 1205:6009c59d8676 broker
fix to sdl
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 02 Dec 2019 14:32:05 +0100 |
parents | b519c1c878f1 |
children | 21c2b0eee53c |
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 | |
439 | 5 * Copyright (C) 2017-2019 Osimis S.A., Belgium |
408 | 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 | |
430 | 24 #include "RadiographyAlphaLayer.h" |
25 #include "RadiographyDicomLayer.h" | |
26 #include "RadiographyTextLayer.h" | |
475
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
27 #include "RadiographyMaskLayer.h" |
732
c35e98d22764
move Deprecated classes to a separate folder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
726
diff
changeset
|
28 #include "../Deprecated/Toolbox/DicomFrameConverter.h" |
408 | 29 |
30 #include <Core/Images/Image.h> | |
31 #include <Core/Images/ImageProcessing.h> | |
32 #include <Core/Images/PamReader.h> | |
33 #include <Core/Images/PamWriter.h> | |
34 #include <Core/Images/PngWriter.h> | |
35 #include <Core/OrthancException.h> | |
36 #include <Core/Toolbox.h> | |
37 #include <Plugins/Samples/Common/DicomDatasetReader.h> | |
38 #include <Plugins/Samples/Common/FullOrthancDataset.h> | |
39 | |
412 | 40 #include <boost/math/special_functions/round.hpp> |
41 | |
408 | 42 |
43 namespace OrthancStone | |
44 { | |
45 RadiographyScene::LayerAccessor::LayerAccessor(RadiographyScene& scene, | |
46 size_t index) : | |
47 scene_(scene), | |
48 index_(index) | |
49 { | |
50 Layers::iterator layer = scene.layers_.find(index); | |
51 if (layer == scene.layers_.end()) | |
52 { | |
53 layer_ = NULL; | |
54 } | |
55 else | |
56 { | |
57 assert(layer->second != NULL); | |
58 layer_ = layer->second; | |
59 } | |
60 } | |
61 | |
426 | 62 |
408 | 63 RadiographyScene::LayerAccessor::LayerAccessor(RadiographyScene& scene, |
64 double x, | |
65 double y) : | |
66 scene_(scene), | |
67 index_(0) // Dummy initialization | |
68 { | |
69 if (scene.LookupLayer(index_, x, y)) | |
70 { | |
71 Layers::iterator layer = scene.layers_.find(index_); | |
426 | 72 |
408 | 73 if (layer == scene.layers_.end()) |
74 { | |
75 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
76 } | |
77 else | |
78 { | |
79 assert(layer->second != NULL); | |
80 layer_ = layer->second; | |
81 } | |
82 } | |
83 else | |
84 { | |
85 layer_ = NULL; | |
86 } | |
87 } | |
88 | |
89 | |
90 RadiographyScene& RadiographyScene::LayerAccessor::GetScene() const | |
91 { | |
92 if (IsValid()) | |
93 { | |
94 return scene_; | |
95 } | |
96 else | |
97 { | |
98 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
99 } | |
100 } | |
101 | |
102 | |
103 size_t RadiographyScene::LayerAccessor::GetIndex() const | |
104 { | |
105 if (IsValid()) | |
106 { | |
107 return index_; | |
108 } | |
109 else | |
110 { | |
111 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
112 } | |
113 } | |
114 | |
115 | |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
116 RadiographyLayer& RadiographyScene::LayerAccessor::GetLayer() const |
408 | 117 { |
118 if (IsValid()) | |
119 { | |
120 return *layer_; | |
121 } | |
122 else | |
123 { | |
124 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
125 } | |
426 | 126 } |
408 | 127 |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
128 RadiographyLayer& RadiographyScene::RegisterLayer(RadiographyLayer* layer) |
408 | 129 { |
130 if (layer == NULL) | |
131 { | |
132 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
133 } | |
134 | |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
135 std::auto_ptr<RadiographyLayer> raii(layer); |
426 | 136 |
1199
922d2e61aa5d
RadiograpyScene: can now remove any layer + new key wrappers for Delete/Backspace
Alain Mazy <alain@mazy.be>
parents:
1196
diff
changeset
|
137 size_t index = nextLayerIndex_++; |
408 | 138 raii->SetIndex(index); |
139 layers_[index] = raii.release(); | |
140 | |
623
42dadae61fa9
renamed IObservable::EmitMessage() as BroadcastMessage()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
605
diff
changeset
|
141 BroadcastMessage(GeometryChangedMessage(*this, *layer)); |
42dadae61fa9
renamed IObservable::EmitMessage() as BroadcastMessage()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
605
diff
changeset
|
142 BroadcastMessage(ContentChangedMessage(*this, *layer)); |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
143 Register<RadiographyLayer::LayerEditedMessage>(*layer, &RadiographyScene::OnLayerEdited); |
408 | 144 |
145 return *layer; | |
146 } | |
426 | 147 |
876 | 148 size_t RadiographyScene::GetApproximateMemoryUsage() const |
149 { | |
150 size_t size = 0; | |
151 for (Layers::const_iterator it = layers_.begin(); it != layers_.end(); it++) | |
152 { | |
153 size += it->second->GetApproximateMemoryUsage(); | |
154 } | |
155 return size; | |
156 } | |
157 | |
503
77e0eb83ff63
layers are now Observable and emitting LayerEdited messages
amazy
parents:
488
diff
changeset
|
158 void RadiographyScene::OnLayerEdited(const RadiographyLayer::LayerEditedMessage& message) |
77e0eb83ff63
layers are now Observable and emitting LayerEdited messages
amazy
parents:
488
diff
changeset
|
159 { |
623
42dadae61fa9
renamed IObservable::EmitMessage() as BroadcastMessage()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
605
diff
changeset
|
160 BroadcastMessage(RadiographyScene::LayerEditedMessage(*this, message.GetOrigin())); |
503
77e0eb83ff63
layers are now Observable and emitting LayerEdited messages
amazy
parents:
488
diff
changeset
|
161 } |
408 | 162 |
1200 | 163 |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
164 RadiographyScene::RadiographyScene() : |
1199
922d2e61aa5d
RadiograpyScene: can now remove any layer + new key wrappers for Delete/Backspace
Alain Mazy <alain@mazy.be>
parents:
1196
diff
changeset
|
165 nextLayerIndex_(0), |
408 | 166 hasWindowing_(false), |
167 windowingCenter_(0), // Dummy initialization | |
168 windowingWidth_(0) // Dummy initialization | |
169 { | |
170 } | |
171 | |
172 | |
173 RadiographyScene::~RadiographyScene() | |
174 { | |
175 for (Layers::iterator it = layers_.begin(); it != layers_.end(); it++) | |
176 { | |
177 assert(it->second != NULL); | |
178 delete it->second; | |
179 } | |
180 } | |
181 | |
739
be9c1530d40a
deprecating enum SliceImageQuality
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
182 RadiographyPhotometricDisplayMode RadiographyScene::GetPreferredPhotomotricDisplayMode() const |
432
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
183 { |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
184 // return the mode of the first layer who "cares" about its display mode (normaly, the one and only layer that is a DicomLayer) |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
185 for (Layers::const_iterator it = layers_.begin(); it != layers_.end(); it++) |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
186 { |
739
be9c1530d40a
deprecating enum SliceImageQuality
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
187 if (it->second->GetPreferredPhotomotricDisplayMode() != RadiographyPhotometricDisplayMode_Default) |
432
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
188 { |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
189 return it->second->GetPreferredPhotomotricDisplayMode(); |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
190 } |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
191 } |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
192 |
739
be9c1530d40a
deprecating enum SliceImageQuality
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
193 return RadiographyPhotometricDisplayMode_Default; |
432
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
194 } |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
195 |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
196 |
430 | 197 void RadiographyScene::GetLayersIndexes(std::vector<size_t>& output) const |
198 { | |
199 for (Layers::const_iterator it = layers_.begin(); it != layers_.end(); it++) | |
200 { | |
201 output.push_back(it->first); | |
202 } | |
203 } | |
204 | |
425 | 205 void RadiographyScene::RemoveLayer(size_t layerIndex) |
206 { | |
428
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
426
diff
changeset
|
207 LOG(INFO) << "Removing layer: " << layerIndex; |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
426
diff
changeset
|
208 |
571
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
209 Layers::iterator found = layers_.find(layerIndex); |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
210 |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
211 if (found == layers_.end()) |
425 | 212 { |
213 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
214 } | |
571
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
215 else |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
216 { |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
217 assert(found->second != NULL); |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
218 delete found->second; |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
219 |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
220 layers_.erase(found); |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
221 |
1199
922d2e61aa5d
RadiograpyScene: can now remove any layer + new key wrappers for Delete/Backspace
Alain Mazy <alain@mazy.be>
parents:
1196
diff
changeset
|
222 LOG(INFO) << "Removing layer, there are now : " << layers_.size() << " layers"; |
1131
4663f158c748
RadiographyWidget is now notified when a layer is removed from the scene
Alain Mazy <alain@mazy.be>
parents:
1112
diff
changeset
|
223 |
4663f158c748
RadiographyWidget is now notified when a layer is removed from the scene
Alain Mazy <alain@mazy.be>
parents:
1112
diff
changeset
|
224 BroadcastMessage(RadiographyScene::LayerRemovedMessage(*this, layerIndex)); |
571
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
225 } |
425 | 226 } |
227 | |
430 | 228 const RadiographyLayer& RadiographyScene::GetLayer(size_t layerIndex) const |
425 | 229 { |
571
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
230 Layers::const_iterator found = layers_.find(layerIndex); |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
231 |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
232 if (found == layers_.end()) |
425 | 233 { |
234 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
235 } | |
571
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
236 else |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
237 { |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
238 assert(found->second != NULL); |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
239 return *found->second; |
a29f9628369e
fix build on visual studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
553
diff
changeset
|
240 } |
425 | 241 } |
408 | 242 |
1201 | 243 RadiographyLayer& RadiographyScene::GetLayer(size_t layerIndex) |
244 { | |
245 Layers::const_iterator found = layers_.find(layerIndex); | |
246 | |
247 if (found == layers_.end()) | |
248 { | |
249 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
250 } | |
251 else | |
252 { | |
253 assert(found->second != NULL); | |
254 return *found->second; | |
255 } | |
256 } | |
257 | |
408 | 258 bool RadiographyScene::GetWindowing(float& center, |
259 float& width) const | |
260 { | |
261 if (hasWindowing_) | |
262 { | |
263 center = windowingCenter_; | |
264 width = windowingWidth_; | |
265 return true; | |
266 } | |
267 else | |
268 { | |
269 return false; | |
270 } | |
271 } | |
272 | |
273 | |
274 void RadiographyScene::GetWindowingWithDefault(float& center, | |
275 float& width) const | |
276 { | |
277 if (!GetWindowing(center, width)) | |
278 { | |
279 center = 128; | |
280 width = 256; | |
281 } | |
282 } | |
283 | |
284 | |
285 void RadiographyScene::SetWindowing(float center, | |
286 float width) | |
287 { | |
288 hasWindowing_ = true; | |
289 windowingCenter_ = center; | |
290 windowingWidth_ = width; | |
503
77e0eb83ff63
layers are now Observable and emitting LayerEdited messages
amazy
parents:
488
diff
changeset
|
291 |
623
42dadae61fa9
renamed IObservable::EmitMessage() as BroadcastMessage()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
605
diff
changeset
|
292 BroadcastMessage(RadiographyScene::WindowingChangedMessage(*this)); |
408 | 293 } |
294 | |
295 | |
1201 | 296 RadiographyLayer& RadiographyScene::UpdateText(size_t layerIndex, |
297 const std::string& utf8, | |
298 unsigned int fontSize, | |
299 uint8_t foreground) | |
300 { | |
301 RadiographyTextLayer& textLayer = dynamic_cast<RadiographyTextLayer&>(GetLayer(layerIndex)); | |
302 textLayer.SetText(utf8, fontSize, foreground); | |
303 | |
304 BroadcastMessage(RadiographyScene::ContentChangedMessage(*this, textLayer)); | |
305 BroadcastMessage(RadiographyScene::LayerEditedMessage(*this, textLayer)); | |
306 return textLayer; | |
307 } | |
308 | |
309 | |
1190 | 310 RadiographyLayer& RadiographyScene::LoadText(const std::string& utf8, |
1196
a5f2a6b04a31
RadiographyScene: windowing is now only applied to the Dicom layer
Alain Mazy <alain@mazy.be>
parents:
1190
diff
changeset
|
311 unsigned int fontSize, |
1190 | 312 uint8_t foreground, |
430 | 313 RadiographyLayer::Geometry* geometry) |
408 | 314 { |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
315 std::auto_ptr<RadiographyTextLayer> alpha(new RadiographyTextLayer(*this)); |
1201 | 316 alpha->SetText(utf8, fontSize, foreground); |
430 | 317 if (geometry != NULL) |
318 { | |
319 alpha->SetGeometry(*geometry); | |
320 } | |
408 | 321 |
1199
922d2e61aa5d
RadiograpyScene: can now remove any layer + new key wrappers for Delete/Backspace
Alain Mazy <alain@mazy.be>
parents:
1196
diff
changeset
|
322 RadiographyLayer& registeredLayer = RegisterLayer(alpha.release()); |
922d2e61aa5d
RadiograpyScene: can now remove any layer + new key wrappers for Delete/Backspace
Alain Mazy <alain@mazy.be>
parents:
1196
diff
changeset
|
323 |
922d2e61aa5d
RadiograpyScene: can now remove any layer + new key wrappers for Delete/Backspace
Alain Mazy <alain@mazy.be>
parents:
1196
diff
changeset
|
324 BroadcastMessage(RadiographyScene::LayerEditedMessage(*this, registeredLayer)); |
922d2e61aa5d
RadiograpyScene: can now remove any layer + new key wrappers for Delete/Backspace
Alain Mazy <alain@mazy.be>
parents:
1196
diff
changeset
|
325 return registeredLayer; |
408 | 326 } |
327 | |
426 | 328 |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
329 RadiographyLayer& RadiographyScene::LoadTestBlock(unsigned int width, |
430 | 330 unsigned int height, |
331 RadiographyLayer::Geometry* geometry) | |
408 | 332 { |
333 std::auto_ptr<Orthanc::Image> block(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, width, height, false)); | |
334 | |
335 for (unsigned int padding = 0; | |
336 (width > 2 * padding) && (height > 2 * padding); | |
337 padding++) | |
338 { | |
339 uint8_t color; | |
340 if (255 > 10 * padding) | |
341 { | |
342 color = 255 - 10 * padding; | |
343 } | |
344 else | |
345 { | |
346 color = 0; | |
347 } | |
348 | |
349 Orthanc::ImageAccessor region; | |
350 block->GetRegion(region, padding, padding, width - 2 * padding, height - 2 * padding); | |
351 Orthanc::ImageProcessing::Set(region, color); | |
352 } | |
353 | |
430 | 354 return LoadAlphaBitmap(block.release(), geometry); |
355 } | |
356 | |
488 | 357 RadiographyLayer& RadiographyScene::LoadMask(const std::vector<Orthanc::ImageProcessing::ImagePoint>& corners, |
475
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
358 const RadiographyDicomLayer& dicomLayer, |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
359 float foreground, |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
360 RadiographyLayer::Geometry* geometry) |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
361 { |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
362 std::auto_ptr<RadiographyMaskLayer> mask(new RadiographyMaskLayer(*this, dicomLayer, foreground)); |
475
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
363 mask->SetCorners(corners); |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
364 if (geometry != NULL) |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
365 { |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
366 mask->SetGeometry(*geometry); |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
367 } |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
368 |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
369 return RegisterLayer(mask.release()); |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
370 } |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
371 |
3c28542229a3
added a mask layer in the RadiographyWidget (to be cleaned)
am@osimis.io
parents:
440
diff
changeset
|
372 |
430 | 373 RadiographyLayer& RadiographyScene::LoadAlphaBitmap(Orthanc::ImageAccessor* bitmap, RadiographyLayer::Geometry *geometry) |
374 { | |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
375 std::auto_ptr<RadiographyAlphaLayer> alpha(new RadiographyAlphaLayer(*this)); |
430 | 376 alpha->SetAlpha(bitmap); |
377 if (geometry != NULL) | |
378 { | |
379 alpha->SetGeometry(*geometry); | |
380 } | |
408 | 381 |
382 return RegisterLayer(alpha.release()); | |
383 } | |
384 | |
553
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
385 RadiographyLayer& RadiographyScene::LoadDicomImage(Orthanc::ImageAccessor* dicomImage, // takes ownership |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
386 const std::string& instance, |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
387 unsigned int frame, |
714
d2c0e347ddc2
deprecating DicomFrameConverter
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
623
diff
changeset
|
388 Deprecated::DicomFrameConverter* converter, // takes ownership |
739
be9c1530d40a
deprecating enum SliceImageQuality
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
389 RadiographyPhotometricDisplayMode preferredPhotometricDisplayMode, |
553
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
390 RadiographyLayer::Geometry* geometry) |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
391 { |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
392 RadiographyDicomLayer& layer = dynamic_cast<RadiographyDicomLayer&>(RegisterLayer(new RadiographyDicomLayer(*this))); |
553
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
393 |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
394 layer.SetInstance(instance, frame); |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
395 |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
396 if (geometry != NULL) |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
397 { |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
398 layer.SetGeometry(*geometry); |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
399 } |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
400 |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
401 layer.SetDicomFrameConverter(converter); |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
402 layer.SetSourceImage(dicomImage); |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
403 layer.SetPreferredPhotomotricDisplayMode(preferredPhotometricDisplayMode); |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
404 |
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
405 return layer; |
587 | 406 } |
553
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
407 |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
408 RadiographyLayer& RadiographyScene::LoadDicomFrame(Deprecated::OrthancApiClient& orthanc, |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
409 const std::string& instance, |
410
6decc0ba9da5
rename RadiographyScene::Layer as RadiographyLayer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
409
diff
changeset
|
410 unsigned int frame, |
430 | 411 bool httpCompression, |
412 RadiographyLayer::Geometry* geometry) | |
408 | 413 { |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
414 RadiographyDicomLayer& layer = dynamic_cast<RadiographyDicomLayer&>(RegisterLayer(new RadiographyDicomLayer( *this))); |
430 | 415 layer.SetInstance(instance, frame); |
416 | |
417 if (geometry != NULL) | |
418 { | |
419 layer.SetGeometry(*geometry); | |
420 } | |
408 | 421 |
422 { | |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
423 Deprecated::IWebService::HttpHeaders headers; |
408 | 424 std::string uri = "/instances/" + instance + "/tags"; |
426 | 425 |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
426 orthanc.GetBinaryAsync( |
426 | 427 uri, headers, |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
428 new Callable<RadiographyScene, Deprecated::OrthancApiClient::BinaryResponseReadyMessage> |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
429 (GetSharedObserver(), &RadiographyScene::OnTagsReceived), NULL, |
426 | 430 new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); |
408 | 431 } |
432 | |
433 { | |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
434 Deprecated::IWebService::HttpHeaders headers; |
408 | 435 headers["Accept"] = "image/x-portable-arbitrarymap"; |
436 | |
437 if (httpCompression) | |
438 { | |
439 headers["Accept-Encoding"] = "gzip"; | |
440 } | |
426 | 441 |
408 | 442 std::string uri = ("/instances/" + instance + "/frames/" + |
443 boost::lexical_cast<std::string>(frame) + "/image-uint16"); | |
426 | 444 |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
445 orthanc.GetBinaryAsync( |
426 | 446 uri, headers, |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
447 new Callable<RadiographyScene, Deprecated::OrthancApiClient::BinaryResponseReadyMessage> |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
448 (GetSharedObserver(), &RadiographyScene::OnFrameReceived), NULL, |
426 | 449 new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); |
408 | 450 } |
451 | |
452 return layer; | |
453 } | |
454 | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
455 |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
456 RadiographyLayer& RadiographyScene::LoadDicomWebFrame(Deprecated::IWebService& web) |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
457 { |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
458 RadiographyLayer& layer = RegisterLayer(new RadiographyDicomLayer(*this)); |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
459 |
426 | 460 |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
461 return layer; |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
462 } |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
463 |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
464 |
426 | 465 |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
466 void RadiographyScene::OnTagsReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message) |
408 | 467 { |
468 size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&> | |
426 | 469 (message.GetPayload()).GetValue(); |
408 | 470 |
471 LOG(INFO) << "JSON received: " << message.GetUri().c_str() | |
472 << " (" << message.GetAnswerSize() << " bytes) for layer " << index; | |
426 | 473 |
408 | 474 Layers::iterator layer = layers_.find(index); |
475 if (layer != layers_.end()) | |
476 { | |
477 assert(layer->second != NULL); | |
426 | 478 |
408 | 479 OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer(), message.GetAnswerSize()); |
430 | 480 dynamic_cast<RadiographyDicomLayer*>(layer->second)->SetDicomTags(dicom); |
408 | 481 |
482 float c, w; | |
483 if (!hasWindowing_ && | |
484 layer->second->GetDefaultWindowing(c, w)) | |
485 { | |
486 hasWindowing_ = true; | |
487 windowingCenter_ = c; | |
488 windowingWidth_ = w; | |
489 } | |
490 | |
623
42dadae61fa9
renamed IObservable::EmitMessage() as BroadcastMessage()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
605
diff
changeset
|
491 BroadcastMessage(GeometryChangedMessage(*this, *(layer->second))); |
408 | 492 } |
493 } | |
426 | 494 |
408 | 495 |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
496 void RadiographyScene::OnFrameReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message) |
408 | 497 { |
498 size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&>(message.GetPayload()).GetValue(); | |
426 | 499 |
408 | 500 LOG(INFO) << "DICOM frame received: " << message.GetUri().c_str() |
501 << " (" << message.GetAnswerSize() << " bytes) for layer " << index; | |
426 | 502 |
408 | 503 Layers::iterator layer = layers_.find(index); |
504 if (layer != layers_.end()) | |
505 { | |
506 assert(layer->second != NULL); | |
507 | |
508 std::string content; | |
509 if (message.GetAnswerSize() > 0) | |
510 { | |
511 content.assign(reinterpret_cast<const char*>(message.GetAnswer()), message.GetAnswerSize()); | |
512 } | |
426 | 513 |
408 | 514 std::auto_ptr<Orthanc::PamReader> reader(new Orthanc::PamReader); |
515 reader->ReadFromMemory(content); | |
430 | 516 dynamic_cast<RadiographyDicomLayer*>(layer->second)->SetSourceImage(reader.release()); |
408 | 517 |
623
42dadae61fa9
renamed IObservable::EmitMessage() as BroadcastMessage()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
605
diff
changeset
|
518 BroadcastMessage(ContentChangedMessage(*this, *(layer->second))); |
408 | 519 } |
520 } | |
521 | |
522 | |
523 Extent2D RadiographyScene::GetSceneExtent() const | |
524 { | |
525 Extent2D extent; | |
526 | |
527 for (Layers::const_iterator it = layers_.begin(); | |
528 it != layers_.end(); ++it) | |
529 { | |
530 assert(it->second != NULL); | |
531 extent.Union(it->second->GetExtent()); | |
532 } | |
533 | |
534 return extent; | |
535 } | |
426 | 536 |
408 | 537 |
538 void RadiographyScene::Render(Orthanc::ImageAccessor& buffer, | |
409 | 539 const AffineTransform2D& viewTransform, |
1196
a5f2a6b04a31
RadiographyScene: windowing is now only applied to the Dicom layer
Alain Mazy <alain@mazy.be>
parents:
1190
diff
changeset
|
540 ImageInterpolation interpolation, |
a5f2a6b04a31
RadiographyScene: windowing is now only applied to the Dicom layer
Alain Mazy <alain@mazy.be>
parents:
1190
diff
changeset
|
541 bool applyWindowing) const |
408 | 542 { |
543 // Render layers in the background-to-foreground order | |
1199
922d2e61aa5d
RadiograpyScene: can now remove any layer + new key wrappers for Delete/Backspace
Alain Mazy <alain@mazy.be>
parents:
1196
diff
changeset
|
544 for (size_t index = 0; index < nextLayerIndex_; index++) |
408 | 545 { |
546 Layers::const_iterator it = layers_.find(index); | |
547 if (it != layers_.end()) | |
548 { | |
549 assert(it->second != NULL); | |
1196
a5f2a6b04a31
RadiographyScene: windowing is now only applied to the Dicom layer
Alain Mazy <alain@mazy.be>
parents:
1190
diff
changeset
|
550 it->second->Render(buffer, viewTransform, interpolation, windowingCenter_, windowingWidth_, applyWindowing); |
408 | 551 } |
552 } | |
553 } | |
554 | |
555 | |
556 bool RadiographyScene::LookupLayer(size_t& index /* out */, | |
557 double x, | |
558 double y) const | |
559 { | |
560 // Render layers in the foreground-to-background order | |
1199
922d2e61aa5d
RadiograpyScene: can now remove any layer + new key wrappers for Delete/Backspace
Alain Mazy <alain@mazy.be>
parents:
1196
diff
changeset
|
561 for (size_t i = nextLayerIndex_; i > 0; i--) |
408 | 562 { |
563 index = i - 1; | |
564 Layers::const_iterator it = layers_.find(index); | |
565 if (it != layers_.end()) | |
566 { | |
567 assert(it->second != NULL); | |
568 if (it->second->Contains(x, y)) | |
569 { | |
570 return true; | |
571 } | |
572 } | |
573 } | |
574 | |
575 return false; | |
576 } | |
577 | |
426 | 578 |
408 | 579 void RadiographyScene::DrawBorder(CairoContext& context, |
580 unsigned int layer, | |
581 double zoom) | |
582 { | |
583 Layers::const_iterator found = layers_.find(layer); | |
426 | 584 |
408 | 585 if (found != layers_.end()) |
586 { | |
587 context.SetSourceColor(255, 0, 0); | |
588 found->second->DrawBorders(context, zoom); | |
589 } | |
590 } | |
591 | |
592 | |
593 void RadiographyScene::GetRange(float& minValue, | |
594 float& maxValue) const | |
595 { | |
596 bool first = true; | |
426 | 597 |
408 | 598 for (Layers::const_iterator it = layers_.begin(); |
599 it != layers_.end(); it++) | |
600 { | |
601 assert(it->second != NULL); | |
602 | |
603 float a, b; | |
604 if (it->second->GetRange(a, b)) | |
605 { | |
606 if (first) | |
607 { | |
608 minValue = a; | |
609 maxValue = b; | |
610 first = false; | |
611 } | |
612 else | |
613 { | |
614 minValue = std::min(a, minValue); | |
615 maxValue = std::max(b, maxValue); | |
616 } | |
617 } | |
618 } | |
619 | |
620 if (first) | |
621 { | |
622 minValue = 0; | |
623 maxValue = 0; | |
624 } | |
625 } | |
626 | |
481
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
627 Orthanc::Image* RadiographyScene::ExportToImage(double pixelSpacingX, |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
628 double pixelSpacingY, |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
629 ImageInterpolation interpolation, |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
630 bool invert, |
1196
a5f2a6b04a31
RadiographyScene: windowing is now only applied to the Dicom layer
Alain Mazy <alain@mazy.be>
parents:
1190
diff
changeset
|
631 int64_t maxValue /* for inversion */, |
a5f2a6b04a31
RadiographyScene: windowing is now only applied to the Dicom layer
Alain Mazy <alain@mazy.be>
parents:
1190
diff
changeset
|
632 bool applyWindowing) |
426 | 633 { |
408 | 634 if (pixelSpacingX <= 0 || |
635 pixelSpacingY <= 0) | |
636 { | |
637 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
638 } | |
426 | 639 |
408 | 640 Extent2D extent = GetSceneExtent(); |
641 | |
928
1b49e78d91d0
fix for older compilers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
923
diff
changeset
|
642 int w = boost::math::iround(extent.GetWidth() / pixelSpacingX); |
1b49e78d91d0
fix for older compilers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
923
diff
changeset
|
643 int h = boost::math::iround(extent.GetHeight() / pixelSpacingY); |
408 | 644 |
645 if (w < 0 || h < 0) | |
646 { | |
647 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
648 } | |
649 | |
650 Orthanc::Image layers(Orthanc::PixelFormat_Float32, | |
651 static_cast<unsigned int>(w), | |
652 static_cast<unsigned int>(h), false); | |
653 | |
409 | 654 AffineTransform2D view = AffineTransform2D::Combine( |
426 | 655 AffineTransform2D::CreateScaling(1.0 / pixelSpacingX, 1.0 / pixelSpacingY), |
656 AffineTransform2D::CreateOffset(-extent.GetX1(), -extent.GetY1())); | |
657 | |
432
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
658 // wipe background before rendering |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
659 Orthanc::ImageProcessing::Set(layers, 0); |
4eb96c6b4e96
improved handling of MONOCHROME1, background and invertion
am@osimis.io
parents:
431
diff
changeset
|
660 |
1196
a5f2a6b04a31
RadiographyScene: windowing is now only applied to the Dicom layer
Alain Mazy <alain@mazy.be>
parents:
1190
diff
changeset
|
661 Render(layers, view, interpolation, applyWindowing); |
408 | 662 |
481
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
663 std::auto_ptr<Orthanc::Image> rendered(new Orthanc::Image(Orthanc::PixelFormat_Grayscale16, |
553
92305ee35b1c
web-worker consequences: give access to lower level data
Alain Mazy <alain@mazy.be>
parents:
541
diff
changeset
|
664 layers.GetWidth(), layers.GetHeight(), false)); |
481
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
665 |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
666 Orthanc::ImageProcessing::Convert(*rendered, layers); |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
667 if (invert) |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
668 Orthanc::ImageProcessing::Invert(*rendered, maxValue); |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
669 |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
670 return rendered.release(); |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
671 } |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
672 |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
673 |
587 | 674 Orthanc::Image* RadiographyScene::ExportToCreateDicomRequestAndImage(Json::Value& createDicomRequestContent, |
675 const Json::Value& dicomTags, | |
676 const std::string& parentOrthancId, | |
677 double pixelSpacingX, | |
678 double pixelSpacingY, | |
679 bool invert, | |
680 ImageInterpolation interpolation) | |
481
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
681 { |
541 | 682 LOG(INFO) << "Exporting RadiographyScene to DICOM"; |
683 | |
1196
a5f2a6b04a31
RadiographyScene: windowing is now only applied to the Dicom layer
Alain Mazy <alain@mazy.be>
parents:
1190
diff
changeset
|
684 std::auto_ptr<Orthanc::Image> rendered(ExportToImage(pixelSpacingX, pixelSpacingY, interpolation, false)); // note: we don't invert the image in the pixels data because we'll set the PhotometricDisplayMode correctly in the DICOM tags |
408 | 685 |
483 | 686 createDicomRequestContent["Tags"] = dicomTags; |
408 | 687 |
739
be9c1530d40a
deprecating enum SliceImageQuality
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
688 RadiographyPhotometricDisplayMode photometricMode = GetPreferredPhotomotricDisplayMode(); |
be9c1530d40a
deprecating enum SliceImageQuality
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
689 if ((invert && photometricMode != RadiographyPhotometricDisplayMode_Monochrome2) || |
be9c1530d40a
deprecating enum SliceImageQuality
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
690 (!invert && photometricMode == RadiographyPhotometricDisplayMode_Monochrome1)) |
436
04711a2e12cd
fix crop + export photometric interpretation correctly
am@osimis.io
parents:
432
diff
changeset
|
691 { |
483 | 692 createDicomRequestContent["Tags"]["PhotometricInterpretation"] = "MONOCHROME1"; |
436
04711a2e12cd
fix crop + export photometric interpretation correctly
am@osimis.io
parents:
432
diff
changeset
|
693 } |
04711a2e12cd
fix crop + export photometric interpretation correctly
am@osimis.io
parents:
432
diff
changeset
|
694 else |
04711a2e12cd
fix crop + export photometric interpretation correctly
am@osimis.io
parents:
432
diff
changeset
|
695 { |
483 | 696 createDicomRequestContent["Tags"]["PhotometricInterpretation"] = "MONOCHROME2"; |
436
04711a2e12cd
fix crop + export photometric interpretation correctly
am@osimis.io
parents:
432
diff
changeset
|
697 } |
408 | 698 |
699 // WARNING: The order of PixelSpacing is Y/X. We use "%0.8f" to | |
700 // avoid floating-point numbers to grow over 16 characters, | |
701 // which would be invalid according to DICOM standard | |
702 // ("dciodvfy" would complain). | |
703 char buf[32]; | |
704 sprintf(buf, "%0.8f\\%0.8f", pixelSpacingY, pixelSpacingX); | |
426 | 705 |
483 | 706 createDicomRequestContent["Tags"]["PixelSpacing"] = buf; |
408 | 707 |
708 float center, width; | |
709 if (GetWindowing(center, width)) | |
710 { | |
483 | 711 createDicomRequestContent["Tags"]["WindowCenter"] = |
426 | 712 boost::lexical_cast<std::string>(boost::math::iround(center)); |
408 | 713 |
483 | 714 createDicomRequestContent["Tags"]["WindowWidth"] = |
426 | 715 boost::lexical_cast<std::string>(boost::math::iround(width)); |
408 | 716 } |
717 | |
587 | 718 if (!parentOrthancId.empty()) |
719 { | |
720 createDicomRequestContent["Parent"] = parentOrthancId; | |
721 } | |
722 | |
723 return rendered.release(); | |
724 } | |
725 | |
726 | |
727 void RadiographyScene::ExportToCreateDicomRequest(Json::Value& createDicomRequestContent, | |
728 const Json::Value& dicomTags, | |
729 const std::string& parentOrthancId, | |
730 double pixelSpacingX, | |
731 double pixelSpacingY, | |
732 bool invert, | |
733 ImageInterpolation interpolation, | |
734 bool usePam) | |
735 { | |
736 LOG(INFO) << "Exporting RadiographyScene to DICOM"; | |
737 VLOG(1) << "Exporting RadiographyScene to: export to image"; | |
738 | |
739 std::auto_ptr<Orthanc::Image> rendered(ExportToCreateDicomRequestAndImage(createDicomRequestContent, dicomTags, parentOrthancId, pixelSpacingX, pixelSpacingY, invert, interpolation)); | |
740 | |
741 // convert the image into base64 for inclusing in the createDicomRequest | |
742 std::string base64; | |
743 | |
744 { | |
745 std::string content; | |
746 | |
747 if (usePam) | |
748 { | |
749 VLOG(1) << "Exporting RadiographyScene: convert to PAM"; | |
750 Orthanc::PamWriter writer; | |
751 writer.WriteToMemory(content, *rendered); | |
752 } | |
753 else | |
754 { | |
755 Orthanc::PngWriter writer; | |
756 writer.WriteToMemory(content, *rendered); | |
757 } | |
758 | |
759 VLOG(1) << "Exporting RadiographyScene: encoding to base64"; | |
760 Orthanc::Toolbox::EncodeBase64(base64, content); | |
761 } | |
426 | 762 |
408 | 763 // This is Data URI scheme: https://en.wikipedia.org/wiki/Data_URI_scheme |
426 | 764 createDicomRequestContent["Content"] = ("data:" + |
765 std::string(usePam ? Orthanc::MIME_PAM : Orthanc::MIME_PNG) + | |
766 ";base64," + base64); | |
481
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
767 |
541 | 768 VLOG(1) << "Exporting RadiographyScene: create-dicom request is ready"; |
484
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
769 } |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
770 |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
771 |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
772 void RadiographyScene::ExportDicom(Deprecated::OrthancApiClient& orthanc, |
484
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
773 const Json::Value& dicomTags, |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
774 const std::string& parentOrthancId, |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
775 double pixelSpacingX, |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
776 double pixelSpacingY, |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
777 bool invert, |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
778 ImageInterpolation interpolation, |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
779 bool usePam) |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
780 { |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
781 Json::Value createDicomRequestContent; |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
782 |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
783 ExportToCreateDicomRequest(createDicomRequestContent, dicomTags, parentOrthancId, pixelSpacingX, pixelSpacingY, invert, interpolation, usePam); |
7bf001b9d244
re-added ExportToCreateDicomRequest
Alain Mazy <alain@mazy.be>
parents:
483
diff
changeset
|
784 |
481
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
785 orthanc.PostJsonAsyncExpectJson( |
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
786 "/tools/create-dicom", createDicomRequestContent, |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
787 new Callable<RadiographyScene, Deprecated::OrthancApiClient::JsonResponseReadyMessage> |
1066
b537002f83a9
removing broker from deprecated classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
928
diff
changeset
|
788 (GetSharedObserver(), &RadiographyScene::OnDicomExported), |
481
159a465e27bd
reworked RadiographyScene export to export to an Orthanc::Image too
am@osimis.io
parents:
475
diff
changeset
|
789 NULL, NULL); |
483 | 790 |
791 } | |
792 | |
793 | |
794 // Export using PAM is faster than using PNG, but requires Orthanc | |
795 // core >= 1.4.3 | |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
796 void RadiographyScene::ExportDicom(Deprecated::OrthancApiClient& orthanc, |
483 | 797 const Orthanc::DicomMap& dicom, |
798 const std::string& parentOrthancId, | |
799 double pixelSpacingX, | |
800 double pixelSpacingY, | |
801 bool invert, | |
802 ImageInterpolation interpolation, | |
803 bool usePam) | |
804 { | |
805 std::set<Orthanc::DicomTag> tags; | |
806 dicom.GetTags(tags); | |
807 | |
808 Json::Value jsonTags = Json::objectValue; | |
809 | |
810 for (std::set<Orthanc::DicomTag>::const_iterator | |
811 tag = tags.begin(); tag != tags.end(); ++tag) | |
812 { | |
813 const Orthanc::DicomValue& value = dicom.GetValue(*tag); | |
814 if (!value.IsNull() && | |
815 !value.IsBinary()) | |
816 { | |
817 jsonTags[tag->Format()] = value.GetContent(); | |
818 } | |
819 } | |
820 | |
821 ExportDicom(orthanc, jsonTags, parentOrthancId, pixelSpacingX, pixelSpacingY, invert, interpolation, usePam); | |
408 | 822 } |
823 | |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
824 void RadiographyScene::OnDicomExported(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) |
408 | 825 { |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
826 LOG(INFO) << "DICOM export was successful: " |
408 | 827 << message.GetJson().toStyledString(); |
828 } | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
829 |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
830 |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
831 void RadiographyScene::OnDicomWebReceived(const Deprecated::IWebService::HttpRequestSuccessMessage& message) |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
832 { |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
833 LOG(INFO) << "DICOMweb WADO-RS received: " << message.GetAnswerSize() << " bytes"; |
418 | 834 |
726
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
835 const Deprecated::IWebService::HttpHeaders& h = message.GetAnswerHttpHeaders(); |
4f2416d519b4
moving layers, widgets and loaders to Deprecated namespace
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
714
diff
changeset
|
836 for (Deprecated::IWebService::HttpHeaders::const_iterator |
426 | 837 it = h.begin(); it != h.end(); ++it) |
418 | 838 { |
839 printf("[%s] = [%s]\n", it->first.c_str(), it->second.c_str()); | |
840 } | |
417
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
841 } |
aee3d7941c9b
preparing to load images using DICOMweb
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
412
diff
changeset
|
842 |
408 | 843 } |