2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
10 # This software is governed by the CeCILL-B license under French law and
11 # abiding by the rules of distribution of free software. You can use,
12 # modify and/ or redistribute the software under the terms of the CeCILL-B
13 # license as circulated by CEA, CNRS and INRIA at the following URL
14 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 # or in the file LICENSE.txt.
17 # As a counterpart to the access to the source code and rights to copy,
18 # modify and redistribute granted by the license, users are provided only
19 # with a limited warranty and the software's author, the holder of the
20 # economic rights, and the successive licensors have only limited
23 # The fact that you are presently reading this means that you have had
24 # knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------ */
28 /*=========================================================================
30 Program: Visualization Toolkit
31 Module: $RCSfile: wxvtkImageViewer2.cxx,v $
33 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
35 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
37 This software is distributed WITHOUT ANY WARRANTY; without even
38 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
39 PURPOSE. See the above copyright notice for more information.
41 =========================================================================*/
42 #include "wxvtkImageViewer2.h"
44 #include "vtkCamera.h"
45 #include "vtkCommand.h"
46 #include "vtkImageActor.h"
47 #include "vtkImageData.h"
48 #include "vtkImageData.h"
49 #include "vtkImageMapToWindowLevelColors.h"
50 #include "vtkInteractorStyleImage.h"
51 #include "vtkObjectFactory.h"
52 #include "vtkRenderWindow.h"
53 #include "vtkRenderWindowInteractor.h"
54 #include "vtkRenderer.h"
56 //EED 2017-01-01 Migration VTK7
57 #if VTK_MAJOR_VERSION <= 5
58 vtkCxxRevisionMacro(wxvtkImageViewer2, "$Revision: 1.8 $");
63 vtkStandardNewMacro(wxvtkImageViewer2);
65 //----------------------------------------------------------------------------
66 wxvtkImageViewer2::wxvtkImageViewer2()
68 this->RenderWindow = NULL;
69 this->Renderer = NULL;
70 this->ImageActor = vtkImageActor::New();
71 this->WindowLevel = vtkImageMapToWindowLevelColors::New();
72 this->Interactor = NULL;
73 this->InteractorStyle = NULL;
76 this->FirstRender = 1;
77 this->SliceOrientation = wxvtkImageViewer2::SLICE_ORIENTATION_XY;
81 vtkRenderWindow *renwin = vtkRenderWindow::New();
82 this->SetRenderWindow(renwin);
85 vtkRenderer *ren = vtkRenderer::New();
86 this->SetRenderer(ren);
89 this->InstallPipeline();
92 //----------------------------------------------------------------------------
93 wxvtkImageViewer2::~wxvtkImageViewer2()
95 if (this->WindowLevel)
97 this->WindowLevel->Delete();
98 this->WindowLevel = NULL;
101 if (this->ImageActor)
103 this->ImageActor->Delete();
104 this->ImageActor = NULL;
109 this->Renderer->Delete();
110 this->Renderer = NULL;
113 if (this->RenderWindow)
115 this->RenderWindow->Delete();
116 this->RenderWindow = NULL;
119 if (this->Interactor)
121 this->Interactor->Delete();
122 this->Interactor = NULL;
125 if (this->InteractorStyle)
127 this->InteractorStyle->Delete();
128 this->InteractorStyle = NULL;
132 //----------------------------------------------------------------------------
133 void wxvtkImageViewer2::SetupInteractor(vtkRenderWindowInteractor *arg)
135 if (this->Interactor == arg)
140 this->UnInstallPipeline();
142 if (this->Interactor)
144 this->Interactor->UnRegister(this);
147 this->Interactor = arg;
149 if (this->Interactor)
151 this->Interactor->Register(this);
154 this->InstallPipeline();
158 this->Renderer->GetActiveCamera()->ParallelProjectionOn();
162 //----------------------------------------------------------------------------
163 void wxvtkImageViewer2::SetRenderWindow(vtkRenderWindow *arg)
165 if (this->RenderWindow == arg)
170 this->UnInstallPipeline();
172 if (this->RenderWindow)
174 this->RenderWindow->UnRegister(this);
177 this->RenderWindow = arg;
179 if (this->RenderWindow)
181 this->RenderWindow->Register(this);
184 this->InstallPipeline();
187 //----------------------------------------------------------------------------
188 void wxvtkImageViewer2::SetRenderer(vtkRenderer *arg)
190 if (this->Renderer == arg)
195 this->UnInstallPipeline();
199 this->Renderer->UnRegister(this);
202 this->Renderer = arg;
206 this->Renderer->Register(this);
209 this->InstallPipeline();
210 this->UpdateOrientation();
213 //----------------------------------------------------------------------------
214 void wxvtkImageViewer2::SetSize(int a,int b)
216 this->RenderWindow->SetSize(a, b);
219 //----------------------------------------------------------------------------
220 int* wxvtkImageViewer2::GetSize()
222 return this->RenderWindow->GetSize();
225 //----------------------------------------------------------------------------
226 void wxvtkImageViewer2::GetSliceRange(int &min, int &max)
228 vtkImageData *input = this->GetInput();
232 //EED 2017-01-01 Migration VTK7
233 #if VTK_MAJOR_VERSION <= 5
234 input->UpdateInformation();
235 int *w_ext = input->GetWholeExtent();
237 int *w_ext = input->GetExtent();
240 min = w_ext[this->SliceOrientation * 2];
241 max = w_ext[this->SliceOrientation * 2 + 1];
245 //----------------------------------------------------------------------------
246 int* wxvtkImageViewer2::GetSliceRange()
248 vtkImageData *input = this->GetInput();
251 //EED 2017-01-01 Migration VTK7
252 #if VTK_MAJOR_VERSION <= 5
253 input->UpdateInformation();
254 printf("EED Warning wxvtkImageViewer2::GetSliceRange GetWholeExtent()[2] ??? /n");
255 return input->GetWholeExtent() + this->SliceOrientation * 2;
257 printf("EED Warning wxvtkImageViewer2::GetSliceRange GetExtent()[2] ??? /n");
258 return input->GetExtent() + this->SliceOrientation * 2;
264 //----------------------------------------------------------------------------
265 int wxvtkImageViewer2::GetSliceMin()
267 int *range = this->GetSliceRange();
275 //----------------------------------------------------------------------------
276 int wxvtkImageViewer2::GetSliceMax()
278 int *range = this->GetSliceRange();
286 //----------------------------------------------------------------------------
287 void wxvtkImageViewer2::SetSlice(int slice)
289 int *range = this->GetSliceRange();
292 if (slice < range[0])
296 else if (slice > range[1])
302 if (this->Slice == slice)
310 this->UpdateDisplayExtent();
314 //----------------------------------------------------------------------------
315 void wxvtkImageViewer2::SetSliceOrientation(int orientation)
317 if (orientation < wxvtkImageViewer2::SLICE_ORIENTATION_YZ ||
318 orientation > wxvtkImageViewer2::SLICE_ORIENTATION_XY)
320 vtkErrorMacro("Error - invalid slice orientation " << orientation);
324 if (this->SliceOrientation == orientation)
329 this->SliceOrientation = orientation;
333 int *range = this->GetSliceRange();
336 this->Slice = static_cast<int>((range[0] + range[1]) * 0.5);
339 this->UpdateOrientation();
340 this->UpdateDisplayExtent();
342 if (this->Renderer && this->GetInput())
344 double scale = this->Renderer->GetActiveCamera()->GetParallelScale();
345 this->Renderer->ResetCamera();
346 this->Renderer->GetActiveCamera()->SetParallelScale(scale);
352 //----------------------------------------------------------------------------
353 void wxvtkImageViewer2::UpdateOrientation()
355 // Set the camera position
357 vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
361 // EED 21 mars FLIP problem ..PLOP..
362 switch (this->SliceOrientation)
364 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
365 cam->SetViewUp(0,0,1);
366 cam->SetPosition(1,0,0); // -1 if medical ?
367 cam->SetFocalPoint(0,0,0);
370 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
371 cam->SetViewUp(0,0,1);
372 cam->SetPosition(0,-1,0); // 1 if medical ?
373 cam->SetFocalPoint(0,0,0);
376 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
377 cam->SetViewUp(0,-1,0);
378 cam->SetPosition(0,0,-1);
379 cam->SetFocalPoint(0,0,0);
384 switch (this->SliceOrientation)
386 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
387 cam->SetViewUp(0,0,1);
388 cam->SetPosition(1,0,0); // -1 if medical ?
389 cam->SetFocalPoint(0,0,0);
392 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
393 cam->SetViewUp(0,0,1);
394 cam->SetPosition(0,-1,0); // 1 if medical ?
395 cam->SetFocalPoint(0,0,0);
398 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
399 cam->SetViewUp(0,1,0);
400 cam->SetPosition(0,0,1); // -1 if medical ?
401 cam->SetFocalPoint(0,0,0);
411 //----------------------------------------------------------------------------
412 void wxvtkImageViewer2::UpdateDisplayExtent()
414 vtkImageData *input = this->GetInput();
415 if (!input || !this->ImageActor)
420 // std::cout << "--- wxvtkImageViewer2::UpdateDisplayExtent()"<<std::endl;
421 //EED 2017-01-01 Migration VTK7
422 #if VTK_MAJOR_VERSION <= 5
423 input->UpdateInformation();
424 int *w_ext = input->GetWholeExtent();
426 int *w_ext = input->GetExtent();
429 // std::cout << "ext = "
430 // <<w_ext[0]<<" - "<<w_ext[1]<<" ; "
431 // <<w_ext[2]<<" - "<<w_ext[3]<<" ; "
432 // <<w_ext[4]<<" - "<<w_ext[5]
434 // Is the slice in range ? If not, fix it
436 int slice_min = w_ext[this->SliceOrientation * 2];
437 int slice_max = w_ext[this->SliceOrientation * 2 + 1];
438 if (this->Slice < slice_min || this->Slice > slice_max)
440 this->Slice = static_cast<int>((slice_min + slice_max) * 0.5);
443 // Set the image actor
445 switch (this->SliceOrientation)
447 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
448 this->ImageActor->SetDisplayExtent(
449 w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice);
452 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
453 this->ImageActor->SetDisplayExtent(
454 w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5]);
457 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
458 this->ImageActor->SetDisplayExtent(
459 this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5]);
463 // Figure out the correct clipping range
467 if (this->InteractorStyle &&
468 this->InteractorStyle->GetAutoAdjustCameraClippingRange())
470 this->Renderer->ResetCameraClippingRange();
474 vtkCamera *cam = this->Renderer->GetActiveCamera();
478 this->ImageActor->GetBounds(bounds);
479 double spos = bounds[this->SliceOrientation * 2];
480 double cpos = cam->GetPosition()[this->SliceOrientation];
481 double range = fabs(spos - cpos);
482 double *spacing = input->GetSpacing();
484 //(spacing[0] + spacing[1] + spacing[2]) / 3.0;
486 cam->SetClippingRange(
487 range - avg_spacing * 3.0, range + avg_spacing * 3.0);
493 //----------------------------------------------------------------------------
494 void wxvtkImageViewer2::SetPosition(int a,int b)
496 this->RenderWindow->SetPosition(a, b);
499 //----------------------------------------------------------------------------
500 int* wxvtkImageViewer2::GetPosition()
502 return this->RenderWindow->GetPosition();
505 //----------------------------------------------------------------------------
506 void wxvtkImageViewer2::SetDisplayId(void *a)
508 this->RenderWindow->SetDisplayId(a);
511 //----------------------------------------------------------------------------
512 void wxvtkImageViewer2::SetWindowId(void *a)
514 this->RenderWindow->SetWindowId(a);
517 //----------------------------------------------------------------------------
518 void wxvtkImageViewer2::SetParentId(void *a)
520 this->RenderWindow->SetParentId(a);
523 //----------------------------------------------------------------------------
524 double wxvtkImageViewer2::GetColorWindow()
526 return this->WindowLevel->GetWindow();
529 //----------------------------------------------------------------------------
530 double wxvtkImageViewer2::GetColorLevel()
532 return this->WindowLevel->GetLevel();
535 //----------------------------------------------------------------------------
536 void wxvtkImageViewer2::SetColorWindow(double s)
538 this->WindowLevel->SetWindow(s);
541 //----------------------------------------------------------------------------
542 void wxvtkImageViewer2::SetColorLevel(double s)
544 this->WindowLevel->SetLevel(s);
547 //----------------------------------------------------------------------------
548 class wxvtkImageViewer2Callback : public vtkCommand
551 static wxvtkImageViewer2Callback *New() { return new wxvtkImageViewer2Callback; }
553 void Execute(vtkObject *caller,
555 void *vtkNotUsed(callData))
557 if (this->IV->GetInput() == NULL)
564 if (event == vtkCommand::ResetWindowLevelEvent)
567 //EED 2017-01-01 Migration VTK7
568 #if VTK_MAJOR_VERSION <= 5
569 this->IV->GetInput()->UpdateInformation();
570 this->IV->GetInput()->SetUpdateExtent
571 (this->IV->GetInput()->GetWholeExtent());
572 this->IV->GetInput()->Update();
577 double *range = this->IV->GetInput()->GetScalarRange();
578 this->IV->SetColorWindow(range[1] - range[0]);
579 this->IV->SetColorLevel(0.5 * (range[1] + range[0]));
586 if (event == vtkCommand::StartWindowLevelEvent)
588 this->InitialWindow = this->IV->GetColorWindow();
589 this->InitialLevel = this->IV->GetColorLevel();
593 // Adjust the window level here
595 vtkInteractorStyleImage *isi =
596 static_cast<vtkInteractorStyleImage *>(caller);
598 int *size = this->IV->GetRenderWindow()->GetSize();
599 double window = this->InitialWindow;
600 double level = this->InitialLevel;
602 // Compute normalized delta
605 (isi->GetWindowLevelCurrentPosition()[0] -
606 isi->GetWindowLevelStartPosition()[0]) / size[0];
608 (isi->GetWindowLevelStartPosition()[1] -
609 isi->GetWindowLevelCurrentPosition()[1]) / size[1];
611 // Scale by current values
613 if (fabs(window) > 0.01)
619 dx = dx * (window < 0 ? -0.01 : 0.01);
621 if (fabs(level) > 0.01)
627 dy = dy * (level < 0 ? -0.01 : 0.01);
630 // Abs so that direction does not flip
641 // Compute new window level
643 double newWindow = dx + window;
645 newLevel = level - dy;
647 // Stay away from zero and really
649 if (fabs(newWindow) < 0.01)
651 newWindow = 0.01*(newWindow < 0 ? -1 : 1);
653 if (fabs(newLevel) < 0.01)
655 newLevel = 0.01*(newLevel < 0 ? -1 : 1);
658 this->IV->SetColorWindow(newWindow);
659 this->IV->SetColorLevel(newLevel);
663 wxvtkImageViewer2 *IV;
664 double InitialWindow;
668 //----------------------------------------------------------------------------
669 void wxvtkImageViewer2::InstallPipeline()
671 if (this->RenderWindow && this->Renderer)
673 this->RenderWindow->AddRenderer(this->Renderer);
676 if (this->Interactor)
678 if (!this->InteractorStyle)
680 this->InteractorStyle = vtkInteractorStyleImage::New();
681 wxvtkImageViewer2Callback *cbk = wxvtkImageViewer2Callback::New();
683 this->InteractorStyle->AddObserver(
684 vtkCommand::WindowLevelEvent, cbk);
685 this->InteractorStyle->AddObserver(
686 vtkCommand::StartWindowLevelEvent, cbk);
687 this->InteractorStyle->AddObserver(
688 vtkCommand::ResetWindowLevelEvent, cbk);
692 this->Interactor->SetInteractorStyle(this->InteractorStyle);
693 this->Interactor->SetRenderWindow(this->RenderWindow);
696 if (this->Renderer && this->ImageActor)
698 this->Renderer->AddViewProp(this->ImageActor);
701 if (this->ImageActor && this->WindowLevel)
703 //EED 2017-01-01 Migration VTK7
704 #if VTK_MAJOR_VERSION <= 5
705 this->ImageActor->SetInput(this->WindowLevel->GetOutput());
707 this->ImageActor->SetInputData(this->WindowLevel->GetOutput());
712 //----------------------------------------------------------------------------
713 void wxvtkImageViewer2::UnInstallPipeline()
715 if (this->ImageActor)
717 //EED 2017-01-01 Migration VTK7
718 #if VTK_MAJOR_VERSION <= 5
719 this->ImageActor->SetInput(NULL);
721 this->ImageActor->SetInputData(NULL);
725 if (this->Renderer && this->ImageActor)
727 this->Renderer->RemoveViewProp(this->ImageActor);
730 if (this->RenderWindow && this->Renderer)
732 this->RenderWindow->RemoveRenderer(this->Renderer);
735 if (this->Interactor)
737 this->Interactor->SetInteractorStyle(NULL);
738 this->Interactor->SetRenderWindow(NULL);
742 //----------------------------------------------------------------------------
743 void wxvtkImageViewer2::Render()
745 if (this->FirstRender)
747 // Initialize the size if not set yet
749 vtkImageData *input = this->GetInput();
750 if (this->RenderWindow->GetSize()[0] == 0 &&
755 //EED 2017-01-01 Migration VTK7
756 #if VTK_MAJOR_VERSION <= 5
757 input->UpdateInformation();
758 int *w_ext = input->GetWholeExtent();
760 int *w_ext = input->GetExtent();
765 // std::cout << "wxvtkImageViewer2::Render ext = "
766 // <<w_ext[0]<<" - "<<w_ext[1]<<" ; "
767 // <<w_ext[2]<<" - "<<w_ext[3]<<" ; "
768 // <<w_ext[4]<<" - "<<w_ext[5]
771 switch (this->SliceOrientation)
773 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
775 xs = w_ext[1] - w_ext[0] + 1;
776 ys = w_ext[3] - w_ext[2] + 1;
777 // std::cout << "SLICE_ORIENTATION_XY" << std::endl;
780 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
781 xs = w_ext[1] - w_ext[0] + 1;
782 ys = w_ext[5] - w_ext[4] + 1;
783 // std::cout << "SLICE_ORIENTATION_XZ" << std::endl;
786 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
787 xs = w_ext[3] - w_ext[2] + 1;
788 ys = w_ext[5] - w_ext[4] + 1;
789 // std::cout << "SLICE_ORIENTATION_YZ" << std::endl;
793 // if it would be smaller than 150 by 100 then limit to 150 by 100
794 this->RenderWindow->SetSize(
795 xs < 150 ? 150 : xs, ys < 100 ? 100 : ys);
797 // std::cout << "wxvtkImageViewer2::Render() : "<<xs<<"-"<<ys<<std::endl;
800 this->Renderer->ResetCamera();
801 this->Renderer->GetActiveCamera()->SetParallelScale(
802 xs < 150 ? 75 : (xs - 1 ) / 2.0);
804 this->FirstRender = 0;
808 if (this->GetInput())
810 this->RenderWindow->Render();
814 //----------------------------------------------------------------------------
815 const char* wxvtkImageViewer2::GetWindowName()
817 return this->RenderWindow->GetWindowName();
820 //----------------------------------------------------------------------------
821 void wxvtkImageViewer2::SetOffScreenRendering(int i)
823 this->RenderWindow->SetOffScreenRendering(i);
826 //----------------------------------------------------------------------------
827 int wxvtkImageViewer2::GetOffScreenRendering()
829 return this->RenderWindow->GetOffScreenRendering();
832 //----------------------------------------------------------------------------
833 void wxvtkImageViewer2::SetInput(vtkImageData *in)
835 // std::cout << "### wxvtkImageViewer2::SetInput"<<std::endl;
836 //EED 2017-01-01 Migration VTK7
837 #if VTK_MAJOR_VERSION <= 5
838 this->WindowLevel->SetInput(in);
840 this->WindowLevel->SetInputData(in);
843 this->UpdateDisplayExtent();
847 //----------------------------------------------------------------------------
848 vtkImageData* wxvtkImageViewer2::GetInput()
850 return vtkImageData::SafeDownCast(this->WindowLevel->GetInput());
853 //----------------------------------------------------------------------------
854 void wxvtkImageViewer2::SetInputConnection(vtkAlgorithmOutput* input)
856 this->WindowLevel->SetInputConnection(input);
857 this->UpdateDisplayExtent();
860 //----------------------------------------------------------------------------
861 #ifndef VTK_LEGACY_REMOVE
862 int wxvtkImageViewer2::GetWholeZMin()
864 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMin, "VTK 5.0",
865 wxvtkImageViewer2::GetSliceMin);
866 return this->GetSliceMin();
868 int wxvtkImageViewer2::GetWholeZMax()
870 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMax, "VTK 5.0",
871 wxvtkImageViewer2::GetSliceMax);
872 return this->GetSliceMax();
874 int wxvtkImageViewer2::GetZSlice()
876 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetZSlice, "VTK 5.0",
877 wxvtkImageViewer2::GetSlice);
878 return this->GetSlice();
880 void wxvtkImageViewer2::SetZSlice(int s)
882 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::SetZSlice, "VTK 5.0",
883 wxvtkImageViewer2::SetSlice);
888 //----------------------------------------------------------------------------
889 void wxvtkImageViewer2::PrintSelf(ostream& os, vtkIndent indent)
891 this->Superclass::PrintSelf(os, indent);
893 os << indent << "RenderWindow:\n";
894 this->RenderWindow->PrintSelf(os,indent.GetNextIndent());
895 os << indent << "Renderer:\n";
896 this->Renderer->PrintSelf(os,indent.GetNextIndent());
897 os << indent << "ImageActor:\n";
898 this->ImageActor->PrintSelf(os,indent.GetNextIndent());
899 os << indent << "WindowLevel:\n" << endl;
900 this->WindowLevel->PrintSelf(os,indent.GetNextIndent());
901 os << indent << "Slice: " << this->Slice << endl;
902 os << indent << "SliceOrientation: " << this->SliceOrientation << endl;
903 os << indent << "InteractorStyle: " << endl;
904 if (this->InteractorStyle)
907 this->InteractorStyle->PrintSelf(os,indent.GetNextIndent());