Mercurial > hg > orthanc-stone
annotate Applications/Samples/BasicPetCtFusionApplication.h @ 1327:4f8db2d202c8 broker
OrthancSeriesProgressiveLoader now has two modes that
can be selected at object creation :
- progressive (will first load jpeg50, then jpeg90 then PAM)
- non-progressive (will directly load PAM (uncompressed))
Please note that the slice loading order remains dynamic
and depending upon the slice that the client code wishes
to extract from the volume.
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Wed, 25 Mar 2020 14:34:27 +0100 |
parents | 8a0a62189f46 |
children |
rev | line source |
---|---|
0 | 1 /** |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
1270
2d8ab34c8c91
upgrade to year 2020
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
439
diff
changeset
|
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium |
0 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
47 | 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. | |
0 | 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 | |
47 | 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 | |
0 | 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 **/ | |
20 | |
21 | |
22 #pragma once | |
23 | |
24 #include "SampleInteractor.h" | |
25 | |
212
5412adf19980
resort to OrthancFramework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
147
diff
changeset
|
26 #include <Core/Logging.h> |
0 | 27 |
28 namespace OrthancStone | |
29 { | |
30 namespace Samples | |
31 { | |
32 class BasicPetCtFusionApplication : public SampleApplicationBase | |
33 { | |
34 private: | |
35 class Interactor : public SampleInteractor | |
36 { | |
37 public: | |
38 static void SetStyle(LayeredSceneWidget& widget, | |
39 bool ct, | |
40 bool pet) | |
41 { | |
42 if (ct) | |
43 { | |
44 RenderStyle style; | |
45 style.windowing_ = ImageWindowing_Bone; | |
46 widget.SetLayerStyle(0, style); | |
47 } | |
48 else | |
49 { | |
50 RenderStyle style; | |
51 style.visible_ = false; | |
52 widget.SetLayerStyle(0, style); | |
53 } | |
54 | |
55 if (ct && pet) | |
56 { | |
57 RenderStyle style; | |
58 style.applyLut_ = true; | |
59 style.alpha_ = 0.5; | |
60 widget.SetLayerStyle(1, style); | |
61 } | |
62 else if (pet) | |
63 { | |
64 RenderStyle style; | |
65 style.applyLut_ = true; | |
66 widget.SetLayerStyle(1, style); | |
67 } | |
68 else | |
69 { | |
70 RenderStyle style; | |
71 style.visible_ = false; | |
72 widget.SetLayerStyle(1, style); | |
73 } | |
74 } | |
75 | |
76 | |
77 static bool IsVisible(LayeredSceneWidget& widget, | |
78 size_t layer) | |
79 { | |
80 RenderStyle style = widget.GetLayerStyle(layer); | |
81 return style.visible_; | |
82 } | |
83 | |
84 | |
85 static void ToggleInterpolation(LayeredSceneWidget& widget, | |
86 size_t layer) | |
87 { | |
88 RenderStyle style = widget.GetLayerStyle(layer); | |
89 | |
147
f48c5d422d45
removed meaningless ImageInterpolation_Linear value
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
134
diff
changeset
|
90 if (style.interpolation_ == ImageInterpolation_Bilinear) |
0 | 91 { |
92 style.interpolation_ = ImageInterpolation_Nearest; | |
93 } | |
94 else | |
95 { | |
147
f48c5d422d45
removed meaningless ImageInterpolation_Linear value
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
134
diff
changeset
|
96 style.interpolation_ = ImageInterpolation_Bilinear; |
0 | 97 } |
98 | |
99 widget.SetLayerStyle(layer, style); | |
100 } | |
101 | |
102 | |
103 Interactor(VolumeImage& volume, | |
104 VolumeProjection projection, | |
105 bool reverse) : | |
106 SampleInteractor(volume, projection, reverse) | |
107 { | |
108 } | |
109 | |
110 | |
111 virtual void KeyPressed(WorldSceneWidget& widget, | |
112 char key, | |
113 KeyboardModifiers modifiers, | |
114 IStatusBar* statusBar) | |
115 { | |
116 LayeredSceneWidget& layered = dynamic_cast<LayeredSceneWidget&>(widget); | |
117 | |
118 switch (key) | |
119 { | |
120 case 'c': | |
121 // Toggle the visibility of the CT layer | |
122 SetStyle(layered, !IsVisible(layered, 0), IsVisible(layered, 1)); | |
123 break; | |
124 | |
125 case 'p': | |
126 // Toggle the visibility of the PET layer | |
127 SetStyle(layered, IsVisible(layered, 0), !IsVisible(layered, 1)); | |
128 break; | |
129 | |
130 case 'i': | |
131 { | |
132 // Toggle on/off the interpolation | |
133 ToggleInterpolation(layered, 0); | |
134 ToggleInterpolation(layered, 1); | |
135 break; | |
136 } | |
137 | |
138 default: | |
139 break; | |
140 } | |
141 } | |
142 }; | |
143 | |
144 | |
145 public: | |
146 virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) | |
147 { | |
148 boost::program_options::options_description generic("Sample options"); | |
149 generic.add_options() | |
150 ("ct", boost::program_options::value<std::string>(), | |
151 "Orthanc ID of the CT series") | |
152 ("pet", boost::program_options::value<std::string>(), | |
153 "Orthanc ID of the PET series") | |
154 ("threads", boost::program_options::value<unsigned int>()->default_value(3), | |
155 "Number of download threads for the CT series") | |
156 ; | |
157 | |
158 options.add(generic); | |
159 } | |
160 | |
161 virtual void Initialize(BasicApplicationContext& context, | |
162 IStatusBar& statusBar, | |
163 const boost::program_options::variables_map& parameters) | |
164 { | |
165 using namespace OrthancStone; | |
166 | |
167 if (parameters.count("ct") != 1 || | |
168 parameters.count("pet") != 1) | |
169 { | |
170 LOG(ERROR) << "The series ID is missing"; | |
171 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
172 } | |
173 | |
174 std::string ct = parameters["ct"].as<std::string>(); | |
175 std::string pet = parameters["pet"].as<std::string>(); | |
176 unsigned int threads = parameters["threads"].as<unsigned int>(); | |
177 | |
178 VolumeImage& ctVolume = context.AddSeriesVolume(ct, true /* progressive download */, threads); | |
179 VolumeImage& petVolume = context.AddSeriesVolume(pet, true /* progressive download */, 1); | |
180 | |
181 // Take the PET volume as the reference for the slices | |
1298
8a0a62189f46
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1270
diff
changeset
|
182 std::unique_ptr<Interactor> interactor(new Interactor(petVolume, VolumeProjection_Axial, false /* don't reverse normal */)); |
0 | 183 |
1298
8a0a62189f46
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1270
diff
changeset
|
184 std::unique_ptr<LayeredSceneWidget> widget(new LayeredSceneWidget); |
0 | 185 widget->AddLayer(new VolumeImage::LayerFactory(ctVolume)); |
186 widget->AddLayer(new VolumeImage::LayerFactory(petVolume)); | |
187 widget->SetSlice(interactor->GetCursor().GetCurrentSlice()); | |
188 widget->SetInteractor(*interactor); | |
189 | |
190 Interactor::SetStyle(*widget, true, true); // Initially, show both CT and PET layers | |
191 | |
192 context.AddInteractor(interactor.release()); | |
193 context.SetCentralWidget(widget.release()); | |
194 | |
195 statusBar.SetMessage("Use the key \"t\" to toggle the fullscreen mode"); | |
196 statusBar.SetMessage("Use the key \"c\" to show/hide the CT layer"); | |
197 statusBar.SetMessage("Use the key \"p\" to show/hide the PET layer"); | |
198 statusBar.SetMessage("Use the key \"i\" to toggle the smoothing of the images"); | |
199 } | |
200 }; | |
201 } | |
202 } |