#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 = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif mpVideoSurface = SDL_CreateRGBSurface( SDL_HWSURFACE ,mDim[0] // width ,mDim[1] ,8 ,rmask ,gmask ,bmask ,amask ); return (true); } // 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(); } // 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) { 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; // 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(); } /** * 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); }