comparison Applications/Samples/SingleFrameEditorApplication.h @ 359:100df90bf0ea am-2

preparing to implement Export
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 30 Oct 2018 08:11:06 +0100
parents b8eeb49f3e65
children 8262e4e9826d
comparison
equal deleted inserted replaced
358:b8eeb49f3e65 359:100df90bf0ea
21 21
22 #pragma once 22 #pragma once
23 23
24 #include "SampleApplicationBase.h" 24 #include "SampleApplicationBase.h"
25 25
26 #include "../../Framework/Toolbox/GeometryToolbox.h"
27 #include "../../Framework/Toolbox/ImageGeometry.h" 26 #include "../../Framework/Toolbox/ImageGeometry.h"
28 #include "../../Framework/Layers/OrthancFrameLayerSource.h" 27 #include "../../Framework/Toolbox/OrthancApiClient.h"
29 28 #include "../../Framework/Toolbox/DicomFrameConverter.h"
30 #include <Core/DicomFormat/DicomArray.h> 29
31 #include <Core/Images/FontRegistry.h> 30 #include <Core/Images/FontRegistry.h>
31 #include <Core/Images/Image.h>
32 #include <Core/Images/ImageProcessing.h> 32 #include <Core/Images/ImageProcessing.h>
33 #include <Core/Images/PamReader.h> 33 #include <Core/Images/PamReader.h>
34 #include <Core/Images/PngWriter.h> //TODO
35 #include <Core/Logging.h> 34 #include <Core/Logging.h>
35 #include <Plugins/Samples/Common/DicomDatasetReader.h>
36 #include <Plugins/Samples/Common/FullOrthancDataset.h> 36 #include <Plugins/Samples/Common/FullOrthancDataset.h>
37 #include <Plugins/Samples/Common/DicomDatasetReader.h>
38 37
39 38
40 #include <boost/math/constants/constants.hpp> 39 #include <boost/math/constants/constants.hpp>
41 40
42 namespace OrthancStone 41 namespace OrthancStone
2205 private: 2204 private:
2206 BitmapStack& stack_; 2205 BitmapStack& stack_;
2207 std::auto_ptr<Orthanc::Image> floatBuffer_; 2206 std::auto_ptr<Orthanc::Image> floatBuffer_;
2208 std::auto_ptr<CairoSurface> cairoBuffer_; 2207 std::auto_ptr<CairoSurface> cairoBuffer_;
2209 bool invert_; 2208 bool invert_;
2209 ImageInterpolation interpolation_;
2210 2210
2211 virtual bool RenderInternal(unsigned int width, 2211 virtual bool RenderInternal(unsigned int width,
2212 unsigned int height, 2212 unsigned int height,
2213 ImageInterpolation interpolation) 2213 ImageInterpolation interpolation)
2214 { 2214 {
2238 cairoBuffer_.reset(new CairoSurface(width, height)); 2238 cairoBuffer_.reset(new CairoSurface(width, height));
2239 } 2239 }
2240 2240
2241 stack_.Render(*floatBuffer_, GetView(), interpolation); 2241 stack_.Render(*floatBuffer_, GetView(), interpolation);
2242 2242
2243 // TODO => rendering quality 2243 // Very similar to GrayscaleFrameRenderer => TODO MERGE?
2244
2245 // As in GrayscaleFrameRenderer => TODO MERGE?
2246 2244
2247 Orthanc::ImageAccessor target; 2245 Orthanc::ImageAccessor target;
2248 cairoBuffer_->GetAccessor(target); 2246 cairoBuffer_->GetAccessor(target);
2249 2247
2250 for (unsigned int y = 0; y < height; y++) 2248 for (unsigned int y = 0; y < height; y++)
2267 { 2265 {
2268 // https://en.wikipedia.org/wiki/Linear_interpolation 2266 // https://en.wikipedia.org/wiki/Linear_interpolation
2269 v = static_cast<uint8_t>(255.0f * (*p - x0) / (x1 - x0)); // (*) 2267 v = static_cast<uint8_t>(255.0f * (*p - x0) / (x1 - x0)); // (*)
2270 } 2268 }
2271 2269
2272 // TODO MONOCHROME1
2273 if (invert_) 2270 if (invert_)
2274 { 2271 {
2275 v = 255 - v; 2272 v = 255 - v;
2276 } 2273 }
2277 2274
2294 } 2291 }
2295 2292
2296 virtual bool RenderScene(CairoContext& context, 2293 virtual bool RenderScene(CairoContext& context,
2297 const ViewportGeometry& view) 2294 const ViewportGeometry& view)
2298 { 2295 {
2299 ImageInterpolation interpolation = ImageInterpolation_Nearest; // TODO PARAMETER?
2300
2301 cairo_t* cr = context.GetObject(); 2296 cairo_t* cr = context.GetObject();
2302 2297
2303 if (RenderInternal(context.GetWidth(), context.GetHeight(), interpolation)) 2298 if (RenderInternal(context.GetWidth(), context.GetHeight(), interpolation_))
2304 { 2299 {
2305 // https://www.cairographics.org/FAQ/#paint_from_a_surface 2300 // https://www.cairographics.org/FAQ/#paint_from_a_surface
2306 cairo_save(cr); 2301 cairo_save(cr);
2307 cairo_identity_matrix(cr); 2302 cairo_identity_matrix(cr);
2308 cairo_set_source_surface(cr, cairoBuffer_->GetObject(), 0, 0); 2303 cairo_set_source_surface(cr, cairoBuffer_->GetObject(), 0, 0);
2327 const std::string& name) : 2322 const std::string& name) :
2328 WorldSceneWidget(name), 2323 WorldSceneWidget(name),
2329 IObservable(broker), 2324 IObservable(broker),
2330 IObserver(broker), 2325 IObserver(broker),
2331 stack_(stack), 2326 stack_(stack),
2332 invert_(false) 2327 invert_(false),
2328 interpolation_(ImageInterpolation_Nearest)
2333 { 2329 {
2334 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::GeometryChangedMessage>(*this, &BitmapStackWidget::OnGeometryChanged)); 2330 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::GeometryChangedMessage>(*this, &BitmapStackWidget::OnGeometryChanged));
2335 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::ContentChangedMessage>(*this, &BitmapStackWidget::OnContentChanged)); 2331 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::ContentChangedMessage>(*this, &BitmapStackWidget::OnContentChanged));
2336 } 2332 }
2337 2333
2352 NotifyContentChanged(); 2348 NotifyContentChanged();
2353 } 2349 }
2354 2350
2355 void SetInvert(bool invert) 2351 void SetInvert(bool invert)
2356 { 2352 {
2357 invert_ = invert; 2353 if (invert_ != invert)
2358 NotifyContentChanged(); 2354 {
2355 invert_ = invert;
2356 NotifyContentChanged();
2357 }
2359 } 2358 }
2360 2359
2361 void SwitchInvert() 2360 void SwitchInvert()
2362 { 2361 {
2363 invert_ = !invert_; 2362 invert_ = !invert_;
2365 } 2364 }
2366 2365
2367 bool IsInvert() const 2366 bool IsInvert() const
2368 { 2367 {
2369 return invert_; 2368 return invert_;
2369 }
2370
2371 void SetInterpolation(ImageInterpolation interpolation)
2372 {
2373 if (interpolation_ != interpolation)
2374 {
2375 interpolation_ = interpolation;
2376 NotifyContentChanged();
2377 }
2378 }
2379
2380 ImageInterpolation GetInterpolation() const
2381 {
2382 return interpolation_;
2370 } 2383 }
2371 }; 2384 };
2372 2385
2373 2386
2374 class BitmapStackInteractor : public IWorldSceneInteractor 2387 class BitmapStackInteractor : public IWorldSceneInteractor
2382 Tool_Resize, 2395 Tool_Resize,
2383 Tool_Windowing 2396 Tool_Windowing
2384 }; 2397 };
2385 2398
2386 2399
2387 UndoRedoStack undoRedoStack_; 2400 UndoRedoStack undoRedoStack_;
2388 Tool tool_; 2401 Tool tool_;
2402 OrthancApiClient *orthanc_;
2389 2403
2390 2404
2391 static double GetHandleSize() 2405 static double GetHandleSize()
2392 { 2406 {
2393 return 10.0; 2407 return 10.0;
2406 } 2420 }
2407 2421
2408 2422
2409 public: 2423 public:
2410 BitmapStackInteractor() : 2424 BitmapStackInteractor() :
2411 tool_(Tool_Move) 2425 tool_(Tool_Move),
2426 orthanc_(NULL)
2412 { 2427 {
2413 } 2428 }
2414 2429
2415 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, 2430 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget,
2416 const ViewportGeometry& view, 2431 const ViewportGeometry& view,
2580 2595
2581 case 'c': 2596 case 'c':
2582 tool_ = Tool_Crop; 2597 tool_ = Tool_Crop;
2583 break; 2598 break;
2584 2599
2600 case 'e':
2601 Export();
2602 break;
2603
2585 case 'i': 2604 case 'i':
2586 dynamic_cast<BitmapStackWidget&>(widget).SwitchInvert(); 2605 dynamic_cast<BitmapStackWidget&>(widget).SwitchInvert();
2587 break; 2606 break;
2588 2607
2589 case 'm': 2608 case 'm':
2590 tool_ = Tool_Move; 2609 tool_ = Tool_Move;
2591 break; 2610 break;
2592 2611
2612 case 'n':
2613 {
2614 BitmapStackWidget& w = dynamic_cast<BitmapStackWidget&>(widget);
2615
2616 switch (w.GetInterpolation())
2617 {
2618 case ImageInterpolation_Nearest:
2619 LOG(INFO) << "Switching to bilinear interpolation";
2620 w.SetInterpolation(ImageInterpolation_Bilinear);
2621 break;
2622
2623 case ImageInterpolation_Bilinear:
2624 LOG(INFO) << "Switching to nearest neighbor interpolation";
2625 w.SetInterpolation(ImageInterpolation_Nearest);
2626 break;
2627
2628 default:
2629 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
2630 }
2631
2632 break;
2633 }
2634
2593 case 'r': 2635 case 'r':
2594 tool_ = Tool_Rotate; 2636 tool_ = Tool_Rotate;
2595 break; 2637 break;
2596 2638
2597 case 's': 2639 case 's':
2619 break; 2661 break;
2620 2662
2621 default: 2663 default:
2622 break; 2664 break;
2623 } 2665 }
2666 }
2667
2668
2669 void SetOrthanc(OrthancApiClient& orthanc)
2670 {
2671 orthanc_ = &orthanc;
2672 }
2673
2674
2675 void Export()
2676 {
2677 if (orthanc_ == NULL)
2678 {
2679 return;
2680 }
2681
2682 // TODO
2683 LOG(WARNING) << "Exporting DICOM";
2624 } 2684 }
2625 }; 2685 };
2626 2686
2627 2687
2628 2688
2664 2724
2665 context_ = context; 2725 context_ = context;
2666 2726
2667 statusBar.SetMessage("Use the key \"a\" to reinitialize the layout"); 2727 statusBar.SetMessage("Use the key \"a\" to reinitialize the layout");
2668 statusBar.SetMessage("Use the key \"c\" to crop"); 2728 statusBar.SetMessage("Use the key \"c\" to crop");
2729 statusBar.SetMessage("Use the key \"e\" to export DICOM to the Orthanc server");
2669 statusBar.SetMessage("Use the key \"f\" to switch full screen"); 2730 statusBar.SetMessage("Use the key \"f\" to switch full screen");
2670 statusBar.SetMessage("Use the key \"i\" to invert contrast"); 2731 statusBar.SetMessage("Use the key \"i\" to invert contrast");
2671 statusBar.SetMessage("Use the key \"m\" to move objects"); 2732 statusBar.SetMessage("Use the key \"m\" to move objects");
2733 statusBar.SetMessage("Use the key \"n\" to switch between nearest neighbor and bilinear interpolation");
2672 statusBar.SetMessage("Use the key \"r\" to rotate objects"); 2734 statusBar.SetMessage("Use the key \"r\" to rotate objects");
2673 statusBar.SetMessage("Use the key \"s\" to resize objects (not applicable to DICOM bitmaps)"); 2735 statusBar.SetMessage("Use the key \"s\" to resize objects (not applicable to DICOM bitmaps)");
2674 statusBar.SetMessage("Use the key \"w\" to change windowing"); 2736 statusBar.SetMessage("Use the key \"w\" to change windowing");
2675 2737
2676 statusBar.SetMessage("Use the key \"ctrl-z\" to undo action"); 2738 statusBar.SetMessage("Use the key \"ctrl-z\" to undo action");
2684 2746
2685 std::string instance = parameters["instance"].as<std::string>(); 2747 std::string instance = parameters["instance"].as<std::string>();
2686 int frame = parameters["frame"].as<unsigned int>(); 2748 int frame = parameters["frame"].as<unsigned int>();
2687 2749
2688 orthancApiClient_.reset(new OrthancApiClient(IObserver::broker_, context_->GetWebService())); 2750 orthancApiClient_.reset(new OrthancApiClient(IObserver::broker_, context_->GetWebService()));
2751 interactor_.SetOrthanc(*orthancApiClient_);
2689 2752
2690 Orthanc::FontRegistry fonts; 2753 Orthanc::FontRegistry fonts;
2691 fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); 2754 fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16);
2692 2755
2693 stack_.reset(new BitmapStack(IObserver::broker_, *orthancApiClient_)); 2756 stack_.reset(new BitmapStack(IObserver::broker_, *orthancApiClient_));
2694 stack_->LoadFrame(instance, frame, false).SetPan(200, 0); 2757 stack_->LoadFrame(instance, frame, false).SetPan(200, 0);
2695 //stack_->LoadFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", 0, false); 2758 //stack_->LoadFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", 0, false);
2696 2759
2697 { 2760 {
2698 BitmapStack::Bitmap& bitmap = stack_->LoadText(fonts.GetFont(0), "Hello\nworld\nBonjour, Alain"); 2761 BitmapStack::Bitmap& bitmap = stack_->LoadText(fonts.GetFont(0), "Hello\nworld");
2699 //dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256); 2762 //dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256);
2700 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true); 2763 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true);
2701 } 2764 }
2702 2765
2703 { 2766 {
2712 mainWidget_->SetTransmitMouseOver(true); 2775 mainWidget_->SetTransmitMouseOver(true);
2713 mainWidget_->SetInteractor(interactor_); 2776 mainWidget_->SetInteractor(interactor_);
2714 2777
2715 //stack_->SetWindowing(128, 256); 2778 //stack_->SetWindowing(128, 256);
2716 } 2779 }
2717
2718
2719 void Invert()
2720 {
2721 // TODO
2722 }
2723
2724 void Rotate(int degrees)
2725 {
2726 // TODO
2727 }
2728
2729 void Export()
2730 {
2731 // TODO: export dicom file to a temporary file
2732 }
2733 }; 2780 };
2734
2735
2736 } 2781 }
2737 } 2782 }