1 /*=========================================================================
3 Program: Visualization Toolkit
4 Module: $RCSfile: vtkImageColorViewer.cxx,v $
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
14 =========================================================================*/
15 #include "vtkImageColorViewer.h"
17 #include "vtkCamera.h"
18 #include "vtkCommand.h"
19 #include "vtkImageActor.h"
20 #include "vtkImageData.h"
21 #include "vtkImageData.h"
22 #include "vtkImageMapToWindowLevelColors2.h"
23 #include "vtkInteractorStyleImage.h"
24 #include "vtkObjectFactory.h"
25 #include "vtkRenderWindow.h"
26 #include "vtkRenderWindowInteractor.h"
27 #include "vtkRenderer.h"
29 vtkCxxRevisionMacro(vtkImageColorViewer, "$Revision: 1.3 $")
30 vtkStandardNewMacro(vtkImageColorViewer)
32 //----------------------------------------------------------------------------
33 vtkImageColorViewer::vtkImageColorViewer()
35 this->RenderWindow = NULL;
36 this->Renderer = NULL;
37 this->ImageActor = vtkImageActor::New();
38 this->WindowLevel = vtkImageMapToWindowLevelColors2::New();
39 this->Interactor = NULL;
40 this->InteractorStyle = NULL;
43 this->FirstRender = 1;
44 this->SliceOrientation = vtkImageColorViewer::SLICE_ORIENTATION_XY;
48 vtkRenderWindow *renwin = vtkRenderWindow::New();
49 this->SetRenderWindow(renwin);
52 vtkRenderer *ren = vtkRenderer::New();
53 this->SetRenderer(ren);
56 this->InstallPipeline();
59 //----------------------------------------------------------------------------
60 vtkImageColorViewer::~vtkImageColorViewer()
62 if (this->WindowLevel)
64 this->WindowLevel->Delete();
65 this->WindowLevel = NULL;
70 this->ImageActor->Delete();
71 this->ImageActor = NULL;
76 this->Renderer->Delete();
77 this->Renderer = NULL;
80 if (this->RenderWindow)
82 this->RenderWindow->Delete();
83 this->RenderWindow = NULL;
88 this->Interactor->Delete();
89 this->Interactor = NULL;
92 if (this->InteractorStyle)
94 this->InteractorStyle->Delete();
95 this->InteractorStyle = NULL;
99 //----------------------------------------------------------------------------
100 void vtkImageColorViewer::SetupInteractor(vtkRenderWindowInteractor *arg)
102 if (this->Interactor == arg)
107 this->UnInstallPipeline();
109 if (this->Interactor)
111 this->Interactor->UnRegister(this);
114 this->Interactor = arg;
116 if (this->Interactor)
118 this->Interactor->Register(this);
121 this->InstallPipeline();
125 this->Renderer->GetActiveCamera()->ParallelProjectionOn();
129 //----------------------------------------------------------------------------
130 void vtkImageColorViewer::SetRenderWindow(vtkRenderWindow *arg)
132 if (this->RenderWindow == arg)
137 this->UnInstallPipeline();
139 if (this->RenderWindow)
141 this->RenderWindow->UnRegister(this);
144 this->RenderWindow = arg;
146 if (this->RenderWindow)
148 this->RenderWindow->Register(this);
151 this->InstallPipeline();
154 //----------------------------------------------------------------------------
155 void vtkImageColorViewer::SetRenderer(vtkRenderer *arg)
157 if (this->Renderer == arg)
162 this->UnInstallPipeline();
166 this->Renderer->UnRegister(this);
169 this->Renderer = arg;
173 this->Renderer->Register(this);
176 this->InstallPipeline();
177 this->UpdateOrientation();
180 //----------------------------------------------------------------------------
181 void vtkImageColorViewer::SetSize(int a,int b)
183 this->RenderWindow->SetSize(a, b);
186 //----------------------------------------------------------------------------
187 int* vtkImageColorViewer::GetSize()
189 return this->RenderWindow->GetSize();
192 //----------------------------------------------------------------------------
193 void vtkImageColorViewer::GetSliceRange(int &min, int &max)
195 vtkImageData *input = this->GetInput();
198 input->UpdateInformation();
199 int *w_ext = input->GetWholeExtent();
200 min = w_ext[this->SliceOrientation * 2];
201 max = w_ext[this->SliceOrientation * 2 + 1];
205 //----------------------------------------------------------------------------
206 int* vtkImageColorViewer::GetSliceRange()
208 vtkImageData *input = this->GetInput();
211 input->UpdateInformation();
212 return input->GetWholeExtent() + this->SliceOrientation * 2;
217 //----------------------------------------------------------------------------
218 int vtkImageColorViewer::GetSliceMin()
220 int *range = this->GetSliceRange();
228 //----------------------------------------------------------------------------
229 int vtkImageColorViewer::GetSliceMax()
231 int *range = this->GetSliceRange();
239 //----------------------------------------------------------------------------
240 void vtkImageColorViewer::SetSlice(int slice)
242 int *range = this->GetSliceRange();
245 if (slice < range[0])
249 else if (slice > range[1])
255 if (this->Slice == slice)
263 this->UpdateDisplayExtent();
267 //----------------------------------------------------------------------------
268 void vtkImageColorViewer::SetSliceOrientation(int orientation)
270 if (orientation < vtkImageColorViewer::SLICE_ORIENTATION_YZ ||
271 orientation > vtkImageColorViewer::SLICE_ORIENTATION_XY)
273 vtkErrorMacro("Error - invalid slice orientation " << orientation);
277 if (this->SliceOrientation == orientation)
282 this->SliceOrientation = orientation;
286 int *range = this->GetSliceRange();
289 this->Slice = static_cast<int>((range[0] + range[1]) * 0.5);
292 this->UpdateOrientation();
293 this->UpdateDisplayExtent();
295 if (this->Renderer && this->GetInput())
297 double scale = this->Renderer->GetActiveCamera()->GetParallelScale();
298 this->Renderer->ResetCamera();
299 this->Renderer->GetActiveCamera()->SetParallelScale(scale);
305 //----------------------------------------------------------------------------
306 void vtkImageColorViewer::UpdateOrientation()
308 // Set the camera position
310 vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
313 switch (this->SliceOrientation)
315 case vtkImageColorViewer::SLICE_ORIENTATION_XY:
316 cam->SetFocalPoint(0,0,0);
317 cam->SetPosition(0,0,1); // -1 if medical ?
318 cam->SetViewUp(0,1,0);
321 case vtkImageColorViewer::SLICE_ORIENTATION_XZ:
322 cam->SetFocalPoint(0,0,0);
323 cam->SetPosition(0,-1,0); // 1 if medical ?
324 cam->SetViewUp(0,0,1);
327 case vtkImageColorViewer::SLICE_ORIENTATION_YZ:
328 cam->SetFocalPoint(0,0,0);
329 cam->SetPosition(1,0,0); // -1 if medical ?
330 cam->SetViewUp(0,0,1);
336 //----------------------------------------------------------------------------
337 void vtkImageColorViewer::UpdateDisplayExtent()
339 vtkImageData *input = this->GetInput();
340 if (!input || !this->ImageActor)
345 input->UpdateInformation();
346 int *w_ext = input->GetWholeExtent();
348 // Is the slice in range ? If not, fix it
350 int slice_min = w_ext[this->SliceOrientation * 2];
351 int slice_max = w_ext[this->SliceOrientation * 2 + 1];
352 if (this->Slice < slice_min || this->Slice > slice_max)
354 this->Slice = static_cast<int>((slice_min + slice_max) * 0.5);
357 // Set the image actor
359 switch (this->SliceOrientation)
361 case vtkImageColorViewer::SLICE_ORIENTATION_XY:
362 this->ImageActor->SetDisplayExtent(
363 w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice);
366 case vtkImageColorViewer::SLICE_ORIENTATION_XZ:
367 this->ImageActor->SetDisplayExtent(
368 w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5]);
371 case vtkImageColorViewer::SLICE_ORIENTATION_YZ:
372 this->ImageActor->SetDisplayExtent(
373 this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5]);
377 // Figure out the correct clipping range
381 if (this->InteractorStyle &&
382 this->InteractorStyle->GetAutoAdjustCameraClippingRange())
384 this->Renderer->ResetCameraClippingRange();
388 vtkCamera *cam = this->Renderer->GetActiveCamera();
392 this->ImageActor->GetBounds(bounds);
393 double spos = (double)bounds[this->SliceOrientation * 2];
394 double cpos = (double)cam->GetPosition()[this->SliceOrientation];
395 double range = fabs(spos - cpos);
396 double *spacing = input->GetSpacing();
398 ((double)spacing[0] + (double)spacing[1] + (double)spacing[2]) / 3.0;
399 cam->SetClippingRange(
400 range - avg_spacing * 3.0, range + avg_spacing * 3.0);
406 //----------------------------------------------------------------------------
407 void vtkImageColorViewer::SetPosition(int a,int b)
409 this->RenderWindow->SetPosition(a, b);
412 //----------------------------------------------------------------------------
413 int* vtkImageColorViewer::GetPosition()
415 return this->RenderWindow->GetPosition();
418 //----------------------------------------------------------------------------
419 void vtkImageColorViewer::SetDisplayId(void *a)
421 this->RenderWindow->SetDisplayId(a);
424 //----------------------------------------------------------------------------
425 void vtkImageColorViewer::SetWindowId(void *a)
427 this->RenderWindow->SetWindowId(a);
430 //----------------------------------------------------------------------------
431 void vtkImageColorViewer::SetParentId(void *a)
433 this->RenderWindow->SetParentId(a);
436 //----------------------------------------------------------------------------
437 double vtkImageColorViewer::GetColorWindow()
439 return this->WindowLevel->GetWindow();
442 //----------------------------------------------------------------------------
443 double vtkImageColorViewer::GetColorLevel()
445 return this->WindowLevel->GetLevel();
448 //----------------------------------------------------------------------------
449 void vtkImageColorViewer::SetColorWindow(double s)
451 this->WindowLevel->SetWindow(s);
454 //----------------------------------------------------------------------------
455 void vtkImageColorViewer::SetColorLevel(double s)
457 this->WindowLevel->SetLevel(s);
460 //----------------------------------------------------------------------------
461 class vtkImageColorViewerCallback : public vtkCommand
464 static vtkImageColorViewerCallback *New() { return new vtkImageColorViewerCallback; }
466 void Execute(vtkObject *caller,
468 void *vtkNotUsed(callData))
470 if (this->IV->GetInput() == NULL)
477 if (event == vtkCommand::ResetWindowLevelEvent)
479 this->IV->GetInput()->UpdateInformation();
480 this->IV->GetInput()->SetUpdateExtent
481 (this->IV->GetInput()->GetWholeExtent());
482 this->IV->GetInput()->Update();
483 double *range = this->IV->GetInput()->GetScalarRange();
484 this->IV->SetColorWindow(range[1] - range[0]);
485 this->IV->SetColorLevel(0.5 * (range[1] + range[0]));
492 if (event == vtkCommand::StartWindowLevelEvent)
494 this->InitialWindow = this->IV->GetColorWindow();
495 this->InitialLevel = this->IV->GetColorLevel();
499 // Adjust the window level here
501 vtkInteractorStyleImage *isi =
502 static_cast<vtkInteractorStyleImage *>(caller);
504 int *size = this->IV->GetRenderWindow()->GetSize();
505 double window = this->InitialWindow;
506 double level = this->InitialLevel;
508 // Compute normalized delta
511 (isi->GetWindowLevelCurrentPosition()[0] -
512 isi->GetWindowLevelStartPosition()[0]) / size[0];
514 (isi->GetWindowLevelStartPosition()[1] -
515 isi->GetWindowLevelCurrentPosition()[1]) / size[1];
517 // Scale by current values
519 if (fabs(window) > 0.01)
525 dx = dx * (window < 0 ? -0.01 : 0.01);
527 if (fabs(level) > 0.01)
533 dy = dy * (level < 0 ? -0.01 : 0.01);
536 // Abs so that direction does not flip
547 // Compute new window level
549 double newWindow = dx + window;
551 newLevel = level - dy;
553 // Stay away from zero and really
555 if (fabs(newWindow) < 0.01)
557 newWindow = 0.01*(newWindow < 0 ? -1 : 1);
559 if (fabs(newLevel) < 0.01)
561 newLevel = 0.01*(newLevel < 0 ? -1 : 1);
564 this->IV->SetColorWindow(newWindow);
565 this->IV->SetColorLevel(newLevel);
569 vtkImageColorViewer *IV;
570 double InitialWindow;
574 //----------------------------------------------------------------------------
575 void vtkImageColorViewer::InstallPipeline()
577 if (this->RenderWindow && this->Renderer)
579 this->RenderWindow->AddRenderer(this->Renderer);
582 if (this->Interactor)
584 if (!this->InteractorStyle)
586 this->InteractorStyle = vtkInteractorStyleImage::New();
587 vtkImageColorViewerCallback *cbk = vtkImageColorViewerCallback::New();
589 this->InteractorStyle->AddObserver(
590 vtkCommand::WindowLevelEvent, cbk);
591 this->InteractorStyle->AddObserver(
592 vtkCommand::StartWindowLevelEvent, cbk);
593 this->InteractorStyle->AddObserver(
594 vtkCommand::ResetWindowLevelEvent, cbk);
598 this->Interactor->SetInteractorStyle(this->InteractorStyle);
599 this->Interactor->SetRenderWindow(this->RenderWindow);
602 if (this->Renderer && this->ImageActor)
604 this->Renderer->AddViewProp(this->ImageActor);
607 if (this->ImageActor && this->WindowLevel)
609 this->ImageActor->SetInput(this->WindowLevel->GetOutput());
613 //----------------------------------------------------------------------------
614 void vtkImageColorViewer::UnInstallPipeline()
616 if (this->ImageActor)
618 this->ImageActor->SetInput(NULL);
621 if (this->Renderer && this->ImageActor)
623 this->Renderer->RemoveViewProp(this->ImageActor);
626 if (this->RenderWindow && this->Renderer)
628 this->RenderWindow->RemoveRenderer(this->Renderer);
631 if (this->Interactor)
633 this->Interactor->SetInteractorStyle(NULL);
634 this->Interactor->SetRenderWindow(NULL);
638 //----------------------------------------------------------------------------
639 void vtkImageColorViewer::Render()
641 if (this->FirstRender)
643 // Initialize the size if not set yet
645 vtkImageData *input = this->GetInput();
646 if (this->RenderWindow->GetSize()[0] == 0 && input)
648 input->UpdateInformation();
649 int *w_ext = input->GetWholeExtent();
652 switch (this->SliceOrientation)
654 case vtkImageColorViewer::SLICE_ORIENTATION_XY:
656 xs = w_ext[1] - w_ext[0] + 1;
657 ys = w_ext[3] - w_ext[2] + 1;
660 case vtkImageColorViewer::SLICE_ORIENTATION_XZ:
661 xs = w_ext[1] - w_ext[0] + 1;
662 ys = w_ext[5] - w_ext[4] + 1;
665 case vtkImageColorViewer::SLICE_ORIENTATION_YZ:
666 xs = w_ext[3] - w_ext[2] + 1;
667 ys = w_ext[5] - w_ext[4] + 1;
671 // if it would be smaller than 150 by 100 then limit to 150 by 100
672 this->RenderWindow->SetSize(
673 xs < 150 ? 150 : xs, ys < 100 ? 100 : ys);
677 this->Renderer->ResetCamera();
678 this->Renderer->GetActiveCamera()->SetParallelScale(
679 xs < 150 ? 75 : (xs - 1 ) / 2.0);
681 this->FirstRender = 0;
684 if (this->GetInput())
686 this->RenderWindow->Render();
690 //----------------------------------------------------------------------------
691 const char* vtkImageColorViewer::GetWindowName()
693 return this->RenderWindow->GetWindowName();
696 //----------------------------------------------------------------------------
697 void vtkImageColorViewer::SetOffScreenRendering(int i)
699 this->RenderWindow->SetOffScreenRendering(i);
702 //----------------------------------------------------------------------------
703 int vtkImageColorViewer::GetOffScreenRendering()
705 return this->RenderWindow->GetOffScreenRendering();
708 //----------------------------------------------------------------------------
709 void vtkImageColorViewer::SetInput(vtkImageData *in)
711 this->WindowLevel->SetInput(in);
712 this->UpdateDisplayExtent();
714 //----------------------------------------------------------------------------
715 vtkImageData* vtkImageColorViewer::GetInput()
717 return vtkImageData::SafeDownCast(this->WindowLevel->GetInput());
720 //----------------------------------------------------------------------------
721 void vtkImageColorViewer::SetInputConnection(vtkAlgorithmOutput* input)
723 this->WindowLevel->SetInputConnection(input);
724 this->UpdateDisplayExtent();
727 //----------------------------------------------------------------------------
728 #ifndef VTK_LEGACY_REMOVE
729 int vtkImageColorViewer::GetWholeZMin()
731 VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::GetWholeZMin, "VTK 5.0",
732 vtkImageColorViewer::GetSliceMin);
733 return this->GetSliceMin();
735 int vtkImageColorViewer::GetWholeZMax()
737 VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::GetWholeZMax, "VTK 5.0",
738 vtkImageColorViewer::GetSliceMax);
739 return this->GetSliceMax();
741 int vtkImageColorViewer::GetZSlice()
743 VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::GetZSlice, "VTK 5.0",
744 vtkImageColorViewer::GetSlice);
745 return this->GetSlice();
747 void vtkImageColorViewer::SetZSlice(int s)
749 VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::SetZSlice, "VTK 5.0",
750 vtkImageColorViewer::SetSlice);
755 //----------------------------------------------------------------------------
756 void vtkImageColorViewer::PrintSelf(ostream& os, vtkIndent indent)
758 this->Superclass::PrintSelf(os, indent);
760 os << indent << "RenderWindow:\n";
761 this->RenderWindow->PrintSelf(os,indent.GetNextIndent());
762 os << indent << "Renderer:\n";
763 this->Renderer->PrintSelf(os,indent.GetNextIndent());
764 os << indent << "ImageActor:\n";
765 this->ImageActor->PrintSelf(os,indent.GetNextIndent());
766 os << indent << "WindowLevel:\n" << endl;
767 this->WindowLevel->PrintSelf(os,indent.GetNextIndent());
768 os << indent << "Slice: " << this->Slice << endl;
769 os << indent << "SliceOrientation: " << this->SliceOrientation << endl;
770 os << indent << "InteractorStyle: " << endl;
771 if (this->InteractorStyle)
774 this->InteractorStyle->PrintSelf(os,indent.GetNextIndent());