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();
472 vtkCamera *cam = this->Renderer->GetActiveCamera();
476 this->ImageActor->GetBounds(bounds);
477 double spos = bounds[this->SliceOrientation * 2];
478 double cpos = cam->GetPosition()[this->SliceOrientation];
479 double range = fabs(spos - cpos);
480 double *spacing = input->GetSpacing();
482 //(spacing[0] + spacing[1] + spacing[2]) / 3.0;
484 cam->SetClippingRange(
485 range - avg_spacing * 3.0, range + avg_spacing * 3.0);
487 } // if InteractorStyle
491 //----------------------------------------------------------------------------
492 void wxvtkImageViewer2::SetPosition(int a,int b)
494 this->RenderWindow->SetPosition(a, b);
497 //----------------------------------------------------------------------------
498 int* wxvtkImageViewer2::GetPosition()
500 return this->RenderWindow->GetPosition();
503 //----------------------------------------------------------------------------
504 void wxvtkImageViewer2::SetDisplayId(void *a)
506 this->RenderWindow->SetDisplayId(a);
509 //----------------------------------------------------------------------------
510 void wxvtkImageViewer2::SetWindowId(void *a)
512 this->RenderWindow->SetWindowId(a);
515 //----------------------------------------------------------------------------
516 void wxvtkImageViewer2::SetParentId(void *a)
518 this->RenderWindow->SetParentId(a);
521 //----------------------------------------------------------------------------
522 double wxvtkImageViewer2::GetColorWindow()
524 return this->WindowLevel->GetWindow();
527 //----------------------------------------------------------------------------
528 double wxvtkImageViewer2::GetColorLevel()
530 return this->WindowLevel->GetLevel();
533 //----------------------------------------------------------------------------
534 void wxvtkImageViewer2::SetColorWindow(double s)
536 this->WindowLevel->SetWindow(s);
539 //----------------------------------------------------------------------------
540 void wxvtkImageViewer2::SetColorLevel(double s)
542 this->WindowLevel->SetLevel(s);
545 //----------------------------------------------------------------------------
546 class wxvtkImageViewer2Callback : public vtkCommand
549 static wxvtkImageViewer2Callback *New() { return new wxvtkImageViewer2Callback; }
551 void Execute(vtkObject *caller,
553 void *vtkNotUsed(callData))
555 if (this->IV->GetInput() == NULL)
562 if (event == vtkCommand::ResetWindowLevelEvent)
565 //EED 2017-01-01 Migration VTK7
566 #if VTK_MAJOR_VERSION <= 5
567 this->IV->GetInput()->UpdateInformation();
568 this->IV->GetInput()->SetUpdateExtent
569 (this->IV->GetInput()->GetWholeExtent());
570 this->IV->GetInput()->Update();
575 double *range = this->IV->GetInput()->GetScalarRange();
576 this->IV->SetColorWindow(range[1] - range[0]);
577 this->IV->SetColorLevel(0.5 * (range[1] + range[0]));
584 if (event == vtkCommand::StartWindowLevelEvent)
586 this->InitialWindow = this->IV->GetColorWindow();
587 this->InitialLevel = this->IV->GetColorLevel();
591 // Adjust the window level here
593 vtkInteractorStyleImage *isi =
594 static_cast<vtkInteractorStyleImage *>(caller);
596 int *size = this->IV->GetRenderWindow()->GetSize();
597 double window = this->InitialWindow;
598 double level = this->InitialLevel;
600 // Compute normalized delta
603 (isi->GetWindowLevelCurrentPosition()[0] -
604 isi->GetWindowLevelStartPosition()[0]) / size[0];
606 (isi->GetWindowLevelStartPosition()[1] -
607 isi->GetWindowLevelCurrentPosition()[1]) / size[1];
609 // Scale by current values
611 if (fabs(window) > 0.01)
617 dx = dx * (window < 0 ? -0.01 : 0.01);
619 if (fabs(level) > 0.01)
625 dy = dy * (level < 0 ? -0.01 : 0.01);
628 // Abs so that direction does not flip
639 // Compute new window level
641 double newWindow = dx + window;
643 newLevel = level - dy;
645 // Stay away from zero and really
647 if (fabs(newWindow) < 0.01)
649 newWindow = 0.01*(newWindow < 0 ? -1 : 1);
651 if (fabs(newLevel) < 0.01)
653 newLevel = 0.01*(newLevel < 0 ? -1 : 1);
656 this->IV->SetColorWindow(newWindow);
657 this->IV->SetColorLevel(newLevel);
661 wxvtkImageViewer2 *IV;
662 double InitialWindow;
666 //----------------------------------------------------------------------------
667 void wxvtkImageViewer2::InstallPipeline()
669 if (this->RenderWindow && this->Renderer)
671 this->RenderWindow->AddRenderer(this->Renderer);
674 if (this->Interactor)
676 if (!this->InteractorStyle)
678 this->InteractorStyle = vtkInteractorStyleImage::New();
679 wxvtkImageViewer2Callback *cbk = wxvtkImageViewer2Callback::New();
681 this->InteractorStyle->AddObserver(
682 vtkCommand::WindowLevelEvent, cbk);
683 this->InteractorStyle->AddObserver(
684 vtkCommand::StartWindowLevelEvent, cbk);
685 this->InteractorStyle->AddObserver(
686 vtkCommand::ResetWindowLevelEvent, cbk);
690 this->Interactor->SetInteractorStyle(this->InteractorStyle);
691 this->Interactor->SetRenderWindow(this->RenderWindow);
694 if (this->Renderer && this->ImageActor)
696 this->Renderer->AddViewProp(this->ImageActor);
699 if (this->ImageActor && this->WindowLevel)
701 //EED 2017-01-01 Migration VTK7
702 #if VTK_MAJOR_VERSION <= 5
703 this->ImageActor->SetInput(this->WindowLevel->GetOutput());
705 this->WindowLevel->Update();
706 this->ImageActor->SetInputData(this->WindowLevel->GetOutput());
711 //----------------------------------------------------------------------------
712 void wxvtkImageViewer2::UnInstallPipeline()
714 if (this->ImageActor)
716 //EED 2017-01-01 Migration VTK7
717 #if VTK_MAJOR_VERSION <= 5
718 this->ImageActor->SetInput(NULL);
720 this->ImageActor->SetInputData(NULL);
724 if (this->Renderer && this->ImageActor)
726 this->Renderer->RemoveViewProp(this->ImageActor);
729 if (this->RenderWindow && this->Renderer)
731 this->RenderWindow->RemoveRenderer(this->Renderer);
734 if (this->Interactor)
736 this->Interactor->SetInteractorStyle(NULL);
737 this->Interactor->SetRenderWindow(NULL);
741 //----------------------------------------------------------------------------
742 void wxvtkImageViewer2::Render()
744 if (this->FirstRender)
746 // Initialize the size if not set yet
748 vtkImageData *input = this->GetInput();
749 if (this->RenderWindow->GetSize()[0] == 0 &&
754 //EED 2017-01-01 Migration VTK7
755 #if VTK_MAJOR_VERSION <= 5
756 input->UpdateInformation();
757 int *w_ext = input->GetWholeExtent();
759 int *w_ext = input->GetExtent();
764 // std::cout << "wxvtkImageViewer2::Render ext = "
765 // <<w_ext[0]<<" - "<<w_ext[1]<<" ; "
766 // <<w_ext[2]<<" - "<<w_ext[3]<<" ; "
767 // <<w_ext[4]<<" - "<<w_ext[5]
770 switch (this->SliceOrientation)
772 case wxvtkImageViewer2::SLICE_ORIENTATION_XY:
774 xs = w_ext[1] - w_ext[0] + 1;
775 ys = w_ext[3] - w_ext[2] + 1;
776 // std::cout << "SLICE_ORIENTATION_XY" << std::endl;
779 case wxvtkImageViewer2::SLICE_ORIENTATION_XZ:
780 xs = w_ext[1] - w_ext[0] + 1;
781 ys = w_ext[5] - w_ext[4] + 1;
782 // std::cout << "SLICE_ORIENTATION_XZ" << std::endl;
785 case wxvtkImageViewer2::SLICE_ORIENTATION_YZ:
786 xs = w_ext[3] - w_ext[2] + 1;
787 ys = w_ext[5] - w_ext[4] + 1;
788 // std::cout << "SLICE_ORIENTATION_YZ" << std::endl;
792 // if it would be smaller than 150 by 100 then limit to 150 by 100
793 this->RenderWindow->SetSize(
794 xs < 150 ? 150 : xs, ys < 100 ? 100 : ys);
796 // std::cout << "wxvtkImageViewer2::Render() : "<<xs<<"-"<<ys<<std::endl;
799 this->Renderer->ResetCamera();
800 this->Renderer->GetActiveCamera()->SetParallelScale(
801 xs < 150 ? 75 : (xs - 1 ) / 2.0);
803 this->FirstRender = 0;
807 if (this->GetInput())
809 this->RenderWindow->Render();
813 //----------------------------------------------------------------------------
814 const char* wxvtkImageViewer2::GetWindowName()
816 return this->RenderWindow->GetWindowName();
819 //----------------------------------------------------------------------------
820 void wxvtkImageViewer2::SetOffScreenRendering(int i)
822 this->RenderWindow->SetOffScreenRendering(i);
825 //----------------------------------------------------------------------------
826 int wxvtkImageViewer2::GetOffScreenRendering()
828 return this->RenderWindow->GetOffScreenRendering();
831 //----------------------------------------------------------------------------
832 void wxvtkImageViewer2::SetInput(vtkImageData *in)
834 // std::cout << "### wxvtkImageViewer2::SetInput"<<std::endl;
835 //EED 2017-01-01 Migration VTK7
836 #if VTK_MAJOR_VERSION <= 5
837 this->WindowLevel->SetInput(in);
839 this->WindowLevel->SetInputData(in);
842 this->UpdateDisplayExtent();
846 //----------------------------------------------------------------------------
847 vtkImageData* wxvtkImageViewer2::GetInput()
849 return vtkImageData::SafeDownCast(this->WindowLevel->GetInput());
852 //----------------------------------------------------------------------------
853 void wxvtkImageViewer2::SetInputConnection(vtkAlgorithmOutput* input)
855 this->WindowLevel->SetInputConnection(input);
856 this->UpdateDisplayExtent();
859 //----------------------------------------------------------------------------
860 #ifndef VTK_LEGACY_REMOVE
861 int wxvtkImageViewer2::GetWholeZMin()
863 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMin, "VTK 5.0",
864 wxvtkImageViewer2::GetSliceMin);
865 return this->GetSliceMin();
867 int wxvtkImageViewer2::GetWholeZMax()
869 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetWholeZMax, "VTK 5.0",
870 wxvtkImageViewer2::GetSliceMax);
871 return this->GetSliceMax();
873 int wxvtkImageViewer2::GetZSlice()
875 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::GetZSlice, "VTK 5.0",
876 wxvtkImageViewer2::GetSlice);
877 return this->GetSlice();
879 void wxvtkImageViewer2::SetZSlice(int s)
881 VTK_LEGACY_REPLACED_BODY(wxvtkImageViewer2::SetZSlice, "VTK 5.0",
882 wxvtkImageViewer2::SetSlice);
887 //----------------------------------------------------------------------------
888 void wxvtkImageViewer2::PrintSelf(ostream& os, vtkIndent indent)
890 this->Superclass::PrintSelf(os, indent);
892 os << indent << "RenderWindow:\n";
893 this->RenderWindow->PrintSelf(os,indent.GetNextIndent());
894 os << indent << "Renderer:\n";
895 this->Renderer->PrintSelf(os,indent.GetNextIndent());
896 os << indent << "ImageActor:\n";
897 this->ImageActor->PrintSelf(os,indent.GetNextIndent());
898 os << indent << "WindowLevel:\n" << endl;
899 this->WindowLevel->PrintSelf(os,indent.GetNextIndent());
900 os << indent << "Slice: " << this->Slice << endl;
901 os << indent << "SliceOrientation: " << this->SliceOrientation << endl;
902 os << indent << "InteractorStyle: " << endl;
903 if (this->InteractorStyle)
906 this->InteractorStyle->PrintSelf(os,indent.GetNextIndent());