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.
 
 
 
 
 
 

692 lines
20 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkOpenGLImageMapper.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 "vtkOpenGLImageMapper.h"
#include "vtkActor2D.h"
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkProperty2D.h"
#include "vtkViewport.h"
#include "vtkWindow.h"
#include "vtkgluPickMatrix.h"
#include "vtkOpenGL.h"
#include <limits.h>
#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkOpenGLImageMapper, "$Revision: 1.62 $");
vtkStandardNewMacro(vtkOpenGLImageMapper);
#endif
vtkOpenGLImageMapper::vtkOpenGLImageMapper()
{
}
vtkOpenGLImageMapper::~vtkOpenGLImageMapper()
{
}
//----------------------------------------------------------------------------
// I know #define can be evil, but this macro absolutely ensures
// that the code will be inlined. The macro expects 'val' to
// be predefined to the same type as y
#define vtkClampToUnsignedChar(x,y) \
{ \
val = (y); \
if (val < 0) \
{ \
val = 0; \
} \
if (val > 255) \
{ \
val = 255; \
} \
(x) = (unsigned char)(val); \
}
/* should do proper rounding, as follows:
(x) = (unsigned char)(val + 0.5f); \
*/
// the bit-shift must be done after the comparison to zero
// because bit-shift is implemenation dependant for negative numbers
#define vtkClampIntToUnsignedChar(x,y,shift) \
{ \
val = (y); \
if (val < 0) \
{ \
val = 0; \
} \
val >>= shift; \
if (val > 255) \
{ \
val = 255; \
} \
(x) = (unsigned char)(val); \
}
// pad an integer to a multiply of four, for OpenGL
inline int vtkPadToFour(int n)
{
return (((n+3)/4)*4);
}
//---------------------------------------------------------------
// render the image by doing the following:
// 1) apply shift and scale to pixel values
// 2) clamp to [0,255] and convert to unsigned char
// 3) draw using glDrawPixels
template <class T>
void vtkOpenGLImageMapperRenderDouble(vtkOpenGLImageMapper *self, vtkImageData *data,
T *dataPtr, double shift, double scale,
int *actorPos, int *actorPos2, int front, int *vsize)
{
int inMin0 = self->DisplayExtent[0];
int inMax0 = self->DisplayExtent[1];
int inMin1 = self->DisplayExtent[2];
int inMax1 = self->DisplayExtent[3];
int width = inMax0 - inMin0 + 1;
int height = inMax1 - inMin1 + 1;
vtkIdType* tempIncs = data->GetIncrements();
vtkIdType inInc1 = tempIncs[1];
int bpp = data->GetNumberOfScalarComponents();
double range[2];
data->GetPointData()->GetScalars()->GetDataTypeRange( range );
// the value .999 is sensitive to z-buffer depth
glRasterPos3f((2.0 * (GLfloat)(actorPos[0]) / vsize[0] - 1),
(2.0 * (GLfloat)(actorPos[1]) / vsize[1] - 1),
(front)?(-1):(.999));
glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
// reformat data into unsigned char
T *inPtr = (T *)dataPtr;
T *inPtr1 = inPtr;
int i;
int j = height;
unsigned char *newPtr;
if (bpp < 4)
{
newPtr = new unsigned char[vtkPadToFour(3*width*height)];
}
else
{
newPtr = new unsigned char[4*width*height];
}
unsigned char *ptr = newPtr;
double val;
unsigned char tmp;
while (--j >= 0)
{
inPtr = inPtr1;
i = width;
switch (bpp)
{
case 1:
while (--i >= 0)
{
vtkClampToUnsignedChar(tmp,((*inPtr++ + shift)*scale));
*ptr++ = tmp;
*ptr++ = tmp;
*ptr++ = tmp;
}
break;
case 2:
while (--i >= 0)
{
vtkClampToUnsignedChar(tmp,((*inPtr++ + shift)*scale));
*ptr++ = tmp;
vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale));
*ptr++ = tmp;
}
break;
case 3:
while (--i >= 0)
{
vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale));
vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale));
vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale));
}
break;
default:
while (--i >= 0)
{
vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale));
vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale));
vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale));
vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale));
inPtr += bpp-4;
}
break;
}
inPtr1 += inInc1;
}
if (self->GetRenderToRectangle())
{
int rectwidth = (actorPos2[0] - actorPos[0]) + 1;
int rectheight = (actorPos2[1] - actorPos[1]) + 1;
float xscale = (float)rectwidth/width;
float yscale = (float)rectheight/height;
glPixelZoom(xscale, yscale);
}
glDrawPixels(width, height, ((bpp < 4) ? GL_RGB : GL_RGBA),
GL_UNSIGNED_BYTE, (void *)newPtr);
if (self->GetRenderToRectangle())
{
// restore zoom to 1,1 otherwise other glDrawPixels cals may be affected
glPixelZoom(1.0, 1.0);
}
delete [] newPtr;
}
//---------------------------------------------------------------
// Same as above, but uses fixed-point math for shift and scale.
// The number of bits used for the fraction is determined from the
// scale. Enough bits are always left over for the integer that
// overflow cannot occur.
template <class T>
void vtkOpenGLImageMapperRenderShort(vtkOpenGLImageMapper *self, vtkImageData *data,
T *dataPtr, double shift, double scale,
int *actorPos, int *actorPos2, int front,
int *vsize)
{
int inMin0 = self->DisplayExtent[0];
int inMax0 = self->DisplayExtent[1];
int inMin1 = self->DisplayExtent[2];
int inMax1 = self->DisplayExtent[3];
int width = inMax0 - inMin0 + 1;
int height = inMax1 - inMin1 + 1;
vtkIdType* tempIncs = data->GetIncrements();
vtkIdType inInc1 = tempIncs[1];
int bpp = data->GetNumberOfScalarComponents();
double range[2];
data->GetPointData()->GetScalars()->GetDataTypeRange( range );
// the value .999 is sensitive to z-buffer depth
glRasterPos3f((2.0 * (GLfloat)(actorPos[0]) / vsize[0] - 1),
(2.0 * (GLfloat)(actorPos[1]) / vsize[1] - 1),
(front)?(-1):(.999));
glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
// Find the number of bits to use for the fraction:
// continue increasing the bits until there is an overflow
// in the worst case, then decrease by 1.
// The "*2.0" and "*1.0" ensure that the comparison is done
// with double-precision math.
int bitShift = 0;
double absScale = ((scale < 0) ? -scale : scale);
while (((long)(1 << bitShift)*absScale)*2.0*USHRT_MAX < INT_MAX*1.0)
{
bitShift++;
}
bitShift--;
long sscale = (long) (scale*(1 << bitShift));
long sshift = (long) (sscale*shift);
/* should do proper rounding, as follows:
long sscale = (long) floor(scale*(1 << bitShift) + 0.5);
long sshift = (long) floor((scale*shift + 0.5)*(1 << bitShift));
*/
long val;
unsigned char tmp;
T *inPtr = (T *)dataPtr;
T *inPtr1 = inPtr;
int i;
int j = height;
unsigned char *newPtr;
if (bpp < 4)
{
newPtr = new unsigned char[vtkPadToFour(3*width*height)];
}
else
{
newPtr = new unsigned char[4*width*height];
}
unsigned char *ptr = newPtr;
while (--j >= 0)
{
inPtr = inPtr1;
i = width;
switch (bpp)
{
case 1:
while (--i >= 0)
{
vtkClampIntToUnsignedChar(tmp,(*inPtr++*sscale+sshift),bitShift);
*ptr++ = tmp;
*ptr++ = tmp;
*ptr++ = tmp;
}
break;
case 2:
while (--i >= 0)
{
vtkClampIntToUnsignedChar(tmp,(*inPtr++*sscale+sshift),bitShift);
*ptr++ = tmp;
vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift);
*ptr++ = tmp;
}
break;
case 3:
while (--i >= 0)
{
vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift);
vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift);
vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift);
}
break;
default:
while (--i >= 0)
{
vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift);
vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift);
vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift);
vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift);
inPtr += bpp-4;
}
break;
}
inPtr1 += inInc1;
}
if (self->GetRenderToRectangle())
{
int rectwidth = (actorPos2[0] - actorPos[0]) + 1;
int rectheight = (actorPos2[1] - actorPos[1]) + 1;
float xscale = (float)rectwidth/width;
float yscale = (float)rectheight/height;
glPixelZoom(xscale, yscale);
}
glDrawPixels(width, height, ((bpp < 4) ? GL_RGB : GL_RGBA),
GL_UNSIGNED_BYTE, (void *)newPtr);
if (self->GetRenderToRectangle())
{
// restore zoom to 1,1 otherwise other glDrawPixels cals may be affected
glPixelZoom(1.0, 1.0);
}
delete [] newPtr;
}
//---------------------------------------------------------------
// render unsigned char data without any shift/scale
template <class T>
void vtkOpenGLImageMapperRenderChar(vtkOpenGLImageMapper *self, vtkImageData *data,
T *dataPtr, int *actorPos, int *actorPos2,
int front, int *vsize)
{
int inMin0 = self->DisplayExtent[0];
int inMax0 = self->DisplayExtent[1];
int inMin1 = self->DisplayExtent[2];
int inMax1 = self->DisplayExtent[3];
int width = inMax0 - inMin0 + 1;
int height = inMax1 - inMin1 + 1;
vtkIdType* tempIncs = data->GetIncrements();
vtkIdType inInc1 = tempIncs[1];
int bpp = data->GetPointData()->GetScalars()->GetNumberOfComponents();
double range[2];
data->GetPointData()->GetScalars()->GetDataTypeRange( range );
// the value .999 is sensitive to z-buffer depth
glRasterPos3f((2.0 * (GLfloat)(actorPos[0]) / vsize[0] - 1),
(2.0 * (GLfloat)(actorPos[1]) / vsize[1] - 1),
(front)?(-1):(.999));
glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
if (self->GetRenderToRectangle())
{
int rectwidth = (actorPos2[0] - actorPos[0]) + 1;
int rectheight = (actorPos2[1] - actorPos[1]) + 1;
float xscale = (float)rectwidth/width;
float yscale = (float)rectheight/height;
glPixelZoom(xscale, yscale);
}
//
if (bpp == 3)
{ // feed through RGB bytes without reformatting
if (inInc1 != width*bpp)
{
glPixelStorei( GL_UNPACK_ROW_LENGTH, inInc1/bpp );
}
glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, (void *)dataPtr);
}
else if (bpp == 4)
{ // feed through RGBA bytes without reformatting
if (inInc1 != width*bpp)
{
glPixelStorei( GL_UNPACK_ROW_LENGTH, inInc1/bpp );
}
glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void *)dataPtr);
}
else
{ // feed through other bytes without reformatting
T *inPtr = (T *)dataPtr;
T *inPtr1 = inPtr;
unsigned char tmp;
int i;
int j = height;
unsigned char *newPtr;
if (bpp < 4)
{
newPtr = new unsigned char[vtkPadToFour(3*width*height)];
}
else
{
newPtr = new unsigned char[4*width*height];
}
unsigned char *ptr = newPtr;
while (--j >= 0)
{
inPtr = inPtr1;
i = width;
switch (bpp)
{
case 1:
while (--i >= 0)
{
*ptr++ = tmp = *inPtr++;
*ptr++ = tmp;
*ptr++ = tmp;
}
break;
case 2:
while (--i >= 0)
{
*ptr++ = tmp = *inPtr++;
*ptr++ = *inPtr++;
*ptr++ = tmp;
}
break;
case 3:
while (--i >= 0)
{
*ptr++ = *inPtr++;
*ptr++ = *inPtr++;
*ptr++ = *inPtr++;
}
break;
default:
while (--i >= 0)
{
*ptr++ = *inPtr++;
*ptr++ = *inPtr++;
*ptr++ = *inPtr++;
*ptr++ = *inPtr++;
inPtr += bpp-4;
}
break;
}
inPtr1 += inInc1;
}
glDrawPixels(width, height, ((bpp < 4) ? GL_RGB : GL_RGBA),
GL_UNSIGNED_BYTE, (void *)newPtr);
delete [] newPtr;
}
if (self->GetRenderToRectangle())
{
// restore zoom to 1,1 otherwise other glDrawPixels cals may be affected
glPixelZoom(1.0, 1.0);
}
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
}
//----------------------------------------------------------------------------
// Define overloads to help the template macro below dispatch to a
// suitable implementation for each type. The last argument is of
// type "long" for the template and of type "int" for the
// non-templates. The template macro's call to this function always
// passes a literal "1" as the last argument, which requires a
// conversion to produce a long. This helps broken compilers select
// the non-template even when the template is otherwise an equal
// match.
template <class T>
void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data,
T *dataPtr, double shift, double scale,
int *actorPos, int *actorPos2, int front, int *vsize,
long)
{
vtkOpenGLImageMapperRenderDouble(self, data, dataPtr, shift, scale,
actorPos, actorPos2, front, vsize);
}
void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data,
char* dataPtr, double shift, double scale,
int *actorPos, int *actorPos2, int front, int *vsize,
int)
{
if(shift == 0.0 && scale == 1.0)
{
vtkOpenGLImageMapperRenderChar(self, data, dataPtr,
actorPos, actorPos2, front, vsize);
}
else
{
vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale,
actorPos, actorPos2, front, vsize);
}
}
void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data,
unsigned char* dataPtr, double shift, double scale,
int *actorPos, int *actorPos2, int front, int *vsize,
int)
{
if(shift == 0.0 && scale == 1.0)
{
vtkOpenGLImageMapperRenderChar(self, data, dataPtr,
actorPos, actorPos2, front, vsize);
}
else
{
vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale,
actorPos, actorPos2, front, vsize);
}
}
void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data,
signed char* dataPtr, double shift, double scale,
int *actorPos, int *actorPos2, int front, int *vsize,
int)
{
if(shift == 0.0 && scale == 1.0)
{
vtkOpenGLImageMapperRenderChar(self, data, dataPtr,
actorPos, actorPos2, front, vsize);
}
else
{
vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale,
actorPos, actorPos2, front, vsize);
}
}
void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data,
short* dataPtr, double shift, double scale,
int *actorPos, int *actorPos2, int front, int *vsize,
int)
{
vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale,
actorPos, actorPos2, front, vsize);
}
void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data,
unsigned short* dataPtr, double shift, double scale,
int *actorPos, int *actorPos2, int front, int *vsize,
int)
{
vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale,
actorPos, actorPos2, front, vsize);
}
//----------------------------------------------------------------------------
// Expects data to be X, Y, components
void vtkOpenGLImageMapper::RenderData(vtkViewport* viewport,
vtkImageData *data, vtkActor2D *actor)
{
void *ptr0;
double shift, scale;
vtkWindow* window = (vtkWindow *) viewport->GetVTKWindow();
if (!window)
{
vtkErrorMacro (<<"vtkOpenGLImageMapper::RenderData - no window set for viewport");
return;
}
// Make this window current. May have become not current due to
// data updates since the render started.
window->MakeCurrent();
shift = this->GetColorShift();
scale = this->GetColorScale();
ptr0 = data->GetScalarPointer(this->DisplayExtent[0],
this->DisplayExtent[2],
this->DisplayExtent[4]);
// push a 2D matrix on the stack
int *vsize = viewport->GetSize();
glMatrixMode( GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
if(viewport->GetIsPicking())
{
vtkgluPickMatrix(viewport->GetPickX(), viewport->GetPickY(),
1, 1, viewport->GetOrigin(), vsize);
}
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
// If picking then set up a model view matrix
if(viewport->GetIsPicking())
{
glOrtho(0,vsize[0] -1, 0, vsize[1] -1, 0, 1);
}
glDisable( GL_LIGHTING);
// Get the position of the text actor
int* actorPos =
actor->GetPositionCoordinate()->GetComputedViewportValue(viewport);
int* actorPos2 =
actor->GetPosition2Coordinate()->GetComputedViewportValue(viewport);
// negative positions will already be clipped to viewport
actorPos[0] += this->PositionAdjustment[0];
actorPos[1] += this->PositionAdjustment[1];
// if picking then only draw a polygon, since an image can not be picked
if(viewport->GetIsPicking())
{
int inMin0 = this->DisplayExtent[0];
int inMax0 = this->DisplayExtent[1];
int inMin1 = this->DisplayExtent[2];
int inMax1 = this->DisplayExtent[3];
float width = inMax0 - inMin0 + 1;
float height = inMax1 - inMin1 + 1;
float x1 = (2.0 * (GLfloat)(actorPos[0]) / vsize[0] - 1);
float y1 = (2.0 * (GLfloat)(actorPos[1]) / vsize[1] - 1);
glRectf(x1, y1, x1+width, y1+height);
// clean up and return
glMatrixMode( GL_PROJECTION);
glPopMatrix();
glMatrixMode( GL_MODELVIEW);
glPopMatrix();
glEnable( GL_LIGHTING);
return;
}
int front =
(actor->GetProperty()->GetDisplayLocation() == VTK_FOREGROUND_LOCATION);
#if defined(sparc) && defined(GL_VERSION_1_1)
glDisable(GL_BLEND);
#endif
switch (data->GetPointData()->GetScalars()->GetDataType())
{
vtkTemplateMacro(
vtkOpenGLImageMapperRender(this, data, static_cast<VTK_TT*>(ptr0),
shift, scale, actorPos, actorPos2, front, vsize,
1)
);
default:
vtkErrorMacro ( << "Unsupported image type: " << data->GetScalarType());
}
glMatrixMode( GL_PROJECTION);
glPopMatrix();
glMatrixMode( GL_MODELVIEW);
glPopMatrix();
glEnable( GL_LIGHTING);
#if defined(sparc) && defined(GL_VERSION_1_1)
glEnable(GL_BLEND);
#endif
}
void vtkOpenGLImageMapper::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
}