Commit 916cf198 authored by Joachim Pouderoux's avatar Joachim Pouderoux Committed by Kitware Robot

Merge topic 'FixWindowToImageFilterWithViewport'

88376dfb Fix crash of the WindowToImageFilter when specifying a Viewport.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !919
parents c358a6a8 88376dfb
Pipeline #2790 running with stage
......@@ -74,6 +74,7 @@ vtk_add_test_cxx(${vtk-module}CxxTests tests
TestTStripsNormalsColorsTCoords.cxx
TestTStripsNormalsTCoords.cxx
TestTStripsTCoords.cxx
TestWindowToImageFilter.cxx
otherLookupTable.cxx,NO_VALID
otherLookupTableWithEnabling.cxx,NO_VALID
RenderNonFinite.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestWindowToImageFilter.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkActor.h"
#include "vtkImageActor.h"
#include "vtkImageMapper3D.h"
#include "vtkNew.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSphereSource.h"
#include "vtkWindowToImageFilter.h"
int TestWindowToImageFilter(int argc, char* argv[])
{
vtkNew<vtkSphereSource> sphereSource;
sphereSource->SetCenter(0.0, 0.0, 0.0);
sphereSource->SetRadius(5.0);
sphereSource->Update();
// Render the sphere
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(sphereSource->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper.Get());
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer.Get());
renderWindow->SetMultiSamples(0);
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(renderWindow.Get());
renderer->AddActor(actor.Get());
renderWindow->Render();
// Take the partial screenshot
vtkNew<vtkWindowToImageFilter> windowToImageFilter;
windowToImageFilter->SetInput(renderWindow.Get());
windowToImageFilter->SetInputBufferTypeToRGB();
windowToImageFilter->SetViewport(0.5, 0.5, 0.8, 1.0);
windowToImageFilter->ReadFrontBufferOff(); // read from the back buffer
windowToImageFilter->Update();
// Show the screenshot
vtkNew<vtkImageActor> imageActor;
imageActor->GetMapper()->SetInputData(windowToImageFilter->GetOutput());
renderer->RemoveActor(actor.Get());
renderer->AddActor(imageActor.Get());
renderWindow->Render();
renderer->ResetCamera();
renderWindow->Render();
int retVal = vtkRegressionTestImage(renderWindow.Get());
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
renderWindowInteractor->Start();
}
return !retVal;
}
......@@ -133,6 +133,30 @@ void vtkWindowToImageFilter::PrintSelf(ostream& os, vtkIndent indent)
os << indent << "FixBoundary: " << this->FixBoundary << endl;
}
//----------------------------------------------------------------------------
void vtkWindowToImageFilter::SetViewport(double a1, double a2, double a3, double a4)
{
#define CLAMP(_x, _min, _max) _x = _x < _min ? _min : (_x > _max ? _max : _x)
CLAMP(a1, 0., 1.);
CLAMP(a2, 0., 1.);
CLAMP(a3, 0., 1.);
CLAMP(a4, 0., 1.);
vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting Viewport to (" << a1 << "," << a2 << "," << a3 << "," << a4 << ")");
if ((this->Viewport[0] != a1) || (this->Viewport[1] != a2) || (this->Viewport[2] != a3) || (this->Viewport[3] != a4))
{
this->Viewport[0] = a1;
this->Viewport[1] = a2;
this->Viewport[2] = a3;
this->Viewport[3] = a4;
this->Modified();
}
}
//----------------------------------------------------------------------------
void vtkWindowToImageFilter::SetViewport(double vp[4])
{
this->SetViewport(vp[0], vp[1], vp[2], vp[3]);
}
//----------------------------------------------------------------------------
// This method returns the largest region that can be generated.
......@@ -242,8 +266,13 @@ void vtkWindowToImageFilter::RequestData(
return;
}
int idxY;
int i;
vtkRenderWindow *renWin = vtkRenderWindow::SafeDownCast(this->Input);
if (!renWin)
{
vtkWarningMacro(
"The window passed to window to image should be a RenderWindow or one of its subclasses");
return;
}
if (! ((out->GetScalarType() == VTK_UNSIGNED_CHAR &&
(this->InputBufferType == VTK_RGB || this->InputBufferType == VTK_RGBA)) ||
......@@ -254,11 +283,9 @@ void vtkWindowToImageFilter::RequestData(
}
int tileScale[2];
int magTileScale[2];
this->Input->GetTileScale(tileScale);
magTileScale[0] = this->Magnification * tileScale[0];
magTileScale[1] = this->Magnification * tileScale[1];
int magTileScale[2] = {this->Magnification * tileScale[0],
this->Magnification * tileScale[1]};
int tileSize[2] = {this->Input->GetActualSize()[0],
this->Input->GetActualSize()[1]};
......@@ -266,27 +293,25 @@ void vtkWindowToImageFilter::RequestData(
// This is the size of the window with all tiles accounted for:
int winSize[2] = {this->Input->GetSize()[0], this->Input->GetSize()[1]};
int vpSize[2];
vpSize[0] = int(this->Viewport[2] * winSize[0] + 0.5)
- int(this->Viewport[0] * winSize[0]);
vpSize[1] = int(this->Viewport[3] * winSize[1] + 0.5)
- int(this->Viewport[1] * winSize[1]);
int imageBounds[4] =
{
int(this->Viewport[0] * tileSize[0]),
int(this->Viewport[1] * tileSize[1]),
int(this->Viewport[2] * tileSize[0] + 0.5) - 1,
int(this->Viewport[3] * tileSize[1] + 0.5) - 1
};
int imageSize[2] = {vpSize[0] * this->Magnification,
vpSize[1] * this->Magnification};
int vpSize[2] = {imageBounds[2] - imageBounds[0] + 1,
imageBounds[3] - imageBounds[1] + 1};
int inIncrY = tileSize[0] * out->GetNumberOfScalarComponents();
int outIncrY = imageSize[0] * out->GetNumberOfScalarComponents();
int imageSize[2] = {vpSize[0] * magTileScale[0],
vpSize[1] * magTileScale[1]};
float *viewAngles;
double *windowCenters;
vtkRenderWindow *renWin = vtkRenderWindow::SafeDownCast(this->Input);
if (!renWin)
{
vtkWarningMacro(
"The window passed to window to image should be a RenderWindow or one of its subclasses");
return;
}
int inIncrY = vpSize[0];
inIncrY *= (this->InputBufferType == VTK_RGB) ? 3 :
((this->InputBufferType == VTK_RGBA) ? 4 : 1);
int outIncrY = imageSize[0] * out->GetNumberOfScalarComponents();
vtkRendererCollection *rc = renWin->GetRenderers();
vtkRenderer *aren;
......@@ -295,12 +320,12 @@ void vtkWindowToImageFilter::RequestData(
// for each renderer
vtkCamera **cams = new vtkCamera *[numRenderers];
viewAngles = new float [numRenderers];
windowCenters = new double [numRenderers*2];
float* viewAngles = new float [numRenderers];
double* windowCenters = new double [numRenderers*2];
double *parallelScale = new double [numRenderers];
vtkCollectionSimpleIterator rsit;
rc->InitTraversal(rsit);
for (i = 0; i < numRenderers; ++i)
for (int i = 0; i < numRenderers; ++i)
{
aren = rc->GetNextRenderer(rsit);
cams[i] = aren->GetActiveCamera();
......@@ -318,7 +343,6 @@ void vtkWindowToImageFilter::RequestData(
this->Input->GetSize();
//this->Rescale2DActors();
int x, y;
int num_iterations[2] = {magTileScale[0], magTileScale[1]};
bool overlap_viewports = false;
......@@ -332,11 +356,11 @@ void vtkWindowToImageFilter::RequestData(
}
}
// Precompute the tile viewport for each iteration.
// Precompute the tile this->Viewport for each iteration.
double *viewports = new double[4 * num_iterations[0] * num_iterations[1]];
for (y = 0; y < num_iterations[1]; y++)
for (int y = 0; y < num_iterations[1]; y++)
{
for (x = 0; x < num_iterations[0]; x++)
for (int x = 0; x < num_iterations[0]; x++)
{
double* cur_viewport = &viewports[(num_iterations[1] * y + x) * 4];
cur_viewport[0] = static_cast<double>(x) / magTileScale[0];
......@@ -371,9 +395,9 @@ void vtkWindowToImageFilter::RequestData(
}
}
for (y = 0; y < num_iterations[1]; y++)
for (int y = 0; y < num_iterations[1]; y++)
{
for (x = 0; x < num_iterations[0]; x++)
for (int x = 0; x < num_iterations[0]; x++)
{
// setup the Window ivars
double* cur_viewport = &viewports[(num_iterations[1] * y + x) * 4];
......@@ -382,7 +406,7 @@ void vtkWindowToImageFilter::RequestData(
// for each renderer, setup camera
rc->InitTraversal(rsit);
for (i = 0; i < numRenderers; ++i)
for (int i = 0; i < numRenderers; ++i)
{
aren = rc->GetNextRenderer(rsit);
cam = aren->GetActiveCamera();
......@@ -439,7 +463,7 @@ void vtkWindowToImageFilter::RequestData(
this->Input->MakeCurrent();
int buffer = this->ReadFrontBuffer;
if(!this->Input->GetDoubleBuffer())
if (!this->Input->GetDoubleBuffer())
{
buffer = 1;
}
......@@ -448,22 +472,14 @@ void vtkWindowToImageFilter::RequestData(
unsigned char *pixels, *pixels1, *outPtr;
if (this->InputBufferType == VTK_RGB)
{
pixels =
this->Input->GetPixelData(int(this->Viewport[0]* tileSize[0]),
int(this->Viewport[1]* tileSize[1]),
int(this->Viewport[2]* tileSize[0] + 0.5) - 1,
int(this->Viewport[3]* tileSize[1] + 0.5) - 1, buffer);
pixels = this->Input->GetPixelData(
imageBounds[0], imageBounds[1], imageBounds[2], imageBounds[3], buffer);
}
else
{
pixels =
renWin->GetRGBACharPixelData(int(this->Viewport[0]* tileSize[0]),
int(this->Viewport[1]* tileSize[1]),
int(this->Viewport[2]* tileSize[0] + 0.5) - 1,
int(this->Viewport[3]* tileSize[1] + 0.5) - 1, buffer);
pixels = renWin->GetRGBACharPixelData(
imageBounds[0], imageBounds[1], imageBounds[2], imageBounds[3], buffer);
}
pixels1 = pixels;
// now write the data to the output image
......@@ -485,7 +501,7 @@ void vtkWindowToImageFilter::RequestData(
start_x_offset *= ncomp;
end_x_offset *= ncomp;
for (idxY = 0; idxY < tileSize[1]; idxY++)
for (int idxY = 0; idxY < tileSize[1]; idxY++)
{
if (idxY >= start_y_offset && idxY < tileSize[1] - end_y_offset)
{
......@@ -499,11 +515,11 @@ void vtkWindowToImageFilter::RequestData(
else
{
outPtr = static_cast<unsigned char *>(
out->GetScalarPointer(x * tileSize[0], y * tileSize[1], 0));
out->GetScalarPointer(x * vpSize[0], y * vpSize[1], 0));
for (idxY = 0; idxY < tileSize[1]; idxY++)
for (int idxY = 0; idxY < vpSize[1]; idxY++)
{
memcpy(outPtr,pixels1,inIncrY);
memcpy(outPtr, pixels1, inIncrY);
outPtr += outIncrY;
pixels1 += inIncrY;
}
......@@ -515,22 +531,17 @@ void vtkWindowToImageFilter::RequestData(
}
else
{ // VTK_ZBUFFER
float *pixels, *pixels1, *outPtr;
pixels = renWin->GetZbufferData(int(this->Viewport[0] * tileSize[0]),
int(this->Viewport[1] * tileSize[1]),
int(this->Viewport[2] * tileSize[0] + 0.5) - 1,
int(this->Viewport[3] * tileSize[1] + 0.5) - 1);
pixels1 = pixels;
float* pixels = renWin->GetZbufferData(
imageBounds[0], imageBounds[1], imageBounds[2], imageBounds[3]);
float* pixels1 = pixels;
// now write the data to the output image
outPtr =
static_cast<float *>(out->GetScalarPointer(x * tileSize[0],
y * tileSize[1], 0));
float* outPtr = static_cast<float *>(
out->GetScalarPointer(x * vpSize[0], y * vpSize[1], 0));
for (idxY = 0; idxY < tileSize[1]; idxY++)
for (int idxY = 0; idxY < vpSize[1]; idxY++)
{
memcpy(outPtr,pixels1,inIncrY*sizeof(float));
memcpy(outPtr, pixels1, inIncrY * sizeof(float));
outPtr += outIncrY;
pixels1 += inIncrY;
}
......@@ -544,7 +555,7 @@ void vtkWindowToImageFilter::RequestData(
// restore settings
// for each renderer
rc->InitTraversal(rsit);
for (i = 0; i < numRenderers; ++i)
for (int i = 0; i < numRenderers; ++i)
{
aren = rc->GetNextRenderer(rsit);
// store the old view angle & set the new
......
......@@ -108,7 +108,8 @@ public:
// Description:
// Set/get the extents to be used to generate the image. Initial value is
// {0,0,1,1} (This option does not work if Magnification > 1.)
vtkSetVector4Macro(Viewport,double);
void SetViewport(double, double, double, double);
void SetViewport(double*);
vtkGetVectorMacro(Viewport,double,4);
// Description:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment