rendered paste body#include "PhotoBox.h"
// C'tor.
PhotoBox::PhotoBox()
{
mpScreen = NULL;
mbDone = false;
mbWritten = false;
}
// D'tor.
PhotoBox::~PhotoBox()
{
}
int PhotoBox::ResizeWindow(int iWidth, int iHeight)
{
return 0;
/* Height / width ration */
GLfloat ratio;
/* Protect against a divide by zero */
if ( iHeight == 0 )
iHeight = 1;
ratio = ( GLfloat )iWidth / ( GLfloat )iHeight;
/* Setup our viewport. */
glViewport( 0, 0, ( GLsizei )iWidth, ( GLsizei )iHeight );
/* change to the projection matrix and set our viewing volume. */
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
/* Set our perspective */
gluPerspective( 45.0f, ratio, 0.1f, 100.0f );
/* Make sure we're chaning the model view and not the projection */
glMatrixMode( GL_MODELVIEW );
/* Reset The View */
glLoadIdentity( );
return (1);
}
/**
* Setup SDL
*
* @version 0.1 [2006.10.07]
*/
bool PhotoBox::Init()
{
if (!InitSDL())
return (false);
if (!InitCamera())
return (false);
//if (!InitOpenGL())
// return (false);
return (true);
}
// Initialize OpenGL
bool PhotoBox::InitOpenGL()
{
// Sets up OpenGL double buffering
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
glViewport(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,1,0,1,0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
// Really Nice Perspective Calculations
//glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
//ResizeWindow(SCREEN_WIDTH, SCREEN_HEIGHT);
return (true);
}
// Initialize SDL
bool PhotoBox::InitSDL()
{
int result = 0;
// Initialize SDL's subsystems - in this case, only video.
if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
{
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
// Video flag info.
int videoFlags = 0;
//videoFlags |= SDL_OPENGL;
// Store the palette in hardware
videoFlags |= SDL_HWPALETTE;
// Enable window resizing
videoFlags |= SDL_RESIZABLE;
//videoFlags |= SDL_FULLSCREEN;
// Get information from the videoinfo.
const SDL_VideoInfo *videoInfo;
videoInfo = SDL_GetVideoInfo( );
if ( !videoInfo )
{
fprintf( stderr, "Video query failed: %s\n",
SDL_GetError( ) );
return (false);
}
// HW supported?
if ( videoInfo->hw_available )
videoFlags |= SDL_HWSURFACE;
else
videoFlags |= SDL_SWSURFACE;
// This checks if hardware blits can be done
if ( videoInfo->blit_hw )
videoFlags |= SDL_HWACCEL;
// Create the main sdl surface
mpScreen = SDL_SetVideoMode(
SCREEN_WIDTH
,SCREEN_HEIGHT
,SCREEN_BPP
,videoFlags
);
if ( mpScreen == NULL )
{
return (false);
}
return (true);
}
// Initialize the camera using ARToolkit
bool PhotoBox::InitCamera()
{
// Initialize the ARToolKit video subsystem
int result = 0;
char *vconf = "camera.xml";
result = arVideoOpen(vconf);
if (result == -1)
{
return (false);
}
// This function returns the size of the captured video frame, in pixels.
result = arVideoInqSize( &mDim[0], &mDim[1] );
if (result == -1)
{
return (false);
}
// Start capturing.
result = arVideoCapStart();
if (result == -1)
{
return (false);
}
mTexBuf = new unsigned char[mDim[0] * mDim[1] * 3];
// Create a video surface for the camera
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0x00ff0000;
gmask = 0x0000ff00;
bmask = 0xff000000;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
mpVideoSurface = SDL_CreateRGBSurface(
SDL_HWSURFACE
,mDim[0] // width
,mDim[1]
,32
,rmask
,gmask
,bmask
,amask
);
return (true);
}
// Render a camera frame.
void PhotoBox::RenderCamera()
{
ARUint8* buffer = NULL;
buffer = arVideoGetImage();
static unsigned char** ss_rows;
if (buffer != NULL)
{
int y_offset = 0;
unsigned char c;
int pixel = 0;
for (int y = 0; y < mDim[1]; ++y)
{
y_offset = y * mDim[0] * 3;
for (int x = 0; x < mDim[0]; ++x)
{
// The << 2 multiplies the position by 4 moving
// it to the correct location of the Uint8 buffer.
c = buffer[ (((y) * mDim[0]+(x)) << 2) + 0];
mTexBuf[y_offset + x * 3 + 0] = c;
c = buffer[ (((y) * mDim[0]+(x)) << 2) + 1];
mTexBuf[y_offset + x * 3 + 1] = c;
c = buffer[ (((y) * mDim[0]+(x)) << 2) + 2];
mTexBuf[y_offset + x * 3 + 2] = c;
}
}
if (!mbWritten)
{
WritePNG("test.png",mTexBuf, mDim[0], mDim[1]);
// LOG("Image written.\n");
mbWritten = true;
}
// Draw the image to the screen
SDL_Rect dstrect;
//mpVideoSurface->pixels = mTexBuf;
mpVideoSurface->pixels = buffer;
dstrect.x = (mpScreen->w-mpVideoSurface->w)/2;
dstrect.y = (mpScreen->h-mpVideoSurface->h)/2;
dstrect.w = mpVideoSurface->w;
dstrect.h = mpVideoSurface->h;
if ( SDL_BlitSurface(mpVideoSurface, NULL, mpScreen, &dstrect) < 0 ) {
SDL_FreeSurface(mpVideoSurface);
}
}
arVideoCapNext();
}
SDL_Surface *PhotoBox::CreateCompatibleSurface( int width, int height )
{
SDL_Surface *screen = SDL_GetVideoSurface();
SDL_PixelFormat *PixelFormat = screen->format;
int flags = (screen->flags & SDL_HWSURFACE);
SDL_Surface *surf;
surf = SDL_CreateRGBSurface( flags, width, height,
PixelFormat->BitsPerPixel,
PixelFormat->Rmask, PixelFormat->Gmask,
PixelFormat->Bmask, PixelFormat->Amask
);
if ( !surf ) return NULL;
if ( PixelFormat->palette && surf->format->palette )
{
memcpy( surf->format->palette->colors,
PixelFormat->palette->colors,
PixelFormat->palette->ncolors*sizeof(SDL_Color)
);
surf->format->palette->ncolors = PixelFormat->palette->ncolors;
}
return surf;
}
// Helper function which writes a PNG image from a RGB color array.
int PhotoBox::WritePNG(char *fn, unsigned char *raster, unsigned int w, unsigned int h)
{
FILE *fp;
png_structp png;
png_infop info;
png_bytepp row_pointers;
int i;
/* create file */
fp = fopen (fn, "wb");
if (!fp) {
// xe_msg (1, "Can not create %s:\n%s", fn, syserrstr());
return (-1);
}
/* build list of pointers to each row */
row_pointers = (png_bytepp) malloc (h * sizeof(png_bytep));
if (!row_pointers) {
// xe_msg (1, "Can not malloc %d PNG row pointers", h);
fclose (fp);
return (-1);
}
for (i = 0; i < h; i++)
row_pointers[i] = raster + i*(w*3);
/* write png */
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
info = png_create_info_struct (png);
if (setjmp (png_jmpbuf (png))) {
// xe_msg (1, "PNG error");
png_destroy_write_struct (&png, &info);
free (row_pointers);
fclose (fp);
return (-1);
}
png_init_io(png, fp);
png_set_IHDR (
png // png struct pointer
,info // header info
,w // width
,h // height
,8 // bit depth
,PNG_COLOR_TYPE_RGB // color_type
,PNG_INTERLACE_NONE // interlace type
,PNG_COMPRESSION_TYPE_DEFAULT // compresssion type
,PNG_FILTER_TYPE_DEFAULT // filter type
);
png_write_info (png, info);
png_write_image (png, row_pointers);
png_write_end (png, info);
png_destroy_write_struct (&png, &info);
free (row_pointers);
/* check for io error */
if (ferror(fp)) {
// xe_msg (1, "Write error %s:\n%s", fn, syserrstr());
fclose (fp);
return (-1);
}
/* ok */
fclose (fp);
return (0);
}
/**
* Execute the main loop, and capture events.
*
* @version 0.1 [2006.10.07]
*/
int PhotoBox::Exec()
{
while (!mbDone)
{
// Render stuff
Render();
// Poll for events, and handle the ones we care about.
SDL_Event event;
while (SDL_PollEvent(&event))
{
// Handle input if the console is used.
switch (event.type)
{
case SDL_KEYDOWN:
break;
case SDL_KEYUP:
// If escape is pressed, return (and thus, quit)
if (event.key.keysym.sym == SDLK_ESCAPE)
return 0;
break;
case SDL_QUIT:
{
ShutDown();
mbDone = true;
break;
}
}
}
}
return(1);
}
/**
* Renders the screen.
*
* @version 0.1 [2006.10.07]
*/
void PhotoBox::Render()
{
// glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// DisplayBMP("image.bmp");
RenderCamera();
SDL_UpdateRect(mpScreen, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
//SDL_GL_SwapBuffers();
}
/**
* Shuts down SDL, OGLConsole, OpenGL
*
* @version 0.1 [2006.10.07]
*/
void PhotoBox::ShutDown()
{
// Cleanup SDL
SDL_Quit( );
}
// From SDL documentation, for testing purpose.
void PhotoBox::DisplayBMP(char *pFile)
{
SDL_Surface *image;
/* Load the BMP file into a surface */
image = SDL_LoadBMP(pFile);
if (image == NULL) {
fprintf(stderr, "Couldn't load %s: %s\n", pFile, SDL_GetError());
// LOG("File error");
return;
}
/* Blit onto the screen surface */
if(SDL_BlitSurface(image, NULL, mpScreen, NULL) < 0)
fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError());
SDL_UpdateRect(mpScreen, 0, 0, image->w, image->h);
/* Free the allocated BMP surface */
SDL_FreeSurface(image);
}