Mercurial > hg > orthanc-stone
annotate Applications/Samples/SingleFrameEditorApplication.h @ 346:c2e040ea8fbe am-2
rotation transform
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 22 Oct 2018 19:40:36 +0200 |
parents | 55438b1ca317 |
children | cd65103c9172 |
rev | line source |
---|---|
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1 /** |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2 * Stone of Orthanc |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
4 * Department, University Hospital of Liege, Belgium |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
6 * |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
7 * This program is free software: you can redistribute it and/or |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
8 * modify it under the terms of the GNU Affero General Public License |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
9 * as published by the Free Software Foundation, either version 3 of |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
10 * the License, or (at your option) any later version. |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
11 * |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
12 * This program is distributed in the hope that it will be useful, but |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
13 * WITHOUT ANY WARRANTY; without even the implied warranty of |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
15 * Affero General Public License for more details. |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
16 * |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
17 * You should have received a copy of the GNU Affero General Public License |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
19 **/ |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
20 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
21 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
22 #pragma once |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
23 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
24 #include "SampleApplicationBase.h" |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
25 |
339 | 26 #include "../../Framework/Toolbox/GeometryToolbox.h" |
27 #include "../../Framework/Toolbox/ImageGeometry.h" | |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
28 #include "../../Framework/Layers/OrthancFrameLayerSource.h" |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
29 |
338 | 30 #include <Core/DicomFormat/DicomArray.h> |
343 | 31 #include <Core/Images/FontRegistry.h> |
339 | 32 #include <Core/Images/ImageProcessing.h> |
338 | 33 #include <Core/Images/PamReader.h> |
343 | 34 #include <Core/Images/PngWriter.h> //TODO |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
35 #include <Core/Logging.h> |
338 | 36 #include <Plugins/Samples/Common/FullOrthancDataset.h> |
339 | 37 #include <Plugins/Samples/Common/DicomDatasetReader.h> |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
38 |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
39 |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
40 #include <boost/math/constants/constants.hpp> |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
41 |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
42 namespace OrthancStone |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
43 { |
338 | 44 class BitmapStack : |
337 | 45 public IObserver, |
336
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
46 public IObservable |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
47 { |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
48 public: |
338 | 49 typedef OriginMessage<MessageType_Widget_GeometryChanged, BitmapStack> GeometryChangedMessage; |
50 typedef OriginMessage<MessageType_Widget_ContentChanged, BitmapStack> ContentChangedMessage; | |
336
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
51 |
337 | 52 private: |
338 | 53 class Bitmap : public boost::noncopyable |
54 { | |
55 private: | |
343 | 56 bool visible_; |
57 bool hasSize_; | |
58 unsigned int width_; | |
59 unsigned int height_; | |
60 bool hasCrop_; | |
61 unsigned int cropX_; | |
62 unsigned int cropY_; | |
63 unsigned int cropWidth_; | |
64 unsigned int cropHeight_; | |
65 Matrix transform_; | |
66 double pixelSpacingX_; | |
67 double pixelSpacingY_; | |
68 double panX_; | |
69 double panY_; | |
346 | 70 double angle_; |
338 | 71 |
342 | 72 |
346 | 73 static Matrix CreateOffsetMatrix(double dx, |
74 double dy) | |
342 | 75 { |
346 | 76 Matrix m = LinearAlgebra::IdentityMatrix(3); |
77 m(0, 2) = dx; | |
78 m(1, 2) = dy; | |
79 return m; | |
80 } | |
81 | |
342 | 82 |
346 | 83 static Matrix CreateScalingMatrix(double sx, |
84 double sy) | |
85 { | |
86 Matrix m = LinearAlgebra::IdentityMatrix(3); | |
87 m(0, 0) = sx; | |
88 m(1, 1) = sy; | |
89 return m; | |
90 } | |
91 | |
92 | |
93 static Matrix CreateRotationMatrix(double angle) | |
94 { | |
342 | 95 Matrix m; |
346 | 96 const double v[] = { cos(angle), -sin(angle), 0, |
97 sin(angle), cos(angle), 0, | |
342 | 98 0, 0, 1 }; |
99 LinearAlgebra::FillMatrix(m, 3, 3, v); | |
346 | 100 return m; |
342 | 101 } |
346 | 102 |
345 | 103 |
346 | 104 static void ApplyTransform(double& x /* inout */, |
105 double& y /* inout */, | |
106 const Matrix& transform) | |
339 | 107 { |
108 Vector p; | |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
109 LinearAlgebra::AssignVector(p, x, y, 1); |
339 | 110 |
346 | 111 Vector q = LinearAlgebra::Product(transform, p); |
339 | 112 |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
113 if (!LinearAlgebra::IsNear(q[2], 1.0)) |
339 | 114 { |
115 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
116 } | |
117 else | |
118 { | |
345 | 119 x = q[0]; |
120 y = q[1]; | |
339 | 121 } |
122 } | |
123 | |
345 | 124 |
346 | 125 void UpdateTransform() |
126 { | |
127 transform_ = CreateScalingMatrix(pixelSpacingX_, pixelSpacingY_); | |
128 | |
129 double centerX = static_cast<double>(width_) / 2.0; | |
130 double centerY = static_cast<double>(height_) / 2.0; | |
131 ApplyTransform(centerX, centerY, transform_); | |
132 | |
133 transform_ = LinearAlgebra::Product( | |
134 CreateOffsetMatrix(panX_ + centerX, panY_ + centerY), | |
135 CreateRotationMatrix(angle_), | |
136 CreateOffsetMatrix(-centerX, -centerY), transform_); | |
137 } | |
138 | |
139 | |
345 | 140 void AddToExtent(Extent2D& extent, |
141 double x, | |
142 double y) const | |
143 { | |
346 | 144 ApplyTransform(x, y, transform_); |
345 | 145 extent.AddPoint(x, y); |
146 } | |
147 | |
339 | 148 |
338 | 149 public: |
341 | 150 Bitmap() : |
339 | 151 visible_(true), |
343 | 152 hasSize_(false), |
339 | 153 width_(0), |
154 height_(0), | |
155 hasCrop_(false), | |
342 | 156 pixelSpacingX_(1), |
157 pixelSpacingY_(1), | |
158 panX_(0), | |
346 | 159 panY_(0), |
160 angle_(45.0 / 180.0 * boost::math::constants::pi<double>()) | |
339 | 161 { |
342 | 162 UpdateTransform(); |
339 | 163 } |
164 | |
343 | 165 virtual ~Bitmap() |
166 { | |
167 } | |
168 | |
339 | 169 void ResetCrop() |
170 { | |
171 hasCrop_ = false; | |
172 } | |
173 | |
174 void Crop(unsigned int x, | |
175 unsigned int y, | |
176 unsigned int width, | |
177 unsigned int height) | |
178 { | |
179 hasCrop_ = true; | |
180 cropX_ = x; | |
181 cropY_ = y; | |
182 cropWidth_ = width; | |
183 cropHeight_ = height; | |
184 } | |
185 | |
186 void GetCrop(unsigned int& x, | |
187 unsigned int& y, | |
188 unsigned int& width, | |
189 unsigned int& height) const | |
338 | 190 { |
339 | 191 if (hasCrop_) |
192 { | |
193 x = cropX_; | |
194 y = cropY_; | |
195 width = cropWidth_; | |
196 height = cropHeight_; | |
197 } | |
198 else | |
199 { | |
200 x = 0; | |
201 y = 0; | |
202 width = width_; | |
203 height = height_; | |
204 } | |
205 } | |
206 | |
346 | 207 void SetAngle(double angle) |
208 { | |
209 angle_ = angle; | |
210 UpdateTransform(); | |
211 } | |
212 | |
213 double GetAngle() const | |
214 { | |
215 return angle_; | |
216 } | |
217 | |
339 | 218 bool IsVisible() const |
219 { | |
220 return visible_; | |
221 } | |
222 | |
223 void SetVisible(bool visible) | |
224 { | |
225 visible_ = visible; | |
226 } | |
227 | |
228 | |
343 | 229 void SetSize(unsigned int width, |
230 unsigned int height) | |
338 | 231 { |
343 | 232 if (hasSize_ && |
233 (width != width_ || | |
234 height != height_)) | |
339 | 235 { |
343 | 236 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
237 } |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
238 |
343 | 239 hasSize_ = true; |
240 width_ = width; | |
241 height_ = height; | |
346 | 242 |
243 UpdateTransform(); | |
338 | 244 } |
245 | |
343 | 246 |
247 void CheckSize(unsigned int width, | |
248 unsigned int height) | |
338 | 249 { |
343 | 250 if (hasSize_ && |
251 (width != width_ || | |
252 height != height_)) | |
338 | 253 { |
343 | 254 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); |
339 | 255 } |
256 } | |
343 | 257 |
339 | 258 |
259 Extent2D GetExtent() const | |
260 { | |
261 Extent2D extent; | |
262 | |
263 unsigned int x, y, width, height; | |
264 GetCrop(x, y, width, height); | |
265 | |
266 double dx = static_cast<double>(x) - 0.5; | |
267 double dy = static_cast<double>(y) - 0.5; | |
268 double dwidth = static_cast<double>(width); | |
269 double dheight = static_cast<double>(height); | |
342 | 270 |
339 | 271 AddToExtent(extent, dx, dy); |
272 AddToExtent(extent, dx + dwidth, dy); | |
273 AddToExtent(extent, dx, dy + dheight); | |
274 AddToExtent(extent, dx + dwidth, dy + dheight); | |
275 | |
276 return extent; | |
277 } | |
278 | |
279 | |
343 | 280 virtual void Render(Orthanc::ImageAccessor& buffer, |
345 | 281 const ViewportGeometry& view, |
282 ImageInterpolation interpolation) const = 0; | |
341 | 283 |
284 | |
285 bool Contains(double x, | |
286 double y) const | |
287 { | |
288 Matrix inv; | |
289 LinearAlgebra::InvertMatrix(inv, transform_); | |
290 | |
291 Vector p; | |
292 LinearAlgebra::AssignVector(p, x, y, 1); | |
293 | |
294 Vector q = LinearAlgebra::Product(inv, p); | |
295 | |
296 if (!LinearAlgebra::IsNear(q[2], 1.0)) | |
297 { | |
298 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
299 } | |
300 else | |
301 { | |
342 | 302 printf("at: (%.02f, %.02f)\n", q[0], q[1]); |
341 | 303 return (q[0] >= 0 && |
304 q[1] >= 0 && | |
305 q[0] <= static_cast<double>(width_) && | |
306 q[1] <= static_cast<double>(height_)); | |
307 } | |
308 } | |
342 | 309 |
310 | |
311 void SetPan(double x, | |
312 double y) | |
313 { | |
314 panX_ = x; | |
315 panY_ = y; | |
316 UpdateTransform(); | |
317 } | |
318 | |
319 | |
343 | 320 void SetPixelSpacing(double x, |
321 double y) | |
322 { | |
323 pixelSpacingX_ = x; | |
324 pixelSpacingY_ = y; | |
325 UpdateTransform(); | |
326 } | |
327 | |
345 | 328 double GetPixelSpacingX() const |
329 { | |
330 return pixelSpacingX_; | |
331 } | |
332 | |
333 double GetPixelSpacingY() const | |
334 { | |
335 return pixelSpacingY_; | |
336 } | |
343 | 337 |
342 | 338 double GetPanX() const |
339 { | |
340 return panX_; | |
341 } | |
342 | |
343 double GetPanY() const | |
344 { | |
345 return panY_; | |
346 } | |
343 | 347 |
348 virtual bool GetDefaultWindowing(float& center, | |
349 float& width) const | |
350 { | |
351 return false; | |
352 } | |
353 | |
354 const Matrix& GetTransform() const | |
355 { | |
356 return transform_; | |
357 } | |
345 | 358 |
359 | |
360 void DrawBorders(CairoContext& context, | |
361 double zoom) | |
362 { | |
363 unsigned int cx, cy, width, height; | |
364 GetCrop(cx, cy, width, height); | |
365 | |
366 double dx = static_cast<double>(cx); | |
367 double dy = static_cast<double>(cy); | |
368 double dwidth = static_cast<double>(width); | |
369 double dheight = static_cast<double>(height); | |
370 | |
371 cairo_t* cr = context.GetObject(); | |
372 cairo_set_line_width(cr, 2.0 / zoom); | |
373 | |
374 double x, y; | |
375 x = dx; | |
376 y = dy; | |
346 | 377 ApplyTransform(x, y, transform_); |
345 | 378 cairo_move_to(cr, x, y); |
379 | |
380 x = dx + dwidth; | |
381 y = dy; | |
346 | 382 ApplyTransform(x, y, transform_); |
345 | 383 cairo_line_to(cr, x, y); |
384 | |
385 x = dx + dwidth; | |
386 y = dy + dheight; | |
346 | 387 ApplyTransform(x, y, transform_); |
345 | 388 cairo_line_to(cr, x, y); |
389 | |
390 x = dx; | |
391 y = dy + dheight; | |
346 | 392 ApplyTransform(x, y, transform_); |
345 | 393 cairo_line_to(cr, x, y); |
394 | |
395 x = dx; | |
396 y = dy; | |
346 | 397 ApplyTransform(x, y, transform_); |
345 | 398 cairo_line_to(cr, x, y); |
399 | |
400 cairo_stroke(cr); | |
401 } | |
338 | 402 }; |
403 | |
404 | |
343 | 405 |
406 class DicomBitmap : public Bitmap | |
407 { | |
408 private: | |
409 std::auto_ptr<Orthanc::ImageAccessor> source_; // Content of PixelData | |
410 std::auto_ptr<DicomFrameConverter> converter_; | |
411 std::auto_ptr<Orthanc::ImageAccessor> converted_; // Float32 or RGB24 | |
412 | |
413 | |
414 void ApplyConverter() | |
415 { | |
416 if (source_.get() != NULL && | |
417 converter_.get() != NULL) | |
418 { | |
419 converted_.reset(converter_->ConvertFrame(*source_)); | |
420 } | |
421 } | |
422 | |
423 public: | |
424 static OrthancPlugins::DicomTag ConvertTag(const Orthanc::DicomTag& tag) | |
425 { | |
426 return OrthancPlugins::DicomTag(tag.GetGroup(), tag.GetElement()); | |
427 } | |
428 | |
429 void SetDicomTags(const OrthancPlugins::FullOrthancDataset& dataset) | |
430 { | |
431 converter_.reset(new DicomFrameConverter); | |
432 converter_->ReadParameters(dataset); | |
433 ApplyConverter(); | |
434 | |
435 std::string tmp; | |
436 Vector pixelSpacing; | |
437 | |
438 if (dataset.GetStringValue(tmp, ConvertTag(Orthanc::DICOM_TAG_PIXEL_SPACING)) && | |
439 LinearAlgebra::ParseVector(pixelSpacing, tmp) && | |
440 pixelSpacing.size() == 2) | |
441 { | |
442 SetPixelSpacing(pixelSpacing[0], pixelSpacing[1]); | |
443 } | |
444 | |
345 | 445 SetPan(-0.5 * GetPixelSpacingX(), -0.5 * GetPixelSpacingY()); |
446 | |
343 | 447 static unsigned int c = 0; |
448 if (c == 0) | |
449 { | |
450 SetPan(400, 0); | |
451 c ++; | |
452 } | |
453 | |
454 OrthancPlugins::DicomDatasetReader reader(dataset); | |
455 | |
456 unsigned int width, height; | |
457 if (!reader.GetUnsignedIntegerValue(width, ConvertTag(Orthanc::DICOM_TAG_COLUMNS)) || | |
458 !reader.GetUnsignedIntegerValue(height, ConvertTag(Orthanc::DICOM_TAG_ROWS))) | |
459 { | |
460 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
461 } | |
462 else | |
463 { | |
464 SetSize(width, height); | |
465 } | |
466 } | |
467 | |
468 | |
469 void SetSourceImage(Orthanc::ImageAccessor* image) // Takes ownership | |
470 { | |
471 std::auto_ptr<Orthanc::ImageAccessor> raii(image); | |
472 | |
473 if (image == NULL) | |
474 { | |
475 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
476 } | |
477 | |
478 SetSize(image->GetWidth(), image->GetHeight()); | |
479 | |
480 source_ = raii; | |
481 ApplyConverter(); | |
482 } | |
483 | |
484 | |
485 virtual void Render(Orthanc::ImageAccessor& buffer, | |
345 | 486 const ViewportGeometry& view, |
487 ImageInterpolation interpolation) const | |
343 | 488 { |
489 if (converted_.get() != NULL) | |
490 { | |
491 Matrix m = LinearAlgebra::Product(view.GetMatrix(), GetTransform()); | |
345 | 492 ApplyProjectiveTransform(buffer, *converted_, m, interpolation, false); |
343 | 493 } |
494 } | |
495 | |
496 | |
497 virtual bool GetDefaultWindowing(float& center, | |
498 float& width) const | |
499 { | |
500 if (converter_.get() != NULL && | |
501 converter_->HasDefaultWindow()) | |
502 { | |
503 center = static_cast<float>(converter_->GetDefaultWindowCenter()); | |
504 width = static_cast<float>(converter_->GetDefaultWindowWidth()); | |
505 return true; | |
506 } | |
507 else | |
508 { | |
509 return false; | |
510 } | |
511 } | |
512 }; | |
513 | |
514 | |
515 | |
516 | |
517 class AlphaBitmap : public Bitmap | |
518 { | |
519 private: | |
520 const BitmapStack& stack_; | |
521 std::auto_ptr<Orthanc::ImageAccessor> alpha_; // Grayscale8 | |
522 bool useWindowing_; | |
523 float foreground_; | |
524 | |
525 public: | |
526 AlphaBitmap(const BitmapStack& stack) : | |
527 stack_(stack), | |
528 useWindowing_(true), | |
529 foreground_(0) | |
530 { | |
531 } | |
532 | |
533 | |
534 void SetForegroundValue(float foreground) | |
535 { | |
536 useWindowing_ = false; | |
537 foreground_ = foreground; | |
538 } | |
539 | |
540 | |
541 void SetAlpha(Orthanc::ImageAccessor* image) | |
542 { | |
543 std::auto_ptr<Orthanc::ImageAccessor> raii(image); | |
544 | |
545 if (image == NULL) | |
546 { | |
547 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
548 } | |
549 | |
550 if (image->GetFormat() != Orthanc::PixelFormat_Grayscale8) | |
551 { | |
552 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
553 } | |
554 | |
555 SetSize(image->GetWidth(), image->GetHeight()); | |
556 alpha_ = raii; | |
557 } | |
558 | |
559 | |
560 void LoadText(const Orthanc::Font& font, | |
561 const std::string& utf8) | |
562 { | |
563 SetAlpha(font.RenderAlpha(utf8)); | |
564 } | |
565 | |
566 | |
567 virtual void Render(Orthanc::ImageAccessor& buffer, | |
345 | 568 const ViewportGeometry& view, |
569 ImageInterpolation interpolation) const | |
343 | 570 { |
571 if (buffer.GetFormat() != Orthanc::PixelFormat_Float32) | |
572 { | |
573 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
574 } | |
575 | |
576 Matrix m = LinearAlgebra::Product(view.GetMatrix(), GetTransform()); | |
577 | |
578 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); | |
345 | 579 ApplyProjectiveTransform(tmp, *alpha_, m, interpolation, true /* clear */); |
343 | 580 |
581 // Blit | |
582 const unsigned int width = buffer.GetWidth(); | |
583 const unsigned int height = buffer.GetHeight(); | |
584 | |
585 float value = foreground_; | |
586 | |
587 if (useWindowing_) | |
588 { | |
589 float center, width; | |
590 if (stack_.GetWindowing(center, width)) | |
591 { | |
592 value = center + width / 2.0f; | |
593 } | |
594 } | |
595 | |
596 for (unsigned int y = 0; y < height; y++) | |
597 { | |
598 float *q = reinterpret_cast<float*>(buffer.GetRow(y)); | |
599 const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y)); | |
600 | |
601 for (unsigned int x = 0; x < width; x++, p++, q++) | |
602 { | |
603 float a = static_cast<float>(*p) / 255.0f; | |
604 | |
605 *q = (a * value + (1.0f - a) * (*q)); | |
606 } | |
607 } | |
608 } | |
609 }; | |
610 | |
611 | |
612 | |
341 | 613 typedef std::map<size_t, Bitmap*> Bitmaps; |
338 | 614 |
341 | 615 OrthancApiClient& orthanc_; |
616 size_t countBitmaps_; | |
617 bool hasWindowing_; | |
618 float windowingCenter_; | |
619 float windowingWidth_; | |
620 Bitmaps bitmaps_; | |
345 | 621 bool hasSelection_; |
622 size_t selectedBitmap_; | |
338 | 623 |
624 public: | |
625 BitmapStack(MessageBroker& broker, | |
626 OrthancApiClient& orthanc) : | |
627 IObserver(broker), | |
628 IObservable(broker), | |
629 orthanc_(orthanc), | |
341 | 630 countBitmaps_(0), |
338 | 631 hasWindowing_(false), |
632 windowingCenter_(0), // Dummy initialization | |
345 | 633 windowingWidth_(0), // Dummy initialization |
634 hasSelection_(false), | |
635 selectedBitmap_(0) // Dummy initialization | |
338 | 636 { |
637 } | |
638 | |
345 | 639 |
640 void Unselect() | |
641 { | |
642 hasSelection_ = false; | |
643 } | |
644 | |
645 | |
646 void Select(size_t bitmap) | |
647 { | |
648 hasSelection_ = true; | |
649 selectedBitmap_ = bitmap; | |
650 } | |
346 | 651 |
652 | |
653 bool GetSelectedBitmap(size_t& bitmap) const | |
654 { | |
655 if (hasSelection_) | |
656 { | |
657 bitmap = selectedBitmap_; | |
658 return true; | |
659 } | |
660 else | |
661 { | |
662 return false; | |
663 } | |
664 } | |
345 | 665 |
338 | 666 |
667 virtual ~BitmapStack() | |
668 { | |
669 for (Bitmaps::iterator it = bitmaps_.begin(); it != bitmaps_.end(); it++) | |
670 { | |
671 assert(it->second != NULL); | |
672 delete it->second; | |
673 } | |
674 } | |
339 | 675 |
676 | |
343 | 677 bool GetWindowing(float& center, |
678 float& width) const | |
339 | 679 { |
680 if (hasWindowing_) | |
681 { | |
682 center = windowingCenter_; | |
683 width = windowingWidth_; | |
343 | 684 return true; |
339 | 685 } |
686 else | |
687 { | |
343 | 688 return false; |
339 | 689 } |
690 } | |
338 | 691 |
692 | |
343 | 693 size_t LoadText(const Orthanc::Font& font, |
694 const std::string& utf8, | |
695 double x, | |
696 double y) | |
697 { | |
698 std::auto_ptr<AlphaBitmap> alpha(new AlphaBitmap(*this)); | |
699 alpha->LoadText(font, utf8); | |
700 | |
701 size_t bitmap = countBitmaps_++; | |
702 | |
703 bitmaps_[bitmap] = alpha.release(); | |
704 | |
705 return bitmap; | |
706 } | |
707 | |
708 | |
341 | 709 size_t LoadFrame(const std::string& instance, |
710 unsigned int frame, | |
711 bool httpCompression) | |
338 | 712 { |
341 | 713 size_t bitmap = countBitmaps_++; |
338 | 714 |
343 | 715 bitmaps_[bitmap] = new DicomBitmap; |
338 | 716 |
717 | |
718 { | |
719 IWebService::Headers headers; | |
720 std::string uri = "/instances/" + instance + "/tags"; | |
721 orthanc_.GetBinaryAsync(uri, headers, | |
722 new Callable<BitmapStack, OrthancApiClient::BinaryResponseReadyMessage> | |
723 (*this, &BitmapStack::OnTagsReceived), NULL, | |
341 | 724 new Orthanc::SingleValueObject<size_t>(bitmap)); |
338 | 725 } |
726 | |
727 { | |
728 IWebService::Headers headers; | |
729 headers["Accept"] = "image/x-portable-arbitrarymap"; | |
730 | |
731 if (httpCompression) | |
732 { | |
733 headers["Accept-Encoding"] = "gzip"; | |
734 } | |
735 | |
736 std::string uri = "/instances/" + instance + "/frames/" + boost::lexical_cast<std::string>(frame) + "/image-uint16"; | |
737 orthanc_.GetBinaryAsync(uri, headers, | |
738 new Callable<BitmapStack, OrthancApiClient::BinaryResponseReadyMessage> | |
739 (*this, &BitmapStack::OnFrameReceived), NULL, | |
341 | 740 new Orthanc::SingleValueObject<size_t>(bitmap)); |
338 | 741 } |
742 | |
341 | 743 return bitmap; |
338 | 744 } |
745 | |
746 | |
747 void OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) | |
748 { | |
346 | 749 size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload.get())->GetValue(); |
338 | 750 |
341 | 751 printf("JSON received: [%s] (%ld bytes) for bitmap %ld\n", |
752 message.Uri.c_str(), message.AnswerSize, index); | |
338 | 753 |
341 | 754 Bitmaps::iterator bitmap = bitmaps_.find(index); |
338 | 755 if (bitmap != bitmaps_.end()) |
756 { | |
757 assert(bitmap->second != NULL); | |
758 | |
759 OrthancPlugins::FullOrthancDataset dicom(message.Answer, message.AnswerSize); | |
343 | 760 dynamic_cast<DicomBitmap*>(bitmap->second)->SetDicomTags(dicom); |
338 | 761 |
762 float c, w; | |
763 if (!hasWindowing_ && | |
764 bitmap->second->GetDefaultWindowing(c, w)) | |
765 { | |
766 hasWindowing_ = true; | |
767 windowingCenter_ = c; | |
768 windowingWidth_ = w; | |
769 } | |
770 | |
771 EmitMessage(GeometryChangedMessage(*this)); | |
772 } | |
773 } | |
774 | |
775 | |
776 void OnFrameReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) | |
777 { | |
346 | 778 size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload.get())->GetValue(); |
338 | 779 |
341 | 780 printf("Frame received: [%s] (%ld bytes) for bitmap %ld\n", |
781 message.Uri.c_str(), message.AnswerSize, index); | |
782 | |
783 Bitmaps::iterator bitmap = bitmaps_.find(index); | |
338 | 784 if (bitmap != bitmaps_.end()) |
785 { | |
786 assert(bitmap->second != NULL); | |
787 | |
788 std::string content; | |
789 if (message.AnswerSize > 0) | |
790 { | |
791 content.assign(reinterpret_cast<const char*>(message.Answer), message.AnswerSize); | |
792 } | |
793 | |
794 std::auto_ptr<Orthanc::PamReader> reader(new Orthanc::PamReader); | |
795 reader->ReadFromMemory(content); | |
343 | 796 dynamic_cast<DicomBitmap*>(bitmap->second)->SetSourceImage(reader.release()); |
338 | 797 |
798 EmitMessage(ContentChangedMessage(*this)); | |
799 } | |
800 } | |
339 | 801 |
802 | |
803 Extent2D GetSceneExtent() const | |
804 { | |
805 Extent2D extent; | |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
806 |
339 | 807 for (Bitmaps::const_iterator it = bitmaps_.begin(); |
808 it != bitmaps_.end(); ++it) | |
809 { | |
810 assert(it->second != NULL); | |
811 extent.Union(it->second->GetExtent()); | |
812 } | |
813 | |
814 return extent; | |
815 } | |
816 | |
817 | |
818 void Render(Orthanc::ImageAccessor& buffer, | |
345 | 819 const ViewportGeometry& view, |
820 ImageInterpolation interpolation) const | |
339 | 821 { |
822 Orthanc::ImageProcessing::Set(buffer, 0); | |
823 | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
824 // Render layers in the background-to-foreground order |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
825 for (size_t index = 0; index < countBitmaps_; index++) |
339 | 826 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
827 Bitmaps::const_iterator it = bitmaps_.find(index); |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
828 if (it != bitmaps_.end()) |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
829 { |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
830 assert(it->second != NULL); |
345 | 831 it->second->Render(buffer, view, interpolation); |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
832 } |
339 | 833 } |
834 } | |
342 | 835 |
836 | |
837 bool LookupBitmap(size_t& index /* out */, | |
838 double x, | |
839 double y) const | |
840 { | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
841 // Render layers in the foreground-to-background order |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
842 for (size_t i = countBitmaps_; i > 0; i--) |
342 | 843 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
844 index = i - 1; |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
845 Bitmaps::const_iterator it = bitmaps_.find(index); |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
846 if (it != bitmaps_.end()) |
342 | 847 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
848 assert(it->second != NULL); |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
849 if (it->second->Contains(x, y)) |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
850 { |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
851 return true; |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
852 } |
342 | 853 } |
854 } | |
855 | |
856 return false; | |
857 } | |
858 | |
859 | |
860 void SetPan(size_t index, | |
861 double panX, | |
862 double panY) | |
863 { | |
864 Bitmaps::iterator bitmap = bitmaps_.find(index); | |
865 if (bitmap != bitmaps_.end()) | |
866 { | |
867 assert(bitmap->second != NULL); | |
868 bitmap->second->SetPan(panX, panY); | |
869 } | |
870 } | |
871 | |
872 | |
873 void GetPan(double& panX, | |
874 double& panY, | |
875 size_t index) const | |
876 { | |
877 Bitmaps::const_iterator bitmap = bitmaps_.find(index); | |
878 if (bitmap != bitmaps_.end()) | |
879 { | |
880 assert(bitmap->second != NULL); | |
881 panX = bitmap->second->GetPanX(); | |
882 panY = bitmap->second->GetPanY(); | |
883 } | |
884 else | |
885 { | |
886 panX = 0; | |
887 panY = 0; | |
888 } | |
889 } | |
345 | 890 |
891 | |
892 void DrawControls(CairoSurface& surface, | |
893 const ViewportGeometry& view) | |
894 { | |
895 if (hasSelection_) | |
896 { | |
897 Bitmaps::const_iterator bitmap = bitmaps_.find(selectedBitmap_); | |
898 | |
899 if (bitmap != bitmaps_.end()) | |
900 { | |
901 CairoContext context(surface); | |
902 | |
903 context.SetSourceColor(255, 0, 0); | |
904 view.ApplyTransform(context); | |
905 bitmap->second->DrawBorders(context, view.GetZoom()); | |
906 } | |
907 } | |
908 } | |
338 | 909 }; |
910 | |
341 | 911 |
912 class BitmapStackInteractor : public IWorldSceneInteractor | |
913 { | |
342 | 914 private: |
915 BitmapStack& stack_; | |
916 | |
917 | |
918 class MoveBitmapTracker : public IWorldSceneMouseTracker | |
919 { | |
920 private: | |
921 BitmapStack& stack_; | |
922 size_t bitmap_; | |
923 double clickX_; | |
924 double clickY_; | |
343 | 925 double panX_; |
926 double panY_; | |
927 bool oneAxis_; | |
342 | 928 |
929 public: | |
343 | 930 MoveBitmapTracker(BitmapStack& stack, |
342 | 931 size_t bitmap, |
932 double x, | |
343 | 933 double y, |
934 bool oneAxis) : | |
342 | 935 stack_(stack), |
936 bitmap_(bitmap), | |
937 clickX_(x), | |
343 | 938 clickY_(y), |
939 oneAxis_(oneAxis) | |
342 | 940 { |
343 | 941 stack.GetPan(panX_, panY_, bitmap_); |
342 | 942 } |
943 | |
944 virtual bool HasRender() const | |
945 { | |
946 return false; | |
947 } | |
948 | |
949 virtual void Render(CairoContext& context, | |
950 double zoom) | |
951 { | |
952 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
953 } | |
954 | |
955 virtual void MouseUp() | |
956 { | |
957 } | |
958 | |
959 virtual void MouseMove(int displayX, | |
960 int displayY, | |
961 double sceneX, | |
962 double sceneY) | |
963 { | |
343 | 964 double dx = sceneX - clickX_; |
965 double dy = sceneY - clickY_; | |
966 | |
967 if (oneAxis_) | |
968 { | |
969 if (fabs(dx) > fabs(dy)) | |
970 { | |
971 stack_.SetPan(bitmap_, dx + panX_, panY_); | |
972 } | |
973 else | |
974 { | |
345 | 975 stack_.SetPan(bitmap_, panX_, dy + panY_); |
343 | 976 } |
977 } | |
978 else | |
979 { | |
980 stack_.SetPan(bitmap_, dx + panX_, dy + panY_); | |
981 } | |
342 | 982 } |
983 }; | |
984 | |
985 | |
341 | 986 public: |
342 | 987 BitmapStackInteractor(BitmapStack& stack) : |
988 stack_(stack) | |
989 { | |
990 } | |
991 | |
341 | 992 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, |
993 const ViewportGeometry& view, | |
994 MouseButton button, | |
995 KeyboardModifiers modifiers, | |
996 double x, | |
997 double y, | |
998 IStatusBar* statusBar) | |
999 { | |
342 | 1000 if (button == MouseButton_Left) |
1001 { | |
1002 size_t bitmap; | |
346 | 1003 |
342 | 1004 if (stack_.LookupBitmap(bitmap, x, y)) |
1005 { | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1006 printf("CLICK on bitmap %ld\n", bitmap); |
346 | 1007 |
1008 size_t selected; | |
1009 if (stack_.GetSelectedBitmap(selected) && | |
1010 bitmap == selected) | |
1011 { | |
1012 return new MoveBitmapTracker(stack_, bitmap, x, y, | |
1013 (modifiers & KeyboardModifiers_Shift)); | |
1014 } | |
1015 else | |
1016 { | |
1017 stack_.Select(bitmap); | |
1018 return NULL; | |
1019 } | |
342 | 1020 } |
1021 else | |
1022 { | |
1023 printf("CLICK outside\n"); | |
345 | 1024 stack_.Unselect(); |
342 | 1025 return NULL; |
1026 } | |
1027 } | |
1028 else | |
1029 { | |
1030 return NULL; | |
1031 } | |
341 | 1032 } |
1033 | |
1034 virtual void MouseOver(CairoContext& context, | |
1035 WorldSceneWidget& widget, | |
1036 const ViewportGeometry& view, | |
1037 double x, | |
1038 double y, | |
1039 IStatusBar* statusBar) | |
1040 { | |
1041 } | |
1042 | |
1043 virtual void MouseWheel(WorldSceneWidget& widget, | |
1044 MouseWheelDirection direction, | |
1045 KeyboardModifiers modifiers, | |
1046 IStatusBar* statusBar) | |
1047 { | |
1048 } | |
1049 | |
1050 virtual void KeyPressed(WorldSceneWidget& widget, | |
1051 KeyboardKeys key, | |
1052 char keyChar, | |
1053 KeyboardModifiers modifiers, | |
1054 IStatusBar* statusBar) | |
1055 { | |
342 | 1056 if (keyChar == 's') |
1057 widget.FitContent(); | |
341 | 1058 } |
1059 }; | |
1060 | |
1061 | |
338 | 1062 |
1063 class BitmapStackWidget : | |
1064 public WorldSceneWidget, | |
1065 public IObservable, | |
1066 public IObserver | |
1067 { | |
1068 private: | |
341 | 1069 BitmapStack& stack_; |
1070 BitmapStackInteractor myInteractor_; | |
337 | 1071 |
336
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1072 protected: |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1073 virtual Extent2D GetSceneExtent() |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1074 { |
339 | 1075 return stack_.GetSceneExtent(); |
336
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1076 } |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1077 |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1078 virtual bool RenderScene(CairoContext& context, |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1079 const ViewportGeometry& view) |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1080 { |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1081 // "Render()" has been replaced |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1082 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1083 } |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1084 |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1085 public: |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1086 BitmapStackWidget(MessageBroker& broker, |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1087 BitmapStack& stack, |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1088 const std::string& name) : |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1089 WorldSceneWidget(name), |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1090 IObservable(broker), |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1091 IObserver(broker), |
342 | 1092 stack_(stack), |
1093 myInteractor_(stack_) | |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1094 { |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1095 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::GeometryChangedMessage>(*this, &BitmapStackWidget::OnGeometryChanged)); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1096 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::ContentChangedMessage>(*this, &BitmapStackWidget::OnContentChanged)); |
341 | 1097 |
1098 SetInteractor(myInteractor_); | |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1099 } |
339 | 1100 |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1101 void OnGeometryChanged(const BitmapStack::GeometryChangedMessage& message) |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1102 { |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1103 printf("Geometry has changed\n"); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1104 FitContent(); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1105 } |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1106 |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1107 void OnContentChanged(const BitmapStack::ContentChangedMessage& message) |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1108 { |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1109 printf("Content has changed\n"); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1110 NotifyContentChanged(); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1111 } |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1112 |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1113 virtual bool Render(Orthanc::ImageAccessor& target) |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1114 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1115 Orthanc::Image buffer(Orthanc::PixelFormat_Float32, target.GetWidth(), |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1116 target.GetHeight(), false); |
345 | 1117 |
1118 // TODO => rendering quality | |
1119 //stack_.Render(buffer, GetView(), ImageInterpolation_Nearest); | |
1120 stack_.Render(buffer, GetView(), ImageInterpolation_Bilinear); | |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1121 |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1122 // As in GrayscaleFrameRenderer => TODO MERGE? |
339 | 1123 |
1124 float windowCenter, windowWidth; | |
343 | 1125 if (!stack_.GetWindowing(windowCenter, windowWidth)) |
1126 { | |
1127 windowCenter = 128; | |
1128 windowWidth = 256; | |
1129 } | |
339 | 1130 |
1131 float x0 = windowCenter - windowWidth / 2.0f; | |
1132 float x1 = windowCenter + windowWidth / 2.0f; | |
1133 | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1134 if (windowWidth >= 0.001f) // Avoid division by zero at (*) |
339 | 1135 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1136 const unsigned int width = target.GetWidth(); |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1137 const unsigned int height = target.GetHeight(); |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1138 |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1139 for (unsigned int y = 0; y < height; y++) |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1140 { |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1141 const float* p = reinterpret_cast<const float*>(buffer.GetConstRow(y)); |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1142 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); |
339 | 1143 |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1144 for (unsigned int x = 0; x < width; x++, p++, q += 4) |
339 | 1145 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1146 uint8_t v = 0; |
339 | 1147 if (*p >= x1) |
1148 { | |
1149 v = 255; | |
1150 } | |
1151 else if (*p <= x0) | |
1152 { | |
1153 v = 0; | |
1154 } | |
1155 else | |
1156 { | |
1157 // https://en.wikipedia.org/wiki/Linear_interpolation | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1158 v = static_cast<uint8_t>(255.0f * (*p - x0) / (x1 - x0)); // (*) |
339 | 1159 } |
1160 | |
1161 // TODO MONOCHROME1 | |
1162 /*if (invert_) | |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1163 { |
339 | 1164 v = 255 - v; |
1165 }*/ | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1166 |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1167 q[0] = v; |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1168 q[1] = v; |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1169 q[2] = v; |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1170 q[3] = 255; |
339 | 1171 } |
1172 } | |
1173 } | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1174 else |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1175 { |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1176 Orthanc::ImageProcessing::Set(target, 0, 0, 0, 255); |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1177 } |
339 | 1178 |
345 | 1179 { |
1180 // TODO => REFACTOR | |
1181 CairoSurface surface(target); | |
1182 stack_.DrawControls(surface, GetView()); | |
1183 } | |
1184 | |
337 | 1185 return true; |
336
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1186 } |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1187 |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1188 }; |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1189 |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1190 |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1191 namespace Samples |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1192 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1193 class SingleFrameEditorApplication : |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1194 public SampleSingleCanvasApplicationBase, |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1195 public IObserver |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1196 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1197 enum Tools |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1198 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1199 Tools_Crop, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1200 Tools_Windowing, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1201 Tools_Zoom, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1202 Tools_Pan |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1203 }; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1204 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1205 enum Actions |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1206 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1207 Actions_Invert, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1208 Actions_RotateLeft, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1209 Actions_RotateRight |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1210 }; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1211 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1212 private: |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1213 class Interactor : public IWorldSceneInteractor |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1214 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1215 private: |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1216 SingleFrameEditorApplication& application_; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1217 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1218 public: |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1219 Interactor(SingleFrameEditorApplication& application) : |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1220 application_(application) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1221 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1222 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1223 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1224 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1225 const ViewportGeometry& view, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1226 MouseButton button, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1227 KeyboardModifiers modifiers, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1228 double x, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1229 double y, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1230 IStatusBar* statusBar) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1231 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1232 switch (application_.currentTool_) { |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1233 case Tools_Zoom: |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1234 printf("ZOOM\n"); |
329
b10dfdb96866
removing WorldSceneWidget::IWorldObserver
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
1235 |
b10dfdb96866
removing WorldSceneWidget::IWorldObserver
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
1236 case Tools_Crop: |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1237 case Tools_Windowing: |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1238 case Tools_Pan: |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1239 // TODO return the right mouse tracker |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1240 return NULL; |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1241 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1242 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1243 return NULL; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1244 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1245 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1246 virtual void MouseOver(CairoContext& context, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1247 WorldSceneWidget& widget, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1248 const ViewportGeometry& view, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1249 double x, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1250 double y, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1251 IStatusBar* statusBar) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1252 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1253 if (statusBar != NULL) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1254 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1255 char buf[64]; |
336
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1256 sprintf(buf, "X = %.02f Y = %.02f (in cm)", x / 10.0, y / 10.0); |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
1257 statusBar->SetMessage(buf); |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1258 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1259 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1260 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1261 virtual void MouseWheel(WorldSceneWidget& widget, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1262 MouseWheelDirection direction, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1263 KeyboardModifiers modifiers, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1264 IStatusBar* statusBar) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1265 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1266 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1267 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1268 virtual void KeyPressed(WorldSceneWidget& widget, |
327 | 1269 KeyboardKeys key, |
1270 char keyChar, | |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1271 KeyboardModifiers modifiers, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1272 IStatusBar* statusBar) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1273 { |
327 | 1274 switch (keyChar) |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1275 { |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1276 case 's': |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1277 widget.FitContent(); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1278 break; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1279 case 'p': |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1280 application_.currentTool_ = Tools_Pan; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1281 break; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1282 case 'z': |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1283 application_.currentTool_ = Tools_Zoom; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1284 break; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1285 case 'c': |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1286 application_.currentTool_ = Tools_Crop; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1287 break; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1288 case 'w': |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1289 application_.currentTool_ = Tools_Windowing; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1290 break; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1291 case 'i': |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1292 application_.Invert(); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1293 break; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1294 case 'r': |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1295 if (modifiers == KeyboardModifiers_None) |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1296 application_.Rotate(90); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1297 else |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1298 application_.Rotate(-90); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1299 break; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1300 case 'e': |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1301 application_.Export(); |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1302 break; |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1303 default: |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1304 break; |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1305 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1306 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1307 }; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1308 |
334
c34784e5f299
compatibility fixes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
330
diff
changeset
|
1309 std::auto_ptr<Interactor> mainWidgetInteractor_; |
c34784e5f299
compatibility fixes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
330
diff
changeset
|
1310 std::auto_ptr<OrthancApiClient> orthancApiClient_; |
338 | 1311 std::auto_ptr<BitmapStack> stack_; |
334
c34784e5f299
compatibility fixes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
330
diff
changeset
|
1312 Tools currentTool_; |
c34784e5f299
compatibility fixes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
330
diff
changeset
|
1313 const OrthancFrameLayerSource* source_; |
c34784e5f299
compatibility fixes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
330
diff
changeset
|
1314 unsigned int slice_; |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1315 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1316 public: |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1317 SingleFrameEditorApplication(MessageBroker& broker) : |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1318 IObserver(broker), |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1319 currentTool_(Tools_Zoom), |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1320 source_(NULL), |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1321 slice_(0) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1322 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1323 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1324 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1325 virtual void DeclareStartupOptions(boost::program_options::options_description& options) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1326 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1327 boost::program_options::options_description generic("Sample options"); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1328 generic.add_options() |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1329 ("instance", boost::program_options::value<std::string>(), |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1330 "Orthanc ID of the instance") |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1331 ("frame", boost::program_options::value<unsigned int>()->default_value(0), |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1332 "Number of the frame, for multi-frame DICOM instances") |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1333 ; |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1334 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1335 options.add(generic); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1336 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1337 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1338 virtual void Initialize(StoneApplicationContext* context, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1339 IStatusBar& statusBar, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1340 const boost::program_options::variables_map& parameters) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1341 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1342 using namespace OrthancStone; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1343 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1344 context_ = context; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1345 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1346 statusBar.SetMessage("Use the key \"s\" to reinitialize the layout, \"p\" to pan, \"z\" to zoom, \"c\" to crop, \"i\" to invert, \"w\" to change windowing, \"r\" to rotate cw, \"shift+r\" to rotate ccw"); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1347 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1348 if (parameters.count("instance") != 1) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1349 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1350 LOG(ERROR) << "The instance ID is missing"; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1351 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1352 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1353 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1354 std::string instance = parameters["instance"].as<std::string>(); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1355 int frame = parameters["frame"].as<unsigned int>(); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1356 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1357 orthancApiClient_.reset(new OrthancApiClient(IObserver::broker_, context_->GetWebService())); |
337 | 1358 |
343 | 1359 Orthanc::FontRegistry fonts; |
1360 fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); | |
1361 | |
338 | 1362 stack_.reset(new BitmapStack(IObserver::broker_, *orthancApiClient_)); |
1363 stack_->LoadFrame(instance, frame, false); | |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1364 stack_->LoadFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", frame, false); |
343 | 1365 stack_->LoadText(fonts.GetFont(0), "Hello\nworld\nBonjour, Alain", 0, -50); |
337 | 1366 |
338 | 1367 mainWidget_ = new BitmapStackWidget(IObserver::broker_, *stack_, "main-widget"); |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1368 mainWidget_->SetTransmitMouseOver(true); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1369 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1370 mainWidgetInteractor_.reset(new Interactor(*this)); |
341 | 1371 //mainWidget_->SetInteractor(*mainWidgetInteractor_); |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1372 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1373 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1374 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1375 void Invert() |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1376 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1377 // TODO |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1378 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1379 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1380 void Rotate(int degrees) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1381 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1382 // TODO |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1383 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1384 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1385 void Export() |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1386 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1387 // TODO: export dicom file to a temporary file |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1388 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1389 }; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1390 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1391 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1392 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1393 } |