//----------------------------------------------------------------------------- // file: lightsabre.cpp // desc: rendering the light sabre (win32 version) // url: http://www.cs.princeton.edu/~gewang/projects/darth/ // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Brandon Braunstein (bbraunst@princeton.edu) // Douglas Corey Campbell (campbell@princeton.edu) // Candice Hebden (chebden@princeton.edu) // Paul Simbi (psimbi@princeton.edu) // // (thanks to 'turret' sample by Andreas Gustafsson) // date: autumn 2002 // version: 1.2 //----------------------------------------------------------------------------- #include #include #include #include #include #include #include #include //----------------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------------- LRESULT CALLBACK wnd_proc( HWND, UINT, WPARAM, LPARAM ); void on_initdialog( HWND hDlg ); void on_palettechanged( ); void set_dc_pixel_format( HDC hdc ); HPALETTE get_opengl_palette( HDC hdc ); void on_resize( GLsizei w, GLsizei h ); void init_gl( ); void render_loop( ); void render( ); struct LightState; void draw_sabre( LightState * state ); void draw_light( LightState * state ); void draw_hilt( LightState * state ); GLboolean load_texture( const char * name, GLuint * tex ); GLboolean checkTexDim( int x ); struct GeImageData; GLboolean ge_read_image( const char * filename, GeImageData * pImgData ); unsigned * ge_read_rgb( const char * name, int * width, int * height, int * comp ); //----------------------------------------------------------------------------- // name: struct LightState // desc: light sabre render state //----------------------------------------------------------------------------- struct LightState { float length; float max_length; float color[3]; double freq; double freq_data; unsigned layers; float intensity; LightState( float * c3 = NULL, float max_len = 1.0f, double f = 1.0, double fd = 0.0, unsigned lay = 8, float inten = 1.5 ) { // set the color if( c3 ) memcpy( color, c3, sizeof(color) ); else { color[0] = 1.0f; color[1] = .3f; color[2] = .3f; } length = max_length = max_len; layers = lay; freq = f; freq_data = fd; intensity = inten; } }; //----------------------------------------------------------------------------- // name: struct GeImageData // desc: holds basic image data //----------------------------------------------------------------------------- struct GeImageData { int width; int height; unsigned * bits; GeImageData( int w = 0, int h = 0, unsigned * p = 0 ) : width( w ), height( h ), bits( p ) { } }; //----------------------------------------------------------------------------- // global variables and #defines //----------------------------------------------------------------------------- // width and height of the window GLsizei g_width = 800; GLsizei g_height = 400; // whether to animate GLboolean g_rotate = GL_TRUE; // fill mode GLenum g_fillmode = GL_FILL; // light 0 position GLfloat g_light0_pos[4] = { 2.0f, 1.2f, 4.0f, 1.0f }; // light 1 parameters GLfloat g_light1_ambient[] = { .2f, .2f, .2f, 1.0f }; GLfloat g_light1_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat g_light1_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat g_light1_pos[4] = { -2.0f, 0.0f, -4.0f, 1.0f }; // texture and glu data GLUquadricObj * g_quadric = NULL; GeImageData g_imgData; GLuint g_img[100]; char g_classname[] = "Win32::Darth"; BOOL g_winActive = GL_TRUE; HPALETTE g_hpalette = NULL; HDC g_hDC = NULL; HGLRC g_hglrc = NULL; LightState g_light_state; char g_filename[128] = "darth.rgb"; float g_len_inc = 0.0f; //----------------------------------------------------------------------------- // name: print() // desc: ... //----------------------------------------------------------------------------- void print( const char * msg ) { MessageBox( NULL, msg, "Message!", MB_OK ); } //----------------------------------------------------------------------------- // name: WinMain() // desc: win32 entry point //----------------------------------------------------------------------------- int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { WNDCLASSEX wcex; HWND hwnd; MSG msg; // window class wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = ( WNDPROC )wnd_proc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon( hInstance, (LPCTSTR)IDI_APPLICATION ); wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = (HBRUSH)( COLOR_WINDOW+1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = g_classname; wcex.hIconSm = LoadIcon( wcex.hInstance, (LPCTSTR)IDI_APPLICATION ); // register the class RegisterClassEx( &wcex ); // create the window hwnd = CreateWindow( g_classname, g_classname, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, g_width, g_height, NULL, NULL, hInstance, NULL ); // check if (!hwnd) return GL_FALSE; // show the window ShowWindow( hwnd, nCmdShow ); // update the window UpdateWindow( hwnd ); // fast render loop while( GL_TRUE ) { if ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) { if ( !GetMessage(&msg, NULL, 0, 0) ) return msg.wParam; TranslateMessage(&msg); DispatchMessage(&msg); } else if ( g_winActive == GL_TRUE ) render_loop(); else WaitMessage(); } return 0; } //----------------------------------------------------------------------------- // name: wnd_proc() // desc: ... //----------------------------------------------------------------------------- LRESULT CALLBACK wnd_proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch( uMsg ) { case WM_CREATE: on_initdialog( hwnd ); init_gl( ); break; case WM_ACTIVATEAPP: g_winActive = ( wParam != 0 ); break; case WM_SIZE: // event - window resized on_resize( LOWORD( lParam ), HIWORD( lParam ) ); break; case WM_CLOSE: PostQuitMessage( 0 ); break; case WM_PALETTECHANGED: // This window may set the palette, even though it is not the // currently active window. // Don't do anything if the palette does not exist, or if // this is the window that changed the palette. if( g_hpalette && (HWND)wParam != hwnd ) on_palettechanged(); break; case WM_LBUTTONDOWN: switch( wParam ) { case MK_LBUTTON: if( g_light_state.length == g_light_state.max_length ) g_len_inc = -.05f; else g_len_inc = .05f; break; } break; default: return DefWindowProc( hwnd, uMsg, wParam, lParam ); } return 0; } //----------------------------------------------------------------------------- // name: on_initdialog // desc: initialization for dialog //----------------------------------------------------------------------------- void on_initdialog( HWND hwnd ) { g_hDC = GetDC( hwnd ); // Select the pixel format set_dc_pixel_format( g_hDC ); // get opengl palette g_hpalette = get_opengl_palette( g_hDC ); // Create the rendering context and make it current g_hglrc = wglCreateContext( g_hDC ); wglMakeCurrent( g_hDC, g_hglrc ); g_winActive = GL_TRUE; } //----------------------------------------------------------------------------- // name: on_palettechanged( ) // desc: handles palette //----------------------------------------------------------------------------- void on_palettechanged() { if( !g_hpalette ) return; // select palette to the device context SelectPalette( g_hDC, g_hpalette, GL_FALSE ); // map entries to system pal RealizePalette( g_hDC ); // remap the current colors to the newly realized palette UpdateColors( g_hDC ); } //----------------------------------------------------------------------------- // name: init_gl( ) // desc: opengl //----------------------------------------------------------------------------- void init_gl( ) { // set the GL clear color - use when the color buffer is cleared glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // set the shading model to 'smooth' glShadeModel( GL_SMOOTH ); // enable depth glEnable( GL_DEPTH_TEST ); // set the front faces of polygons glFrontFace( GL_CCW ); // set fill mode glPolygonMode( GL_FRONT_AND_BACK, g_fillmode ); // enable lighting glEnable( GL_LIGHTING ); // enable lighting for front glLightModeli( GL_FRONT_AND_BACK, GL_TRUE ); // material have diffuse and ambient lighting glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); // enable color glEnable( GL_COLOR_MATERIAL ); // initialize our sphere g_quadric = gluNewQuadric( ); gluQuadricNormals( g_quadric, ( GLenum )GLU_SMOOTH ); gluQuadricTexture( g_quadric, GL_TRUE ); // set texture state glPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); if( !load_texture( "light.rgb", &g_img[0] ) ) exit(1); if( !load_texture( "hilt.rgb", &g_img[1] ) ) exit(1); // enable light 0 glEnable( GL_LIGHT0 ); // setup and enable light 1 glLightfv( GL_LIGHT1, GL_AMBIENT, g_light1_ambient ); glLightfv( GL_LIGHT1, GL_DIFFUSE, g_light1_diffuse ); glLightfv( GL_LIGHT1, GL_SPECULAR, g_light1_specular ); glEnable( GL_LIGHT1 ); // light state g_light_state.length = 0.0f; g_light_state.freq = 1.5; printf( "-------------------------------------------------------\n" ); printf( "light sabre sample\n" ); printf( "project: darth\n" ); printf( "url: http://www.cs.princeton.edu/~gewang/projects/darth/\n" ); printf( "\n" ); printf( "author: Ge Wang (gewang@cs.princeton.edu)\n" ); printf( " Perry R. Cook (prc@cs.princeton.edu)\n" ); printf( " Brandon Braunstein (bbraunst@princeton.edu)\n" ); printf( " Douglas Corey Campbell (campbell@princeton.edu)\n" ); printf( " Candice Hebden (chebden@princeton.edu)\n" ); printf( " Paul Simbi (psimbi@princeton.edu)\n" ); printf( " (thanks to 'turret' sample by Andreas Gustafsson)\n" ); printf( "\n" ); printf( "press [L/R] mouse button to activate/deactivate\n" ); printf( "-------------------------------------------------------\n" ); printf( "\n" ); } //----------------------------------------------------------------------------- // name: on_resize( ) // desc: called when window size changes //----------------------------------------------------------------------------- void on_resize( GLsizei w, GLsizei h ) { // save the new window size g_width = w; g_height = h; // map the view port to the client area glViewport( 0, 0, w, h ); // set the matrix mode to project glMatrixMode( GL_PROJECTION ); // load the identity matrix glLoadIdentity( ); // create the viewing frustum gluPerspective( 70.0, (GLfloat) w / (GLfloat) h, .1, 300.0 ); // set the matrix mode to modelview glMatrixMode( GL_MODELVIEW ); // load the identity matrix glLoadIdentity( ); // position the view point gluLookAt( 0.0f, -2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); // set the position of the lights glLightfv( GL_LIGHT0, GL_POSITION, g_light0_pos ); } //----------------------------------------------------------------------------- // name: render_loop( ) // desc: callback function invoked to draw the client area //----------------------------------------------------------------------------- void render_loop( ) { if( g_hDC == NULL ) return; // clear the color and depth buffers glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // save the current matrix state, so transformation will // not persist across displayFunc calls, since we // will do a glPopMatrix() at the end of this function glPushMatrix( ); // render the scene render( ); // pop the matrix glPopMatrix(); // flush glFlush( ); // swap the double buffer SwapBuffers( g_hDC ); } //----------------------------------------------------------------------------- // name: render( ) // desc: render the scene //----------------------------------------------------------------------------- void render() { static float x = 0.0f; x += .001f; // update light state g_light_state.length += g_len_inc; if( g_light_state.length > g_light_state.max_length ) { g_light_state.length = g_light_state.max_length; g_len_inc = 0.0f; } else if( g_light_state.length < 0.0f ) { g_light_state.length = 0.0f; g_len_inc = 0.0f; } glRotatef( 65.0f, 1.0f, 0.0f, 0.0f ); glTranslatef( 0.0f, -.7f, 0.0f ); glRotatef( (float)cos(x) * 360.0f, 0.0f, -1.0f, -1.0f ); draw_sabre( &g_light_state ); } //----------------------------------------------------------------------------- // Name: draw_sabre( ) // Desc: draw light sabre //----------------------------------------------------------------------------- void draw_sabre( LightState * ls ) { glPushMatrix(); draw_hilt( ls ); draw_light( ls ); glPopMatrix(); } //----------------------------------------------------------------------------- // Name: draw_light( ) // Desc: draw light beam //----------------------------------------------------------------------------- void draw_light( LightState * ls ) { unsigned i; float intensity = ls->intensity + (float)cos(ls->freq_data) * .2f; float factor = ls->layers / intensity; ls->freq_data += 1.5; glColor3f( 1.0f / factor, .3f / factor, .2f / factor ); glPushMatrix( ); glEnable( GL_NORMALIZE ); glDepthMask( 0 ); glDisable( GL_LIGHTING ); glEnable( GL_BLEND ); glBlendFunc( GL_ONE, GL_ONE ); glBindTexture( GL_TEXTURE_2D, g_img[0] ); glEnable( GL_TEXTURE_2D ); glScalef( .07f, 1.0f, .07f ); for( i = 0; i < ls->layers; i++ ) { glBegin( GL_QUADS ); glTexCoord2f( 0, 0 ); glVertex3f( -1.0f, 0.0f, 0.0f ); glTexCoord2f( 0, 1 ); glVertex3f( -1.0f, 2.0f * ls->length, 0.0f ); glTexCoord2f( 1, 1 ); glVertex3f( 1.0f, 2.0f * ls->length, 0.0f ); glTexCoord2f( 1, 0 ); glVertex3f( 1.0f, 0.0f, 0.0f ); glEnd(); glRotatef( 180.0f / ls->layers, 0.0f, 1.0f, 0.0f ); } glDisable( GL_TEXTURE_2D ); glEnable( GL_LIGHTING ); glDisable( GL_BLEND ); glDepthMask( 1 ); glDisable( GL_NORMALIZE ); glPopMatrix(); } //----------------------------------------------------------------------------- // Name: draw_hilt( ) // Desc: draw light beam //----------------------------------------------------------------------------- void draw_hilt( LightState * ls ) { glPushMatrix(); glColor3f( .8f, .8f, .8f ); glRotatef( 90, 1.0f, 0.0f, 0.0f ); glBindTexture( GL_TEXTURE_2D, g_img[1] ); glEnable( GL_TEXTURE_2D ); gluCylinder( g_quadric, .045, .045, .06, 10, 1 ); glTranslatef( 0.0f, 0.0f, 0.015f ); gluCylinder( g_quadric, .035, .035, .3, 10, 1 ); glTranslatef( 0.0f, 0.0f, 0.285f ); gluCylinder( g_quadric, .04, .04, .06, 10, 1 ); glDisable( GL_TEXTURE_2D ); glPopMatrix(); } //----------------------------------------------------------------------------- // name: set_dc_pixel_format // desc: select the pixel format for a given device context //----------------------------------------------------------------------------- void set_dc_pixel_format( HDC hDC ) { int nPixelFormat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Size of this structure 1, // Version of this structure PFD_DRAW_TO_WINDOW | // Draw to Window (not to bitmap) PFD_SUPPORT_OPENGL | // Support OpenGL calls in window PFD_DOUBLEBUFFER, // Double buffered PFD_TYPE_RGBA, // RGBA Color mode 32, // Want 24bit color 0,0,0,0,0,0, // Not used to select mode 0,0, // Not used to select mode 0,0,0,0,0, // Not used to select mode 16, // Size of depth buffer 0, // Not used to select mode 0, // Not used to select mode PFD_MAIN_PLANE, // Draw in main plane 0, // Not used to select mode 0,0,0 }; // Not used to select mode // Choose a pixel format that best matches that described in pfd nPixelFormat = ChoosePixelFormat(hDC, &pfd); // Set the pixel format for the device context SetPixelFormat(hDC, nPixelFormat, &pfd); } //----------------------------------------------------------------------------- // name: get_opengl_palette( ) // f necessary, creates a 3-3-2 palette for the device context listed. //----------------------------------------------------------------------------- HPALETTE get_opengl_palette( HDC hDC ) { HPALETTE hRetPal = NULL; // Handle to palette to be created PIXELFORMATDESCRIPTOR pfd; // Pixel Format Descriptor LOGPALETTE *pPal; // Pointer to memory for logical palette int nPixelFormat; // Pixel format index int nColors; // Number of entries in palette int i; // Counting variable BYTE RedRange,GreenRange,BlueRange; // Range for each color entry (7,7,and 3) // Get the pixel format index and retrieve the pixel format description nPixelFormat = GetPixelFormat( hDC ); DescribePixelFormat( hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd ); // Does this pixel format require a palette? If not, do not create a // palette and just return NULL if(!(pfd.dwFlags & PFD_NEED_PALETTE)) return NULL; // Number of entries in palette. 8 bits yeilds 256 entries nColors = 1 << pfd.cColorBits; // Allocate space for a logical palette structure plus all the palette entries pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +nColors*sizeof(PALETTEENTRY)); // Fill in palette header pPal->palVersion = 0x300; // Windows 3.0 pPal->palNumEntries = nColors; // table size // Build mask of all 1's. This creates a number represented by having // the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and // pfd.cBlueBits. RedRange = (1 << pfd.cRedBits) -1; GreenRange = (1 << pfd.cGreenBits) - 1; BlueRange = (1 << pfd.cBlueBits) -1; // Loop through all the palette entries for(i = 0; i < nColors; i++) { // Fill in the 8-bit equivalents for each component pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) & RedRange; pPal->palPalEntry[i].peRed = (unsigned char)( (double) pPal->palPalEntry[i].peRed * 255.0 / RedRange); pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) & GreenRange; pPal->palPalEntry[i].peGreen = (unsigned char)( (double)pPal->palPalEntry[i].peGreen * 255.0 / GreenRange); pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) & BlueRange; pPal->palPalEntry[i].peBlue = (unsigned char)( (double)pPal->palPalEntry[i].peBlue * 255.0 / BlueRange); pPal->palPalEntry[i].peFlags = (unsigned char) NULL; } // Create the palette hRetPal = CreatePalette( pPal ); // Go ahead and select and realize the palette for this device context SelectPalette( hDC, hRetPal, GL_FALSE ); RealizePalette( hDC ); // Free the memory used for the logical palette structure free( pPal ); // Return the handle to the new palette return hRetPal; } //----------------------------------------------------------------------------- // name: load_texture() // desc: ... //----------------------------------------------------------------------------- GLboolean load_texture( const char * name, GLuint * tex ) { static int x = 0; static char buffer[1024]; // read the texture if( !ge_read_image( name, &g_imgData ) ) { sprintf( buffer, "couldn't open file '%s'...\n", name ); print( buffer ); return GL_FALSE; } // check dim if( !checkTexDim( g_imgData.width ) || !checkTexDim( g_imgData.height ) ) { sprintf( buffer, "img dimensions: %dx%d\n", g_imgData.width, g_imgData.height ); strcat( buffer, "must use image file with dimensions that are powers of 2\n" ); print( buffer ); return GL_FALSE; } // generate OpenGL texture glGenTextures( ++x, tex ); glBindTexture( GL_TEXTURE_2D, *tex ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, g_imgData.width, g_imgData.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, g_imgData.bits ); return GL_TRUE; } //----------------------------------------------------------------------------- // name: checkTexDim( ) // desc: checks to see if a dim is a valid opengl texture dimension //----------------------------------------------------------------------------- GLboolean checkTexDim( int dim ) { if( dim < 0 ) return false; int i, count = 0; // count bits for( i = 0; i < 31; i++ ) if( dim & ( 0x1 << i ) ) count++; // this is true only if dim is power of 2 return count == 1; } //----------------------------------------------------------------------------- // Name: ge_read_image( ) // Desc: reads an RGB file into pImgData //----------------------------------------------------------------------------- GLboolean ge_read_image( const char * filename, GeImageData * pImgData ) { int c; if( !filename || !pImgData ) return false; // zero out the memory memset( pImgData, 0, sizeof( GeImageData ) ); pImgData->bits = ge_read_rgb( filename, &pImgData->width, &pImgData->height, &c ); return ( pImgData->bits != 0 ); } //----------------------------------------------------------------------------- /* texture loading - by David Blythe, SGI */ /* a simplistic routine for reading an SGI .rgb image file. */ //----------------------------------------------------------------------------- void bwtorgba(unsigned char *b,unsigned char *l,int n) { while(n--) { l[0] = *b; l[1] = *b; l[2] = *b; l[3] = 0xff; l += 4; b++; } } void rgbtorgba(unsigned char *r,unsigned char *g,unsigned char *b, unsigned char *l,int n) { while(n--) { l[0] = r[0]; l[1] = g[0]; l[2] = b[0]; l[3] = 0xff; l += 4; r++; g++; b++; } } void rgbatorgba(unsigned char *r,unsigned char *g,unsigned char *b, unsigned char *a,unsigned char *l,int n) { while(n--) { l[0] = r[0]; l[1] = g[0]; l[2] = b[0]; l[3] = a[0]; l += 4; r++; g++; b++; a++; } } typedef struct _ImageRec { unsigned short imagic; unsigned short type; unsigned short dim; unsigned short xsize, ysize, zsize; unsigned int min, max; unsigned int wasteBytes; char name[80]; unsigned long colorMap; FILE *file; unsigned char *tmp, *tmpR, *tmpG, *tmpB; unsigned long rleEnd; unsigned int *rowStart; int *rowSize; } ImageRec; static void ConvertShort(unsigned short *array, unsigned int length) { unsigned short b1, b2; unsigned char *ptr; ptr = (unsigned char *)array; while (length--) { b1 = *ptr++; b2 = *ptr++; *array++ = (b1 << 8) | (b2); } } static void ConvertUint(unsigned *array, unsigned int length) { unsigned int b1, b2, b3, b4; unsigned char *ptr; ptr = (unsigned char *)array; while (length--) { b1 = *ptr++; b2 = *ptr++; b3 = *ptr++; b4 = *ptr++; *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); } } static ImageRec *ImageOpen(const char *fileName) { union { int testWord; char testByte[4]; } endianTest; ImageRec *image; int swapFlag; int x; endianTest.testWord = 1; if (endianTest.testByte[0] == 1) { swapFlag = 1; } else { swapFlag = 0; } image = (ImageRec *)malloc(sizeof(ImageRec)); if (image == NULL) { fprintf(stderr, "Out of memory!\n"); exit(1); } if ((image->file = fopen(fileName, "rb")) == NULL) { perror(fileName); //exit(1); return NULL; } fread(image, 1, 12, image->file); if (swapFlag) { ConvertShort(&image->imagic, 6); } image->tmp = (unsigned char *)malloc(image->xsize*256); image->tmpR = (unsigned char *)malloc(image->xsize*256); image->tmpG = (unsigned char *)malloc(image->xsize*256); image->tmpB = (unsigned char *)malloc(image->xsize*256); if (image->tmp == NULL || image->tmpR == NULL || image->tmpG == NULL || image->tmpB == NULL) { fprintf(stderr, "Out of memory!\n"); exit(1); } if ((image->type & 0xFF00) == 0x0100) { x = image->ysize * image->zsize * (int) sizeof(unsigned); image->rowStart = (unsigned *)malloc(x); image->rowSize = (int *)malloc(x); if (image->rowStart == NULL || image->rowSize == NULL) { fprintf(stderr, "Out of memory!\n"); exit(1); } image->rleEnd = 512 + (2 * x); fseek(image->file, 512, SEEK_SET); fread(image->rowStart, 1, x, image->file); fread(image->rowSize, 1, x, image->file); if (swapFlag) { ConvertUint(image->rowStart, x/(int) sizeof(unsigned)); ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int)); } } return image; } static void ImageClose(ImageRec *image) { fclose(image->file); free(image->tmp); free(image->tmpR); free(image->tmpG); free(image->tmpB); free(image); } static void ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) { unsigned char *iPtr, *oPtr, pixel; int count; if ((image->type & 0xFF00) == 0x0100) { fseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET); fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize], image->file); iPtr = image->tmp; oPtr = buf; for (;;) { pixel = *iPtr++; count = (int)(pixel & 0x7F); if (!count) { return; } if (pixel & 0x80) { while (count--) { *oPtr++ = *iPtr++; } } else { pixel = *iPtr++; while (count--) { *oPtr++ = pixel; } } } } else { fseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize), SEEK_SET); fread(buf, 1, image->xsize, image->file); } } unsigned * ge_read_rgb( const char * name, int * width, int * height, int * components) { unsigned *base, *lptr; unsigned char *rbuf, *gbuf, *bbuf, *abuf; ImageRec *image; int y; image = ImageOpen(name); if(!image) return NULL; (*width)=image->xsize; (*height)=image->ysize; (*components)=image->zsize; base = (unsigned *)malloc(image->xsize*image->ysize*sizeof(unsigned)); rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); if(!base || !rbuf || !gbuf || !bbuf) return NULL; lptr = base; for(y=0; yysize; y++) { if(image->zsize>=4) { ImageGetRow(image,rbuf,y,0); ImageGetRow(image,gbuf,y,1); ImageGetRow(image,bbuf,y,2); ImageGetRow(image,abuf,y,3); rgbatorgba(rbuf,gbuf,bbuf,abuf, (unsigned char *)lptr,image->xsize); lptr += image->xsize; } else if(image->zsize==3) { ImageGetRow(image,rbuf,y,0); ImageGetRow(image,gbuf,y,1); ImageGetRow(image,bbuf,y,2); rgbtorgba(rbuf,gbuf,bbuf,(unsigned char *)lptr,image->xsize); lptr += image->xsize; } else { ImageGetRow(image,rbuf,y,0); bwtorgba(rbuf,(unsigned char *)lptr,image->xsize); lptr += image->xsize; } } ImageClose(image); free(rbuf); free(gbuf); free(bbuf); free(abuf); return (unsigned *) base; }