Mercurial > hg > orthanc-stone
comparison Applications/Samples/SingleFrameEditorApplication.h @ 345:55438b1ca317 am-2
drawing borders
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 22 Oct 2018 17:02:34 +0200 |
parents | fdec8e6893cb |
children | c2e040ea8fbe |
comparison
equal
deleted
inserted
replaced
344:fdec8e6893cb | 345:55438b1ca317 |
---|---|
76 transform_(0, 0) = pixelSpacingX_; | 76 transform_(0, 0) = pixelSpacingX_; |
77 transform_(1, 1) = pixelSpacingY_; | 77 transform_(1, 1) = pixelSpacingY_; |
78 transform_(0, 2) = panX_; | 78 transform_(0, 2) = panX_; |
79 transform_(1, 2) = panY_; | 79 transform_(1, 2) = panY_; |
80 | 80 |
81 | |
82 #if 0 | 81 #if 0 |
83 double a = 10.0 / 180.0 * boost::math::constants::pi<double>(); | 82 double a = 10.0 / 180.0 * boost::math::constants::pi<double>(); |
84 Matrix m; | 83 Matrix m; |
85 const double v[] = { cos(a), -sin(a), 0, | 84 const double v[] = { cos(a), -sin(a), 0, |
86 sin(a), cos(a), 0, | 85 sin(a), cos(a), 0, |
87 0, 0, 1 }; | 86 0, 0, 1 }; |
88 LinearAlgebra::FillMatrix(m, 3, 3, v); | 87 LinearAlgebra::FillMatrix(m, 3, 3, v); |
89 transform_ = LinearAlgebra::Product(m, transform_); | 88 transform_ = LinearAlgebra::Product(m, transform_); |
90 #endif | 89 #endif |
91 } | 90 } |
91 | |
92 | |
93 void MapImageToScene(double& x, | |
94 double& y) const | |
95 { | |
96 Vector p; | |
97 LinearAlgebra::AssignVector(p, x, y, 1); | |
98 | |
99 Vector q = LinearAlgebra::Product(transform_, p); | |
100 | |
101 if (!LinearAlgebra::IsNear(q[2], 1.0)) | |
102 { | |
103 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
104 } | |
105 else | |
106 { | |
107 x = q[0]; | |
108 y = q[1]; | |
109 } | |
110 } | |
92 | 111 |
93 | 112 |
94 void AddToExtent(Extent2D& extent, | 113 void AddToExtent(Extent2D& extent, |
95 double x, | 114 double x, |
96 double y) const | 115 double y) const |
97 { | 116 { |
98 Vector p; | 117 MapImageToScene(x, y); |
99 LinearAlgebra::AssignVector(p, x, y, 1); | 118 extent.AddPoint(x, y); |
100 | |
101 Vector q = LinearAlgebra::Product(transform_, p); | |
102 | |
103 if (!LinearAlgebra::IsNear(q[2], 1.0)) | |
104 { | |
105 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
106 } | |
107 else | |
108 { | |
109 extent.AddPoint(q[0], q[1]); | |
110 } | |
111 } | 119 } |
112 | 120 |
113 | 121 |
114 public: | 122 public: |
115 Bitmap() : | 123 Bitmap() : |
227 return extent; | 235 return extent; |
228 } | 236 } |
229 | 237 |
230 | 238 |
231 virtual void Render(Orthanc::ImageAccessor& buffer, | 239 virtual void Render(Orthanc::ImageAccessor& buffer, |
232 const ViewportGeometry& view) const = 0; | 240 const ViewportGeometry& view, |
241 ImageInterpolation interpolation) const = 0; | |
233 | 242 |
234 | 243 |
235 bool Contains(double x, | 244 bool Contains(double x, |
236 double y) const | 245 double y) const |
237 { | 246 { |
273 pixelSpacingX_ = x; | 282 pixelSpacingX_ = x; |
274 pixelSpacingY_ = y; | 283 pixelSpacingY_ = y; |
275 UpdateTransform(); | 284 UpdateTransform(); |
276 } | 285 } |
277 | 286 |
287 double GetPixelSpacingX() const | |
288 { | |
289 return pixelSpacingX_; | |
290 } | |
291 | |
292 double GetPixelSpacingY() const | |
293 { | |
294 return pixelSpacingY_; | |
295 } | |
278 | 296 |
279 double GetPanX() const | 297 double GetPanX() const |
280 { | 298 { |
281 return panX_; | 299 return panX_; |
282 } | 300 } |
283 | 301 |
284 | |
285 double GetPanY() const | 302 double GetPanY() const |
286 { | 303 { |
287 return panY_; | 304 return panY_; |
288 } | 305 } |
289 | |
290 | 306 |
291 virtual bool GetDefaultWindowing(float& center, | 307 virtual bool GetDefaultWindowing(float& center, |
292 float& width) const | 308 float& width) const |
293 { | 309 { |
294 return false; | 310 return false; |
295 } | 311 } |
296 | 312 |
297 | |
298 const Matrix& GetTransform() const | 313 const Matrix& GetTransform() const |
299 { | 314 { |
300 return transform_; | 315 return transform_; |
316 } | |
317 | |
318 | |
319 void DrawBorders(CairoContext& context, | |
320 double zoom) | |
321 { | |
322 unsigned int cx, cy, width, height; | |
323 GetCrop(cx, cy, width, height); | |
324 | |
325 double dx = static_cast<double>(cx); | |
326 double dy = static_cast<double>(cy); | |
327 double dwidth = static_cast<double>(width); | |
328 double dheight = static_cast<double>(height); | |
329 | |
330 cairo_t* cr = context.GetObject(); | |
331 cairo_set_line_width(cr, 2.0 / zoom); | |
332 | |
333 double x, y; | |
334 x = dx; | |
335 y = dy; | |
336 MapImageToScene(x, y); | |
337 cairo_move_to(cr, x, y); | |
338 | |
339 x = dx + dwidth; | |
340 y = dy; | |
341 MapImageToScene(x, y); | |
342 cairo_line_to(cr, x, y); | |
343 | |
344 x = dx + dwidth; | |
345 y = dy + dheight; | |
346 MapImageToScene(x, y); | |
347 cairo_line_to(cr, x, y); | |
348 | |
349 x = dx; | |
350 y = dy + dheight; | |
351 MapImageToScene(x, y); | |
352 cairo_line_to(cr, x, y); | |
353 | |
354 x = dx; | |
355 y = dy; | |
356 MapImageToScene(x, y); | |
357 cairo_line_to(cr, x, y); | |
358 | |
359 cairo_stroke(cr); | |
301 } | 360 } |
302 }; | 361 }; |
303 | 362 |
304 | 363 |
305 | 364 |
340 pixelSpacing.size() == 2) | 399 pixelSpacing.size() == 2) |
341 { | 400 { |
342 SetPixelSpacing(pixelSpacing[0], pixelSpacing[1]); | 401 SetPixelSpacing(pixelSpacing[0], pixelSpacing[1]); |
343 } | 402 } |
344 | 403 |
404 SetPan(-0.5 * GetPixelSpacingX(), -0.5 * GetPixelSpacingY()); | |
405 | |
345 static unsigned int c = 0; | 406 static unsigned int c = 0; |
346 if (c == 0) | 407 if (c == 0) |
347 { | 408 { |
348 SetPan(400, 0); | 409 SetPan(400, 0); |
349 c ++; | 410 c ++; |
379 ApplyConverter(); | 440 ApplyConverter(); |
380 } | 441 } |
381 | 442 |
382 | 443 |
383 virtual void Render(Orthanc::ImageAccessor& buffer, | 444 virtual void Render(Orthanc::ImageAccessor& buffer, |
384 const ViewportGeometry& view) const | 445 const ViewportGeometry& view, |
446 ImageInterpolation interpolation) const | |
385 { | 447 { |
386 if (converted_.get() != NULL) | 448 if (converted_.get() != NULL) |
387 { | 449 { |
388 Matrix m = LinearAlgebra::Product(view.GetMatrix(), GetTransform()); | 450 Matrix m = LinearAlgebra::Product(view.GetMatrix(), GetTransform()); |
389 //ApplyProjectiveTransform(buffer, *converted_, m, ImageInterpolation_Bilinear, false); | 451 ApplyProjectiveTransform(buffer, *converted_, m, interpolation, false); |
390 ApplyProjectiveTransform(buffer, *converted_, m, ImageInterpolation_Nearest, false); | |
391 } | 452 } |
392 } | 453 } |
393 | 454 |
394 | 455 |
395 virtual bool GetDefaultWindowing(float& center, | 456 virtual bool GetDefaultWindowing(float& center, |
461 SetAlpha(font.RenderAlpha(utf8)); | 522 SetAlpha(font.RenderAlpha(utf8)); |
462 } | 523 } |
463 | 524 |
464 | 525 |
465 virtual void Render(Orthanc::ImageAccessor& buffer, | 526 virtual void Render(Orthanc::ImageAccessor& buffer, |
466 const ViewportGeometry& view) const | 527 const ViewportGeometry& view, |
528 ImageInterpolation interpolation) const | |
467 { | 529 { |
468 if (buffer.GetFormat() != Orthanc::PixelFormat_Float32) | 530 if (buffer.GetFormat() != Orthanc::PixelFormat_Float32) |
469 { | 531 { |
470 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | 532 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); |
471 } | 533 } |
472 | 534 |
473 Matrix m = LinearAlgebra::Product(view.GetMatrix(), GetTransform()); | 535 Matrix m = LinearAlgebra::Product(view.GetMatrix(), GetTransform()); |
474 | 536 |
475 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); | 537 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); |
476 ApplyProjectiveTransform(tmp, *alpha_, m, ImageInterpolation_Nearest, true /* clear */); | 538 ApplyProjectiveTransform(tmp, *alpha_, m, interpolation, true /* clear */); |
477 | 539 |
478 // Blit | 540 // Blit |
479 const unsigned int width = buffer.GetWidth(); | 541 const unsigned int width = buffer.GetWidth(); |
480 const unsigned int height = buffer.GetHeight(); | 542 const unsigned int height = buffer.GetHeight(); |
481 | 543 |
513 size_t countBitmaps_; | 575 size_t countBitmaps_; |
514 bool hasWindowing_; | 576 bool hasWindowing_; |
515 float windowingCenter_; | 577 float windowingCenter_; |
516 float windowingWidth_; | 578 float windowingWidth_; |
517 Bitmaps bitmaps_; | 579 Bitmaps bitmaps_; |
580 bool hasSelection_; | |
581 size_t selectedBitmap_; | |
518 | 582 |
519 public: | 583 public: |
520 BitmapStack(MessageBroker& broker, | 584 BitmapStack(MessageBroker& broker, |
521 OrthancApiClient& orthanc) : | 585 OrthancApiClient& orthanc) : |
522 IObserver(broker), | 586 IObserver(broker), |
523 IObservable(broker), | 587 IObservable(broker), |
524 orthanc_(orthanc), | 588 orthanc_(orthanc), |
525 countBitmaps_(0), | 589 countBitmaps_(0), |
526 hasWindowing_(false), | 590 hasWindowing_(false), |
527 windowingCenter_(0), // Dummy initialization | 591 windowingCenter_(0), // Dummy initialization |
528 windowingWidth_(0) // Dummy initialization | 592 windowingWidth_(0), // Dummy initialization |
529 { | 593 hasSelection_(false), |
530 } | 594 selectedBitmap_(0) // Dummy initialization |
531 | 595 { |
596 } | |
597 | |
598 | |
599 void Unselect() | |
600 { | |
601 hasSelection_ = false; | |
602 } | |
603 | |
604 | |
605 void Select(size_t bitmap) | |
606 { | |
607 hasSelection_ = true; | |
608 selectedBitmap_ = bitmap; | |
609 } | |
610 | |
532 | 611 |
533 virtual ~BitmapStack() | 612 virtual ~BitmapStack() |
534 { | 613 { |
535 for (Bitmaps::iterator it = bitmaps_.begin(); it != bitmaps_.end(); it++) | 614 for (Bitmaps::iterator it = bitmaps_.begin(); it != bitmaps_.end(); it++) |
536 { | 615 { |
680 return extent; | 759 return extent; |
681 } | 760 } |
682 | 761 |
683 | 762 |
684 void Render(Orthanc::ImageAccessor& buffer, | 763 void Render(Orthanc::ImageAccessor& buffer, |
685 const ViewportGeometry& view) const | 764 const ViewportGeometry& view, |
765 ImageInterpolation interpolation) const | |
686 { | 766 { |
687 Orthanc::ImageProcessing::Set(buffer, 0); | 767 Orthanc::ImageProcessing::Set(buffer, 0); |
688 | 768 |
689 // Render layers in the background-to-foreground order | 769 // Render layers in the background-to-foreground order |
690 for (size_t index = 0; index < countBitmaps_; index++) | 770 for (size_t index = 0; index < countBitmaps_; index++) |
691 { | 771 { |
692 Bitmaps::const_iterator it = bitmaps_.find(index); | 772 Bitmaps::const_iterator it = bitmaps_.find(index); |
693 if (it != bitmaps_.end()) | 773 if (it != bitmaps_.end()) |
694 { | 774 { |
695 assert(it->second != NULL); | 775 assert(it->second != NULL); |
696 it->second->Render(buffer, view); | 776 it->second->Render(buffer, view, interpolation); |
697 } | 777 } |
698 } | 778 } |
699 } | 779 } |
700 | 780 |
701 | 781 |
748 } | 828 } |
749 else | 829 else |
750 { | 830 { |
751 panX = 0; | 831 panX = 0; |
752 panY = 0; | 832 panY = 0; |
833 } | |
834 } | |
835 | |
836 | |
837 void DrawControls(CairoSurface& surface, | |
838 const ViewportGeometry& view) | |
839 { | |
840 if (hasSelection_) | |
841 { | |
842 Bitmaps::const_iterator bitmap = bitmaps_.find(selectedBitmap_); | |
843 | |
844 if (bitmap != bitmaps_.end()) | |
845 { | |
846 CairoContext context(surface); | |
847 | |
848 context.SetSourceColor(255, 0, 0); | |
849 view.ApplyTransform(context); | |
850 bitmap->second->DrawBorders(context, view.GetZoom()); | |
851 } | |
753 } | 852 } |
754 } | 853 } |
755 }; | 854 }; |
756 | 855 |
757 | 856 |
816 { | 915 { |
817 stack_.SetPan(bitmap_, dx + panX_, panY_); | 916 stack_.SetPan(bitmap_, dx + panX_, panY_); |
818 } | 917 } |
819 else | 918 else |
820 { | 919 { |
821 stack_.SetPan(bitmap_, panX_, dy + panY_); | 920 stack_.SetPan(bitmap_, panX_, dy + panY_); |
822 } | 921 } |
823 } | 922 } |
824 else | 923 else |
825 { | 924 { |
826 stack_.SetPan(bitmap_, dx + panX_, dy + panY_); | 925 stack_.SetPan(bitmap_, dx + panX_, dy + panY_); |
847 { | 946 { |
848 size_t bitmap; | 947 size_t bitmap; |
849 if (stack_.LookupBitmap(bitmap, x, y)) | 948 if (stack_.LookupBitmap(bitmap, x, y)) |
850 { | 949 { |
851 printf("CLICK on bitmap %ld\n", bitmap); | 950 printf("CLICK on bitmap %ld\n", bitmap); |
951 stack_.Select(bitmap); | |
852 return new MoveBitmapTracker(stack_, bitmap, x, y, | 952 return new MoveBitmapTracker(stack_, bitmap, x, y, |
853 (modifiers & KeyboardModifiers_Shift)); | 953 (modifiers & KeyboardModifiers_Shift)); |
854 } | 954 } |
855 else | 955 else |
856 { | 956 { |
857 printf("CLICK outside\n"); | 957 printf("CLICK outside\n"); |
958 stack_.Unselect(); | |
858 return NULL; | 959 return NULL; |
859 } | 960 } |
860 } | 961 } |
861 else | 962 else |
862 { | 963 { |
945 | 1046 |
946 virtual bool Render(Orthanc::ImageAccessor& target) | 1047 virtual bool Render(Orthanc::ImageAccessor& target) |
947 { | 1048 { |
948 Orthanc::Image buffer(Orthanc::PixelFormat_Float32, target.GetWidth(), | 1049 Orthanc::Image buffer(Orthanc::PixelFormat_Float32, target.GetWidth(), |
949 target.GetHeight(), false); | 1050 target.GetHeight(), false); |
950 stack_.Render(buffer, GetView()); | 1051 |
1052 // TODO => rendering quality | |
1053 //stack_.Render(buffer, GetView(), ImageInterpolation_Nearest); | |
1054 stack_.Render(buffer, GetView(), ImageInterpolation_Bilinear); | |
951 | 1055 |
952 // As in GrayscaleFrameRenderer => TODO MERGE? | 1056 // As in GrayscaleFrameRenderer => TODO MERGE? |
953 | 1057 |
954 float windowCenter, windowWidth; | 1058 float windowCenter, windowWidth; |
955 if (!stack_.GetWindowing(windowCenter, windowWidth)) | 1059 if (!stack_.GetWindowing(windowCenter, windowWidth)) |
1002 } | 1106 } |
1003 } | 1107 } |
1004 else | 1108 else |
1005 { | 1109 { |
1006 Orthanc::ImageProcessing::Set(target, 0, 0, 0, 255); | 1110 Orthanc::ImageProcessing::Set(target, 0, 0, 0, 255); |
1111 } | |
1112 | |
1113 { | |
1114 // TODO => REFACTOR | |
1115 CairoSurface surface(target); | |
1116 stack_.DrawControls(surface, GetView()); | |
1007 } | 1117 } |
1008 | 1118 |
1009 return true; | 1119 return true; |
1010 } | 1120 } |
1011 | 1121 |