Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

417 lines
14 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkWindowToImageFilter.cxx,v $
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 "vtkWindowToImageFilter.h"
#include "vtkCamera.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkRenderWindow.h"
#include "vtkRendererCollection.h"
#include "vtkStreamingDemandDrivenPipeline.h"
vtkCxxRevisionMacro(vtkWindowToImageFilter, "$Revision: 1.39.4.1 $");
vtkStandardNewMacro(vtkWindowToImageFilter);
//----------------------------------------------------------------------------
vtkWindowToImageFilter::vtkWindowToImageFilter()
{
this->Input = NULL;
this->Magnification = 1;
this->ReadFrontBuffer = 1;
this->ShouldRerender = 1;
this->Viewport[0] = 0;
this->Viewport[1] = 0;
this->Viewport[2] = 1;
this->Viewport[3] = 1;
this->InputBufferType = VTK_RGB;
this->SetNumberOfInputPorts(0);
this->SetNumberOfOutputPorts(1);
}
//----------------------------------------------------------------------------
vtkWindowToImageFilter::~vtkWindowToImageFilter()
{
if (this->Input)
{
this->Input->UnRegister(this);
this->Input = NULL;
}
}
//----------------------------------------------------------------------------
vtkImageData* vtkWindowToImageFilter::GetOutput()
{
return vtkImageData::SafeDownCast(this->GetOutputDataObject(0));
}
//----------------------------------------------------------------------------
void vtkWindowToImageFilter::SetInput(vtkWindow *input)
{
if (input != this->Input)
{
if (this->Input) {this->Input->UnRegister(this);}
this->Input = input;
if (this->Input) {this->Input->Register(this);}
this->Modified();
}
}
//----------------------------------------------------------------------------
void vtkWindowToImageFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
if ( this->Input )
{
os << indent << "Input:\n";
this->Input->PrintSelf(os,indent.GetNextIndent());
}
else
{
os << indent << "Input: (none)\n";
}
os << indent << "ReadFrontBuffer: " << this->ReadFrontBuffer << "\n";
os << indent << "Magnification: " << this->Magnification << "\n";
os << indent << "ShouldRerender: " << this->ShouldRerender << "\n";
os << indent << "Viewport: " << this->Viewport[0] << "," << this->Viewport[1]
<< "," << this->Viewport[2] << "," << this->Viewport[3] << "\n";
os << indent << "InputBufferType: " << this->InputBufferType << "\n";
}
//----------------------------------------------------------------------------
// This method returns the largest region that can be generated.
void vtkWindowToImageFilter::RequestInformation (
vtkInformation * vtkNotUsed(request),
vtkInformationVector** vtkNotUsed( inputVector ),
vtkInformationVector *outputVector)
{
if (this->Input == NULL )
{
vtkErrorMacro(<<"Please specify a renderer as input!");
return;
}
if(this->Magnification > 1 &&
(this->Viewport[0] != 0 || this->Viewport[1] != 0 ||
this->Viewport[2] != 1 || this->Viewport[3] != 1))
{
vtkWarningMacro(<<"Viewport extents are not used when Magnification > 1");
this->Viewport[0] = 0;
this->Viewport[1] = 0;
this->Viewport[2] = 1;
this->Viewport[3] = 1;
}
// set the extent
int *size = this->Input->GetSize();
int wExtent[6];
wExtent[0]= 0;
wExtent[1] = int((this->Viewport[2] - this->Viewport[0])*size[0] + 0.5)*
this->Magnification - 1;
wExtent[2] = 0;
wExtent[3] = int((this->Viewport[3] - this->Viewport[1])*size[1] + 0.5)*
this->Magnification - 1;
wExtent[4] = 0;
wExtent[5] = 0;
// get the info objects
vtkInformation* outInfo = outputVector->GetInformationObject(0);
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent, 6);
switch( this->InputBufferType )
{
case VTK_RGB:
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 3);
break;
case VTK_RGBA:
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 4);
break;
case VTK_ZBUFFER:
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1);
break;
default:
// VTK_RGB configuration by default
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 3);
break;
}
}
//----------------------------------------------------------------------------
int vtkWindowToImageFilter::ProcessRequest(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
// generate the data
if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
{
this->RequestData(request, inputVector, outputVector);
return 1;
}
// execute information
if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
{
this->RequestInformation(request, inputVector, outputVector);
return 1;
}
return this->Superclass::ProcessRequest(request, inputVector, outputVector);
}
//----------------------------------------------------------------------------
// This function reads a region from a file. The regions extent/axes
// are assumed to be the same as the file extent/order.
void vtkWindowToImageFilter::RequestData(
vtkInformation* vtkNotUsed( request ),
vtkInformationVector** vtkNotUsed( inputVector ),
vtkInformationVector* outputVector)
{
vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkImageData *out =
vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
out->SetExtent(out->GetUpdateExtent());
out->AllocateScalars();
if (!this->Input)
{
return;
}
int outIncrY;
int size[2],winsize[2];
int idxY, rowSize;
int i;
if (! ((out->GetScalarType() == VTK_UNSIGNED_CHAR &&
(this->InputBufferType == VTK_RGB || this->InputBufferType == VTK_RGBA)) ||
(out->GetScalarType() == VTK_FLOAT && this->InputBufferType == VTK_ZBUFFER)))
{
vtkErrorMacro("mismatch in scalar types!");
return;
}
// get the size of the render window
winsize[0] = this->Input->GetSize()[0];
winsize[1] = this->Input->GetSize()[1];
size[0] = int(winsize[0]*(this->Viewport[2]-this->Viewport[0]) + 0.5);
size[1] = int(winsize[1]*(this->Viewport[3]-this->Viewport[1]) + 0.5);
rowSize = size[0]*out->GetNumberOfScalarComponents();
outIncrY = size[0]*this->Magnification*out->GetNumberOfScalarComponents();
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;
}
vtkRendererCollection *rc = renWin->GetRenderers();
vtkRenderer *aren;
vtkCamera *cam;
int numRenderers = rc->GetNumberOfItems();
// for each renderer
vtkCamera **cams = new vtkCamera *[numRenderers];
viewAngles = new float [numRenderers];
windowCenters = new double [numRenderers*2];
double *parallelScale = new double [numRenderers];
vtkCollectionSimpleIterator rsit;
rc->InitTraversal(rsit);
for (i = 0; i < numRenderers; ++i)
{
aren = rc->GetNextRenderer(rsit);
cams[i] = aren->GetActiveCamera();
cams[i]->Register(this);
cams[i]->GetWindowCenter(windowCenters+i*2);
viewAngles[i] = cams[i]->GetViewAngle();
parallelScale[i] = cams[i]->GetParallelScale();
cam = cams[i]->NewInstance();
cam->SetPosition(cams[i]->GetPosition());
cam->SetFocalPoint(cams[i]->GetFocalPoint());
cam->SetViewUp(cams[i]->GetViewUp());
cam->SetClippingRange(cams[i]->GetClippingRange());
cam->SetParallelProjection(cams[i]->GetParallelProjection());
cam->SetFocalDisk(cams[i]->GetFocalDisk());
cam->SetUserTransform(cams[i]->GetUserTransform());
cam->SetViewShear(cams[i]->GetViewShear());
aren->SetActiveCamera(cam);
}
// render each of the tiles required to fill this request
this->Input->SetTileScale(this->Magnification);
this->Input->GetSize();
int x, y;
for (y = 0; y < this->Magnification; y++)
{
for (x = 0; x < this->Magnification; x++)
{
// setup the Window ivars
this->Input->SetTileViewport((double)x/this->Magnification,
(double)y/this->Magnification,
(x+1.0)/this->Magnification,
(y+1.0)/this->Magnification);
double *tvp = this->Input->GetTileViewport();
// for each renderer, setup camera
rc->InitTraversal(rsit);
for (i = 0; i < numRenderers; ++i)
{
aren = rc->GetNextRenderer(rsit);
cam = aren->GetActiveCamera();
double *vp = aren->GetViewport();
double visVP[4];
visVP[0] = (vp[0] < tvp[0]) ? tvp[0] : vp[0];
visVP[0] = (visVP[0] > tvp[2]) ? tvp[2] : visVP[0];
visVP[1] = (vp[1] < tvp[1]) ? tvp[1] : vp[1];
visVP[1] = (visVP[1] > tvp[3]) ? tvp[3] : visVP[1];
visVP[2] = (vp[2] > tvp[2]) ? tvp[2] : vp[2];
visVP[2] = (visVP[2] < tvp[0]) ? tvp[0] : visVP[2];
visVP[3] = (vp[3] > tvp[3]) ? tvp[3] : vp[3];
visVP[3] = (visVP[3] < tvp[1]) ? tvp[1] : visVP[3];
// compute magnification
double mag = (visVP[3] - visVP[1])/(vp[3] - vp[1]);
// compute the delta
double deltax = (visVP[2] + visVP[0])/2.0 - (vp[2] + vp[0])/2.0;
double deltay = (visVP[3] + visVP[1])/2.0 - (vp[3] + vp[1])/2.0;
// scale by original window size
if (visVP[2] - visVP[0] > 0)
{
deltax = 2.0*deltax/(visVP[2] - visVP[0]);
}
if (visVP[3] - visVP[1] > 0)
{
deltay = 2.0*deltay/(visVP[3] - visVP[1]);
}
cam->SetWindowCenter(windowCenters[i*2]+deltax,windowCenters[i*2+1]+deltay);
cam->SetViewAngle(asin(sin(viewAngles[i]*3.1415926/360.0)*mag)
* 360.0 / 3.1415926);
cam->SetParallelScale(parallelScale[i]*mag);
}
// now render the tile and get the data
if (this->ShouldRerender || this->Magnification > 1)
{
this->Input->Render();
}
int buffer = this->ReadFrontBuffer;
if(!this->Input->GetDoubleBuffer())
{
buffer = 1;
}
if (this->InputBufferType == VTK_RGB || this->InputBufferType == VTK_RGBA)
{
unsigned char *pixels, *pixels1, *outPtr;
if (this->InputBufferType == VTK_RGB)
{
pixels = this->Input->GetPixelData(int(this->Viewport[0]* winsize[0]),
int(this->Viewport[1]* winsize[1]),
int(this->Viewport[2]* winsize[0] + 0.5) - 1,
int(this->Viewport[3]* winsize[1] + 0.5) - 1, buffer);
}
else
{
pixels = renWin->GetRGBACharPixelData(int(this->Viewport[0]* winsize[0]),
int(this->Viewport[1]* winsize[1]),
int(this->Viewport[2]* winsize[0] + 0.5) - 1,
int(this->Viewport[3]* winsize[1] + 0.5) - 1, buffer);
}
pixels1 = pixels;
// now write the data to the output image
outPtr =
(unsigned char *)out->GetScalarPointer(x*size[0],y*size[1], 0);
for (idxY = 0; idxY < size[1]; idxY++)
{
memcpy(outPtr,pixels1,rowSize);
outPtr += outIncrY;
pixels1 += rowSize;
}
// free the memory
delete [] pixels;
}
else
{ // VTK_ZBUFFER
float *pixels, *pixels1, *outPtr;
pixels = renWin->GetZbufferData(int(this->Viewport[0]* winsize[0]),
int(this->Viewport[1]* winsize[1]),
int(this->Viewport[2]* winsize[0] + 0.5) - 1,
int(this->Viewport[3]* winsize[1] + 0.5) - 1);
pixels1 = pixels;
// now write the data to the output image
outPtr =
(float *)out->GetScalarPointer(x*size[0],y*size[1], 0);
for (idxY = 0; idxY < size[1]; idxY++)
{
memcpy(outPtr,pixels1,rowSize*sizeof(float));
outPtr += outIncrY;
pixels1 += rowSize;
}
// free the memory
delete [] pixels;
}
}
}
// restore settings
// for each renderer
rc->InitTraversal(rsit);
for (i = 0; i < numRenderers; ++i)
{
aren = rc->GetNextRenderer(rsit);
// store the old view angle & set the new
cam = aren->GetActiveCamera();
aren->SetActiveCamera(cams[i]);
cams[i]->UnRegister(this);
cam->Delete();
}
delete [] viewAngles;
delete [] windowCenters;
delete [] parallelScale;
delete [] cams;
// render each of the tiles required to fill this request
this->Input->SetTileScale(1);
this->Input->SetTileViewport(0.0,0.0,1.0,1.0);
this->Input->GetSize();
}
int vtkWindowToImageFilter::FillOutputPortInformation(
int vtkNotUsed(port), vtkInformation* info)
{
// now add our info
info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData");
return 1;
}