Mercurial > hg > orthanc-stone
annotate Framework/Radiography/RadiographyWidget.cpp @ 428:751fb354149e am-vsol-upgrade
ability to change the scene of the RadiographyWidget
author | am@osimis.io |
---|---|
date | Wed, 28 Nov 2018 10:44:28 +0100 |
parents | 18b707fb8620 |
children | 4eb96c6b4e96 |
rev | line source |
---|---|
413 | 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 "RadiographyWidget.h" | |
23 | |
24 #include <Core/Images/Image.h> | |
25 | |
26 | |
27 namespace OrthancStone | |
28 { | |
29 bool RadiographyWidget::RenderInternal(unsigned int width, | |
30 unsigned int height, | |
31 ImageInterpolation interpolation) | |
32 { | |
33 float windowCenter, windowWidth; | |
428
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
34 scene_->GetWindowingWithDefault(windowCenter, windowWidth); |
413 | 35 |
36 float x0 = windowCenter - windowWidth / 2.0f; | |
37 float x1 = windowCenter + windowWidth / 2.0f; | |
38 | |
39 if (windowWidth <= 0.001f) // Avoid division by zero at (*) | |
40 { | |
41 return false; | |
42 } | |
43 else | |
44 { | |
45 if (floatBuffer_.get() == NULL || | |
46 floatBuffer_->GetWidth() != width || | |
47 floatBuffer_->GetHeight() != height) | |
48 { | |
49 floatBuffer_.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, width, height, false)); | |
50 } | |
51 | |
52 if (cairoBuffer_.get() == NULL || | |
53 cairoBuffer_->GetWidth() != width || | |
54 cairoBuffer_->GetHeight() != height) | |
55 { | |
56 cairoBuffer_.reset(new CairoSurface(width, height)); | |
57 } | |
58 | |
428
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
59 scene_->Render(*floatBuffer_, GetView().GetMatrix(), interpolation); |
413 | 60 |
61 // Conversion from Float32 to BGRA32 (cairo). Very similar to | |
62 // GrayscaleFrameRenderer => TODO MERGE? | |
63 | |
64 Orthanc::ImageAccessor target; | |
65 cairoBuffer_->GetWriteableAccessor(target); | |
66 | |
67 float scaling = 255.0f / (x1 - x0); | |
68 | |
69 for (unsigned int y = 0; y < height; y++) | |
70 { | |
71 const float* p = reinterpret_cast<const float*>(floatBuffer_->GetConstRow(y)); | |
72 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); | |
73 | |
74 for (unsigned int x = 0; x < width; x++, p++, q += 4) | |
75 { | |
76 uint8_t v = 0; | |
77 if (*p >= x1) | |
78 { | |
79 v = 255; | |
80 } | |
81 else if (*p <= x0) | |
82 { | |
83 v = 0; | |
84 } | |
85 else | |
86 { | |
87 // https://en.wikipedia.org/wiki/Linear_interpolation | |
88 v = static_cast<uint8_t>(scaling * (*p - x0)); // (*) | |
89 } | |
90 | |
91 if (invert_) | |
92 { | |
93 v = 255 - v; | |
94 } | |
95 | |
96 q[0] = v; | |
97 q[1] = v; | |
98 q[2] = v; | |
99 q[3] = 255; | |
100 } | |
101 } | |
102 | |
103 return true; | |
104 } | |
105 } | |
106 | |
107 | |
108 bool RadiographyWidget::RenderScene(CairoContext& context, | |
109 const ViewportGeometry& view) | |
110 { | |
111 cairo_t* cr = context.GetObject(); | |
112 | |
113 if (RenderInternal(context.GetWidth(), context.GetHeight(), interpolation_)) | |
114 { | |
115 // https://www.cairographics.org/FAQ/#paint_from_a_surface | |
116 cairo_save(cr); | |
117 cairo_identity_matrix(cr); | |
118 cairo_set_source_surface(cr, cairoBuffer_->GetObject(), 0, 0); | |
119 cairo_paint(cr); | |
120 cairo_restore(cr); | |
121 } | |
122 else | |
123 { | |
124 // https://www.cairographics.org/FAQ/#clear_a_surface | |
125 context.SetSourceColor(0, 0, 0); | |
126 cairo_paint(cr); | |
127 } | |
128 | |
129 if (hasSelection_) | |
130 { | |
428
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
131 scene_->DrawBorder(context, selectedLayer_, view.GetZoom()); |
413 | 132 } |
133 | |
134 return true; | |
135 } | |
136 | |
137 | |
138 RadiographyWidget::RadiographyWidget(MessageBroker& broker, | |
428
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
139 boost::shared_ptr<RadiographyScene> scene, |
413 | 140 const std::string& name) : |
141 WorldSceneWidget(name), | |
142 IObserver(broker), | |
143 invert_(false), | |
144 interpolation_(ImageInterpolation_Nearest), | |
145 hasSelection_(false), | |
146 selectedLayer_(0) // Dummy initialization | |
147 { | |
428
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
148 SetScene(scene); |
413 | 149 } |
150 | |
151 | |
152 void RadiographyWidget::Select(size_t layer) | |
153 { | |
154 hasSelection_ = true; | |
155 selectedLayer_ = layer; | |
156 } | |
157 | |
158 | |
159 bool RadiographyWidget::LookupSelectedLayer(size_t& layer) | |
160 { | |
161 if (hasSelection_) | |
162 { | |
163 layer = selectedLayer_; | |
164 return true; | |
165 } | |
166 else | |
167 { | |
168 return false; | |
169 } | |
170 } | |
171 | |
172 | |
173 void RadiographyWidget::OnGeometryChanged(const RadiographyScene::GeometryChangedMessage& message) | |
174 { | |
175 LOG(INFO) << "Geometry has changed"; | |
176 FitContent(); | |
177 } | |
178 | |
179 | |
180 void RadiographyWidget::OnContentChanged(const RadiographyScene::ContentChangedMessage& message) | |
181 { | |
182 LOG(INFO) << "Content has changed"; | |
183 NotifyContentChanged(); | |
184 } | |
185 | |
186 | |
187 void RadiographyWidget::SetInvert(bool invert) | |
188 { | |
189 if (invert_ != invert) | |
190 { | |
191 invert_ = invert; | |
192 NotifyContentChanged(); | |
193 } | |
194 } | |
195 | |
196 | |
197 void RadiographyWidget::SwitchInvert() | |
198 { | |
199 invert_ = !invert_; | |
200 NotifyContentChanged(); | |
201 } | |
202 | |
203 | |
204 void RadiographyWidget::SetInterpolation(ImageInterpolation interpolation) | |
205 { | |
206 if (interpolation_ != interpolation) | |
207 { | |
208 interpolation_ = interpolation; | |
209 NotifyContentChanged(); | |
210 } | |
211 } | |
428
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
212 |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
213 void RadiographyWidget::SetScene(boost::shared_ptr<RadiographyScene> scene) |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
214 { |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
215 if (scene_ != NULL) |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
216 { |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
217 scene_->Unregister(this); |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
218 } |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
219 |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
220 scene_ = scene; |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
221 |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
222 scene_->RegisterObserverCallback( |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
223 new Callable<RadiographyWidget, RadiographyScene::GeometryChangedMessage> |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
224 (*this, &RadiographyWidget::OnGeometryChanged)); |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
225 |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
226 scene_->RegisterObserverCallback( |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
227 new Callable<RadiographyWidget, RadiographyScene::ContentChangedMessage> |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
228 (*this, &RadiographyWidget::OnContentChanged)); |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
229 |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
230 // force redraw |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
231 FitContent(); |
751fb354149e
ability to change the scene of the RadiographyWidget
am@osimis.io
parents:
413
diff
changeset
|
232 } |
413 | 233 } |