Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

tr_image.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // tr_image.c
00023 #include "tr_local.h"
00024 
00025 /*
00026  * Include file for users of JPEG library.
00027  * You will need to have included system headers that define at least
00028  * the typedefs FILE and size_t before you can include jpeglib.h.
00029  * (stdio.h is sufficient on ANSI-conforming systems.)
00030  * You may also wish to include "jerror.h".
00031  */
00032 
00033 #define JPEG_INTERNALS
00034 #include "../jpeg-6/jpeglib.h"
00035 
00036 
00037 static void LoadBMP( const char *name, byte **pic, int *width, int *height );
00038 static void LoadTGA( const char *name, byte **pic, int *width, int *height );
00039 static void LoadJPG( const char *name, byte **pic, int *width, int *height );
00040 
00041 static byte          s_intensitytable[256];
00042 static unsigned char s_gammatable[256];
00043 
00044 int     gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
00045 int     gl_filter_max = GL_LINEAR;
00046 
00047 #define FILE_HASH_SIZE      1024
00048 static  image_t*        hashTable[FILE_HASH_SIZE];
00049 
00050 /*
00051 ** R_GammaCorrect
00052 */
00053 void R_GammaCorrect( byte *buffer, int bufSize ) {
00054     int i;
00055 
00056     for ( i = 0; i < bufSize; i++ ) {
00057         buffer[i] = s_gammatable[buffer[i]];
00058     }
00059 }
00060 
00061 typedef struct {
00062     char *name;
00063     int minimize, maximize;
00064 } textureMode_t;
00065 
00066 textureMode_t modes[] = {
00067     {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
00068     {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
00069     {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
00070     {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
00071     {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
00072     {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
00073 };
00074 
00075 /*
00076 ================
00077 return a hash value for the filename
00078 ================
00079 */
00080 static long generateHashValue( const char *fname ) {
00081     int     i;
00082     long    hash;
00083     char    letter;
00084 
00085     hash = 0;
00086     i = 0;
00087     while (fname[i] != '\0') {
00088         letter = tolower(fname[i]);
00089         if (letter =='.') break;                // don't include extension
00090         if (letter =='\\') letter = '/';        // damn path names
00091         hash+=(long)(letter)*(i+119);
00092         i++;
00093     }
00094     hash &= (FILE_HASH_SIZE-1);
00095     return hash;
00096 }
00097 
00098 /*
00099 ===============
00100 GL_TextureMode
00101 ===============
00102 */
00103 void GL_TextureMode( const char *string ) {
00104     int     i;
00105     image_t *glt;
00106 
00107     for ( i=0 ; i< 6 ; i++ ) {
00108         if ( !Q_stricmp( modes[i].name, string ) ) {
00109             break;
00110         }
00111     }
00112 
00113     // hack to prevent trilinear from being set on voodoo,
00114     // because their driver freaks...
00115     if ( i == 5 && glConfig.hardwareType == GLHW_3DFX_2D3D ) {
00116         ri.Printf( PRINT_ALL, "Refusing to set trilinear on a voodoo.\n" );
00117         i = 3;
00118     }
00119 
00120 
00121     if ( i == 6 ) {
00122         ri.Printf (PRINT_ALL, "bad filter name\n");
00123         return;
00124     }
00125 
00126     gl_filter_min = modes[i].minimize;
00127     gl_filter_max = modes[i].maximize;
00128 
00129     // change all the existing mipmap texture objects
00130     for ( i = 0 ; i < tr.numImages ; i++ ) {
00131         glt = tr.images[ i ];
00132         if ( glt->mipmap ) {
00133             GL_Bind (glt);
00134             qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
00135             qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
00136         }
00137     }
00138 }
00139 
00140 /*
00141 ===============
00142 R_SumOfUsedImages
00143 ===============
00144 */
00145 int R_SumOfUsedImages( void ) {
00146     int total;
00147     int i;
00148 
00149     total = 0;
00150     for ( i = 0; i < tr.numImages; i++ ) {
00151         if ( tr.images[i]->frameUsed == tr.frameCount ) {
00152             total += tr.images[i]->uploadWidth * tr.images[i]->uploadHeight;
00153         }
00154     }
00155 
00156     return total;
00157 }
00158 
00159 /*
00160 ===============
00161 R_ImageList_f
00162 ===============
00163 */
00164 void R_ImageList_f( void ) {
00165     int     i;
00166     image_t *image;
00167     int     texels;
00168     const char *yesno[] = {
00169         "no ", "yes"
00170     };
00171 
00172     ri.Printf (PRINT_ALL, "\n      -w-- -h-- -mm- -TMU- -if-- wrap --name-------\n");
00173     texels = 0;
00174 
00175     for ( i = 0 ; i < tr.numImages ; i++ ) {
00176         image = tr.images[ i ];
00177 
00178         texels += image->uploadWidth*image->uploadHeight;
00179         ri.Printf (PRINT_ALL,  "%4i: %4i %4i  %s   %d   ",
00180             i, image->uploadWidth, image->uploadHeight, yesno[image->mipmap], image->TMU );
00181         switch ( image->internalFormat ) {
00182         case 1:
00183             ri.Printf( PRINT_ALL, "I    " );
00184             break;
00185         case 2:
00186             ri.Printf( PRINT_ALL, "IA   " );
00187             break;
00188         case 3:
00189             ri.Printf( PRINT_ALL, "RGB  " );
00190             break;
00191         case 4:
00192             ri.Printf( PRINT_ALL, "RGBA " );
00193             break;
00194         case GL_RGBA8:
00195             ri.Printf( PRINT_ALL, "RGBA8" );
00196             break;
00197         case GL_RGB8:
00198             ri.Printf( PRINT_ALL, "RGB8" );
00199             break;
00200         case GL_RGB4_S3TC:
00201             ri.Printf( PRINT_ALL, "S3TC " );
00202             break;
00203         case GL_RGBA4:
00204             ri.Printf( PRINT_ALL, "RGBA4" );
00205             break;
00206         case GL_RGB5:
00207             ri.Printf( PRINT_ALL, "RGB5 " );
00208             break;
00209         default:
00210             ri.Printf( PRINT_ALL, "???? " );
00211         }
00212 
00213         switch ( image->wrapClampMode ) {
00214         case GL_REPEAT:
00215             ri.Printf( PRINT_ALL, "rept " );
00216             break;
00217         case GL_CLAMP:
00218             ri.Printf( PRINT_ALL, "clmp " );
00219             break;
00220         default:
00221             ri.Printf( PRINT_ALL, "%4i ", image->wrapClampMode );
00222             break;
00223         }
00224         
00225         ri.Printf( PRINT_ALL, " %s\n", image->imgName );
00226     }
00227     ri.Printf (PRINT_ALL, " ---------\n");
00228     ri.Printf (PRINT_ALL, " %i total texels (not including mipmaps)\n", texels);
00229     ri.Printf (PRINT_ALL, " %i total images\n\n", tr.numImages );
00230 }
00231 
00232 //=======================================================================
00233 
00234 /*
00235 ================
00236 ResampleTexture
00237 
00238 Used to resample images in a more general than quartering fashion.
00239 
00240 This will only be filtered properly if the resampled size
00241 is greater than half the original size.
00242 
00243 If a larger shrinking is needed, use the mipmap function 
00244 before or after.
00245 ================
00246 */
00247 static void ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out,  
00248                             int outwidth, int outheight ) {
00249     int     i, j;
00250     unsigned    *inrow, *inrow2;
00251     unsigned    frac, fracstep;
00252     unsigned    p1[2048], p2[2048];
00253     byte        *pix1, *pix2, *pix3, *pix4;
00254 
00255     if (outwidth>2048)
00256         ri.Error(ERR_DROP, "ResampleTexture: max width");
00257                                 
00258     fracstep = inwidth*0x10000/outwidth;
00259 
00260     frac = fracstep>>2;
00261     for ( i=0 ; i<outwidth ; i++ ) {
00262         p1[i] = 4*(frac>>16);
00263         frac += fracstep;
00264     }
00265     frac = 3*(fracstep>>2);
00266     for ( i=0 ; i<outwidth ; i++ ) {
00267         p2[i] = 4*(frac>>16);
00268         frac += fracstep;
00269     }
00270 
00271     for (i=0 ; i<outheight ; i++, out += outwidth) {
00272         inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
00273         inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
00274         frac = fracstep >> 1;
00275         for (j=0 ; j<outwidth ; j++) {
00276             pix1 = (byte *)inrow + p1[j];
00277             pix2 = (byte *)inrow + p2[j];
00278             pix3 = (byte *)inrow2 + p1[j];
00279             pix4 = (byte *)inrow2 + p2[j];
00280             ((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
00281             ((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
00282             ((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
00283             ((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
00284         }
00285     }
00286 }
00287 
00288 /*
00289 ================
00290 R_LightScaleTexture
00291 
00292 Scale up the pixel values in a texture to increase the
00293 lighting range
00294 ================
00295 */
00296 void R_LightScaleTexture (unsigned *in, int inwidth, int inheight, qboolean only_gamma )
00297 {
00298     if ( only_gamma )
00299     {
00300         if ( !glConfig.deviceSupportsGamma )
00301         {
00302             int     i, c;
00303             byte    *p;
00304 
00305             p = (byte *)in;
00306 
00307             c = inwidth*inheight;
00308             for (i=0 ; i<c ; i++, p+=4)
00309             {
00310                 p[0] = s_gammatable[p[0]];
00311                 p[1] = s_gammatable[p[1]];
00312                 p[2] = s_gammatable[p[2]];
00313             }
00314         }
00315     }
00316     else
00317     {
00318         int     i, c;
00319         byte    *p;
00320 
00321         p = (byte *)in;
00322 
00323         c = inwidth*inheight;
00324 
00325         if ( glConfig.deviceSupportsGamma )
00326         {
00327             for (i=0 ; i<c ; i++, p+=4)
00328             {
00329                 p[0] = s_intensitytable[p[0]];
00330                 p[1] = s_intensitytable[p[1]];
00331                 p[2] = s_intensitytable[p[2]];
00332             }
00333         }
00334         else
00335         {
00336             for (i=0 ; i<c ; i++, p+=4)
00337             {
00338                 p[0] = s_gammatable[s_intensitytable[p[0]]];
00339                 p[1] = s_gammatable[s_intensitytable[p[1]]];
00340                 p[2] = s_gammatable[s_intensitytable[p[2]]];
00341             }
00342         }
00343     }
00344 }
00345 
00346 
00347 /*
00348 ================
00349 R_MipMap2
00350 
00351 Operates in place, quartering the size of the texture
00352 Proper linear filter
00353 ================
00354 */
00355 static void R_MipMap2( unsigned *in, int inWidth, int inHeight ) {
00356     int         i, j, k;
00357     byte        *outpix;
00358     int         inWidthMask, inHeightMask;
00359     int         total;
00360     int         outWidth, outHeight;
00361     unsigned    *temp;
00362 
00363     outWidth = inWidth >> 1;
00364     outHeight = inHeight >> 1;
00365     temp = ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 );
00366 
00367     inWidthMask = inWidth - 1;
00368     inHeightMask = inHeight - 1;
00369 
00370     for ( i = 0 ; i < outHeight ; i++ ) {
00371         for ( j = 0 ; j < outWidth ; j++ ) {
00372             outpix = (byte *) ( temp + i * outWidth + j );
00373             for ( k = 0 ; k < 4 ; k++ ) {
00374                 total = 
00375                     1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
00376                     2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
00377                     2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
00378                     1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] +
00379 
00380                     2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
00381                     4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
00382                     4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
00383                     2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] +
00384 
00385                     2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
00386                     4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
00387                     4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
00388                     2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] +
00389 
00390                     1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
00391                     2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
00392                     2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
00393                     1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k];
00394                 outpix[k] = total / 36;
00395             }
00396         }
00397     }
00398 
00399     Com_Memcpy( in, temp, outWidth * outHeight * 4 );
00400     ri.Hunk_FreeTempMemory( temp );
00401 }
00402 
00403 /*
00404 ================
00405 R_MipMap
00406 
00407 Operates in place, quartering the size of the texture
00408 ================
00409 */
00410 static void R_MipMap (byte *in, int width, int height) {
00411     int     i, j;
00412     byte    *out;
00413     int     row;
00414 
00415     if ( !r_simpleMipMaps->integer ) {
00416         R_MipMap2( (unsigned *)in, width, height );
00417         return;
00418     }
00419 
00420     if ( width == 1 && height == 1 ) {
00421         return;
00422     }
00423 
00424     row = width * 4;
00425     out = in;
00426     width >>= 1;
00427     height >>= 1;
00428 
00429     if ( width == 0 || height == 0 ) {
00430         width += height;    // get largest
00431         for (i=0 ; i<width ; i++, out+=4, in+=8 ) {
00432             out[0] = ( in[0] + in[4] )>>1;
00433             out[1] = ( in[1] + in[5] )>>1;
00434             out[2] = ( in[2] + in[6] )>>1;
00435             out[3] = ( in[3] + in[7] )>>1;
00436         }
00437         return;
00438     }
00439 
00440     for (i=0 ; i<height ; i++, in+=row) {
00441         for (j=0 ; j<width ; j++, out+=4, in+=8) {
00442             out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2;
00443             out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2;
00444             out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2;
00445             out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2;
00446         }
00447     }
00448 }
00449 
00450 
00451 /*
00452 ==================
00453 R_BlendOverTexture
00454 
00455 Apply a color blend over a set of pixels
00456 ==================
00457 */
00458 static void R_BlendOverTexture( byte *data, int pixelCount, byte blend[4] ) {
00459     int     i;
00460     int     inverseAlpha;
00461     int     premult[3];
00462 
00463     inverseAlpha = 255 - blend[3];
00464     premult[0] = blend[0] * blend[3];
00465     premult[1] = blend[1] * blend[3];
00466     premult[2] = blend[2] * blend[3];
00467 
00468     for ( i = 0 ; i < pixelCount ; i++, data+=4 ) {
00469         data[0] = ( data[0] * inverseAlpha + premult[0] ) >> 9;
00470         data[1] = ( data[1] * inverseAlpha + premult[1] ) >> 9;
00471         data[2] = ( data[2] * inverseAlpha + premult[2] ) >> 9;
00472     }
00473 }
00474 
00475 byte    mipBlendColors[16][4] = {
00476     {0,0,0,0},
00477     {255,0,0,128},
00478     {0,255,0,128},
00479     {0,0,255,128},
00480     {255,0,0,128},
00481     {0,255,0,128},
00482     {0,0,255,128},
00483     {255,0,0,128},
00484     {0,255,0,128},
00485     {0,0,255,128},
00486     {255,0,0,128},
00487     {0,255,0,128},
00488     {0,0,255,128},
00489     {255,0,0,128},
00490     {0,255,0,128},
00491     {0,0,255,128},
00492 };
00493 
00494 
00495 /*
00496 ===============
00497 Upload32
00498 
00499 ===============
00500 */
00501 extern qboolean charSet;
00502 static void Upload32( unsigned *data, 
00503                           int width, int height, 
00504                           qboolean mipmap, 
00505                           qboolean picmip, 
00506                             qboolean lightMap,
00507                           int *format, 
00508                           int *pUploadWidth, int *pUploadHeight )
00509 {
00510     int         samples;
00511     unsigned    *scaledBuffer = NULL;
00512     unsigned    *resampledBuffer = NULL;
00513     int         scaled_width, scaled_height;
00514     int         i, c;
00515     byte        *scan;
00516     GLenum      internalFormat = GL_RGB;
00517     float       rMax = 0, gMax = 0, bMax = 0;
00518 
00519     //
00520     // convert to exact power of 2 sizes
00521     //
00522     for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
00523         ;
00524     for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
00525         ;
00526     if ( r_roundImagesDown->integer && scaled_width > width )
00527         scaled_width >>= 1;
00528     if ( r_roundImagesDown->integer && scaled_height > height )
00529         scaled_height >>= 1;
00530 
00531     if ( scaled_width != width || scaled_height != height ) {
00532         resampledBuffer = ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 );
00533         ResampleTexture (data, width, height, resampledBuffer, scaled_width, scaled_height);
00534         data = resampledBuffer;
00535         width = scaled_width;
00536         height = scaled_height;
00537     }
00538 
00539     //
00540     // perform optional picmip operation
00541     //
00542     if ( picmip ) {
00543         scaled_width >>= r_picmip->integer;
00544         scaled_height >>= r_picmip->integer;
00545     }
00546 
00547     //
00548     // clamp to minimum size
00549     //
00550     if (scaled_width < 1) {
00551         scaled_width = 1;
00552     }
00553     if (scaled_height < 1) {
00554         scaled_height = 1;
00555     }
00556 
00557     //
00558     // clamp to the current upper OpenGL limit
00559     // scale both axis down equally so we don't have to
00560     // deal with a half mip resampling
00561     //
00562     while ( scaled_width > glConfig.maxTextureSize
00563         || scaled_height > glConfig.maxTextureSize ) {
00564         scaled_width >>= 1;
00565         scaled_height >>= 1;
00566     }
00567 
00568     scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height );
00569 
00570     //
00571     // scan the texture for each channel's max values
00572     // and verify if the alpha channel is being used or not
00573     //
00574     c = width*height;
00575     scan = ((byte *)data);
00576     samples = 3;
00577     if (!lightMap) {
00578         for ( i = 0; i < c; i++ )
00579         {
00580             if ( scan[i*4+0] > rMax )
00581             {
00582                 rMax = scan[i*4+0];
00583             }
00584             if ( scan[i*4+1] > gMax )
00585             {
00586                 gMax = scan[i*4+1];
00587             }
00588             if ( scan[i*4+2] > bMax )
00589             {
00590                 bMax = scan[i*4+2];
00591             }
00592             if ( scan[i*4 + 3] != 255 ) 
00593             {
00594                 samples = 4;
00595                 break;
00596             }
00597         }
00598         // select proper internal format
00599         if ( samples == 3 )
00600         {
00601             if ( glConfig.textureCompression == TC_S3TC )
00602             {
00603                 internalFormat = GL_RGB4_S3TC;
00604             }
00605             else if ( r_texturebits->integer == 16 )
00606             {
00607                 internalFormat = GL_RGB5;
00608             }
00609             else if ( r_texturebits->integer == 32 )
00610             {
00611                 internalFormat = GL_RGB8;
00612             }
00613             else
00614             {
00615                 internalFormat = 3;
00616             }
00617         }
00618         else if ( samples == 4 )
00619         {
00620             if ( r_texturebits->integer == 16 )
00621             {
00622                 internalFormat = GL_RGBA4;
00623             }
00624             else if ( r_texturebits->integer == 32 )
00625             {
00626                 internalFormat = GL_RGBA8;
00627             }
00628             else
00629             {
00630                 internalFormat = 4;
00631             }
00632         }
00633     } else {
00634         internalFormat = 3;
00635     }
00636     // copy or resample data as appropriate for first MIP level
00637     if ( ( scaled_width == width ) && 
00638         ( scaled_height == height ) ) {
00639         if (!mipmap)
00640         {
00641             qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
00642             *pUploadWidth = scaled_width;
00643             *pUploadHeight = scaled_height;
00644             *format = internalFormat;
00645 
00646             goto done;
00647         }
00648         Com_Memcpy (scaledBuffer, data, width*height*4);
00649     }
00650     else
00651     {
00652         // use the normal mip-mapping function to go down from here
00653         while ( width > scaled_width || height > scaled_height ) {
00654             R_MipMap( (byte *)data, width, height );
00655             width >>= 1;
00656             height >>= 1;
00657             if ( width < 1 ) {
00658                 width = 1;
00659             }
00660             if ( height < 1 ) {
00661                 height = 1;
00662             }
00663         }
00664         Com_Memcpy( scaledBuffer, data, width * height * 4 );
00665     }
00666 
00667     R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !mipmap );
00668 
00669     *pUploadWidth = scaled_width;
00670     *pUploadHeight = scaled_height;
00671     *format = internalFormat;
00672 
00673     qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer );
00674 
00675     if (mipmap)
00676     {
00677         int     miplevel;
00678 
00679         miplevel = 0;
00680         while (scaled_width > 1 || scaled_height > 1)
00681         {
00682             R_MipMap( (byte *)scaledBuffer, scaled_width, scaled_height );
00683             scaled_width >>= 1;
00684             scaled_height >>= 1;
00685             if (scaled_width < 1)
00686                 scaled_width = 1;
00687             if (scaled_height < 1)
00688                 scaled_height = 1;
00689             miplevel++;
00690 
00691             if ( r_colorMipLevels->integer ) {
00692                 R_BlendOverTexture( (byte *)scaledBuffer, scaled_width * scaled_height, mipBlendColors[miplevel] );
00693             }
00694 
00695             qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer );
00696         }
00697     }
00698 done:
00699 
00700     if (mipmap)
00701     {
00702         qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
00703         qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
00704     }
00705     else
00706     {
00707         qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00708         qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00709     }
00710 
00711     GL_CheckErrors();
00712 
00713     if ( scaledBuffer != 0 )
00714         ri.Hunk_FreeTempMemory( scaledBuffer );
00715     if ( resampledBuffer != 0 )
00716         ri.Hunk_FreeTempMemory( resampledBuffer );
00717 }
00718 
00719 
00720 /*
00721 ================
00722 R_CreateImage
00723 
00724 This is the only way any image_t are created
00725 ================
00726 */
00727 image_t *R_CreateImage( const char *name, const byte *pic, int width, int height, 
00728                        qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) {
00729     image_t     *image;
00730     qboolean    isLightmap = qfalse;
00731     long        hash;
00732 
00733     if (strlen(name) >= MAX_QPATH ) {
00734         ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long\n", name);
00735     }
00736     if ( !strncmp( name, "*lightmap", 9 ) ) {
00737         isLightmap = qtrue;
00738     }
00739 
00740     if ( tr.numImages == MAX_DRAWIMAGES ) {
00741         ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n");
00742     }
00743 
00744     image = tr.images[tr.numImages] = ri.Hunk_Alloc( sizeof( image_t ), h_low );
00745     image->texnum = 1024 + tr.numImages;
00746     tr.numImages++;
00747 
00748     image->mipmap = mipmap;
00749     image->allowPicmip = allowPicmip;
00750 
00751     strcpy (image->imgName, name);
00752 
00753     image->width = width;
00754     image->height = height;
00755     image->wrapClampMode = glWrapClampMode;
00756 
00757     // lightmaps are always allocated on TMU 1
00758     if ( qglActiveTextureARB && isLightmap ) {
00759         image->TMU = 1;
00760     } else {
00761         image->TMU = 0;
00762     }
00763 
00764     if ( qglActiveTextureARB ) {
00765         GL_SelectTexture( image->TMU );
00766     }
00767 
00768     GL_Bind(image);
00769 
00770     Upload32( (unsigned *)pic, image->width, image->height, 
00771                                 image->mipmap,
00772                                 allowPicmip,
00773                                 isLightmap,
00774                                 &image->internalFormat,
00775                                 &image->uploadWidth,
00776                                 &image->uploadHeight );
00777 
00778     qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
00779     qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
00780 
00781     qglBindTexture( GL_TEXTURE_2D, 0 );
00782 
00783     if ( image->TMU == 1 ) {
00784         GL_SelectTexture( 0 );
00785     }
00786 
00787     hash = generateHashValue(name);
00788     image->next = hashTable[hash];
00789     hashTable[hash] = image;
00790 
00791     return image;
00792 }
00793 
00794 
00795 /*
00796 =========================================================
00797 
00798 BMP LOADING
00799 
00800 =========================================================
00801 */
00802 typedef struct
00803 {
00804     char id[2];
00805     unsigned long fileSize;
00806     unsigned long reserved0;
00807     unsigned long bitmapDataOffset;
00808     unsigned long bitmapHeaderSize;
00809     unsigned long width;
00810     unsigned long height;
00811     unsigned short planes;
00812     unsigned short bitsPerPixel;
00813     unsigned long compression;
00814     unsigned long bitmapDataSize;
00815     unsigned long hRes;
00816     unsigned long vRes;
00817     unsigned long colors;
00818     unsigned long importantColors;
00819     unsigned char palette[256][4];
00820 } BMPHeader_t;
00821 
00822 static void LoadBMP( const char *name, byte **pic, int *width, int *height )
00823 {
00824     int     columns, rows, numPixels;
00825     byte    *pixbuf;
00826     int     row, column;
00827     byte    *buf_p;
00828     byte    *buffer;
00829     int     length;
00830     BMPHeader_t bmpHeader;
00831     byte        *bmpRGBA;
00832 
00833     *pic = NULL;
00834 
00835     //
00836     // load the file
00837     //
00838     length = ri.FS_ReadFile( ( char * ) name, (void **)&buffer);
00839     if (!buffer) {
00840         return;
00841     }
00842 
00843     buf_p = buffer;
00844 
00845     bmpHeader.id[0] = *buf_p++;
00846     bmpHeader.id[1] = *buf_p++;
00847     bmpHeader.fileSize = LittleLong( * ( long * ) buf_p );
00848     buf_p += 4;
00849     bmpHeader.reserved0 = LittleLong( * ( long * ) buf_p );
00850     buf_p += 4;
00851     bmpHeader.bitmapDataOffset = LittleLong( * ( long * ) buf_p );
00852     buf_p += 4;
00853     bmpHeader.bitmapHeaderSize = LittleLong( * ( long * ) buf_p );
00854     buf_p += 4;
00855     bmpHeader.width = LittleLong( * ( long * ) buf_p );
00856     buf_p += 4;
00857     bmpHeader.height = LittleLong( * ( long * ) buf_p );
00858     buf_p += 4;
00859     bmpHeader.planes = LittleShort( * ( short * ) buf_p );
00860     buf_p += 2;
00861     bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p );
00862     buf_p += 2;
00863     bmpHeader.compression = LittleLong( * ( long * ) buf_p );
00864     buf_p += 4;
00865     bmpHeader.bitmapDataSize = LittleLong( * ( long * ) buf_p );
00866     buf_p += 4;
00867     bmpHeader.hRes = LittleLong( * ( long * ) buf_p );
00868     buf_p += 4;
00869     bmpHeader.vRes = LittleLong( * ( long * ) buf_p );
00870     buf_p += 4;
00871     bmpHeader.colors = LittleLong( * ( long * ) buf_p );
00872     buf_p += 4;
00873     bmpHeader.importantColors = LittleLong( * ( long * ) buf_p );
00874     buf_p += 4;
00875 
00876     Com_Memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
00877 
00878     if ( bmpHeader.bitsPerPixel == 8 )
00879         buf_p += 1024;
00880 
00881     if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' ) 
00882     {
00883         ri.Error( ERR_DROP, "LoadBMP: only Windows-style BMP files supported (%s)\n", name );
00884     }
00885     if ( bmpHeader.fileSize != length )
00886     {
00887         ri.Error( ERR_DROP, "LoadBMP: header size does not match file size (%d vs. %d) (%s)\n", bmpHeader.fileSize, length, name );
00888     }
00889     if ( bmpHeader.compression != 0 )
00890     {
00891         ri.Error( ERR_DROP, "LoadBMP: only uncompressed BMP files supported (%s)\n", name );
00892     }
00893     if ( bmpHeader.bitsPerPixel < 8 )
00894     {
00895         ri.Error( ERR_DROP, "LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name );
00896     }
00897 
00898     columns = bmpHeader.width;
00899     rows = bmpHeader.height;
00900     if ( rows < 0 )
00901         rows = -rows;
00902     numPixels = columns * rows;
00903 
00904     if ( width ) 
00905         *width = columns;
00906     if ( height )
00907         *height = rows;
00908 
00909     bmpRGBA = ri.Malloc( numPixels * 4 );
00910     *pic = bmpRGBA;
00911 
00912 
00913     for ( row = rows-1; row >= 0; row-- )
00914     {
00915         pixbuf = bmpRGBA + row*columns*4;
00916 
00917         for ( column = 0; column < columns; column++ )
00918         {
00919             unsigned char red, green, blue, alpha;
00920             int palIndex;
00921             unsigned short shortPixel;
00922 
00923             switch ( bmpHeader.bitsPerPixel )
00924             {
00925             case 8:
00926                 palIndex = *buf_p++;
00927                 *pixbuf++ = bmpHeader.palette[palIndex][2];
00928                 *pixbuf++ = bmpHeader.palette[palIndex][1];
00929                 *pixbuf++ = bmpHeader.palette[palIndex][0];
00930                 *pixbuf++ = 0xff;
00931                 break;
00932             case 16:
00933                 shortPixel = * ( unsigned short * ) pixbuf;
00934                 pixbuf += 2;
00935                 *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
00936                 *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
00937                 *pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
00938                 *pixbuf++ = 0xff;
00939                 break;
00940 
00941             case 24:
00942                 blue = *buf_p++;
00943                 green = *buf_p++;
00944                 red = *buf_p++;
00945                 *pixbuf++ = red;
00946                 *pixbuf++ = green;
00947                 *pixbuf++ = blue;
00948                 *pixbuf++ = 255;
00949                 break;
00950             case 32:
00951                 blue = *buf_p++;
00952                 green = *buf_p++;
00953                 red = *buf_p++;
00954                 alpha = *buf_p++;
00955                 *pixbuf++ = red;
00956                 *pixbuf++ = green;
00957                 *pixbuf++ = blue;
00958                 *pixbuf++ = alpha;
00959                 break;
00960             default:
00961                 ri.Error( ERR_DROP, "LoadBMP: illegal pixel_size '%d' in file '%s'\n", bmpHeader.bitsPerPixel, name );
00962                 break;
00963             }
00964         }
00965     }
00966 
00967     ri.FS_FreeFile( buffer );
00968 
00969 }
00970 
00971 
00972 /*
00973 =================================================================
00974 
00975 PCX LOADING
00976 
00977 =================================================================
00978 */
00979 
00980 
00981 /*
00982 ==============
00983 LoadPCX
00984 ==============
00985 */
00986 static void LoadPCX ( const char *filename, byte **pic, byte **palette, int *width, int *height)
00987 {
00988     byte    *raw;
00989     pcx_t   *pcx;
00990     int     x, y;
00991     int     len;
00992     int     dataByte, runLength;
00993     byte    *out, *pix;
00994     int     xmax, ymax;
00995 
00996     *pic = NULL;
00997     *palette = NULL;
00998 
00999     //
01000     // load the file
01001     //
01002     len = ri.FS_ReadFile( ( char * ) filename, (void **)&raw);
01003     if (!raw) {
01004         return;
01005     }
01006 
01007     //
01008     // parse the PCX file
01009     //
01010     pcx = (pcx_t *)raw;
01011     raw = &pcx->data;
01012 
01013     xmax = LittleShort(pcx->xmax);
01014     ymax = LittleShort(pcx->ymax);
01015 
01016     if (pcx->manufacturer != 0x0a
01017         || pcx->version != 5
01018         || pcx->encoding != 1
01019         || pcx->bits_per_pixel != 8
01020         || xmax >= 1024
01021         || ymax >= 1024)
01022     {
01023         ri.Printf (PRINT_ALL, "Bad pcx file %s (%i x %i) (%i x %i)\n", filename, xmax+1, ymax+1, pcx->xmax, pcx->ymax);
01024         return;
01025     }
01026 
01027     out = ri.Malloc ( (ymax+1) * (xmax+1) );
01028 
01029     *pic = out;
01030 
01031     pix = out;
01032 
01033     if (palette)
01034     {
01035         *palette = ri.Malloc(768);
01036         Com_Memcpy (*palette, (byte *)pcx + len - 768, 768);
01037     }
01038 
01039     if (width)
01040         *width = xmax+1;
01041     if (height)
01042         *height = ymax+1;
01043 // FIXME: use bytes_per_line here?
01044 
01045     for (y=0 ; y<=ymax ; y++, pix += xmax+1)
01046     {
01047         for (x=0 ; x<=xmax ; )
01048         {
01049             dataByte = *raw++;
01050 
01051             if((dataByte & 0xC0) == 0xC0)
01052             {
01053                 runLength = dataByte & 0x3F;
01054                 dataByte = *raw++;
01055             }
01056             else
01057                 runLength = 1;
01058 
01059             while(runLength-- > 0)
01060                 pix[x++] = dataByte;
01061         }
01062 
01063     }
01064 
01065     if ( raw - (byte *)pcx > len)
01066     {
01067         ri.Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename);
01068         ri.Free (*pic);
01069         *pic = NULL;
01070     }
01071 
01072     ri.FS_FreeFile (pcx);
01073 }
01074 
01075 
01076 /*
01077 ==============
01078 LoadPCX32
01079 ==============
01080 */
01081 static void LoadPCX32 ( const char *filename, byte **pic, int *width, int *height) {
01082     byte    *palette;
01083     byte    *pic8;
01084     int     i, c, p;
01085     byte    *pic32;
01086 
01087     LoadPCX (filename, &pic8, &palette, width, height);
01088     if (!pic8) {
01089         *pic = NULL;
01090         return;
01091     }
01092 
01093     c = (*width) * (*height);
01094     pic32 = *pic = ri.Malloc(4 * c );
01095     for (i = 0 ; i < c ; i++) {
01096         p = pic8[i];
01097         pic32[0] = palette[p*3];
01098         pic32[1] = palette[p*3 + 1];
01099         pic32[2] = palette[p*3 + 2];
01100         pic32[3] = 255;
01101         pic32 += 4;
01102     }
01103 
01104     ri.Free (pic8);
01105     ri.Free (palette);
01106 }
01107 
01108 /*
01109 =========================================================
01110 
01111 TARGA LOADING
01112 
01113 =========================================================
01114 */
01115 
01116 /*
01117 =============
01118 LoadTGA
01119 =============
01120 */
01121 static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
01122 {
01123     int     columns, rows, numPixels;
01124     byte    *pixbuf;
01125     int     row, column;
01126     byte    *buf_p;
01127     byte    *buffer;
01128     TargaHeader targa_header;
01129     byte        *targa_rgba;
01130 
01131     *pic = NULL;
01132 
01133     //
01134     // load the file
01135     //
01136     ri.FS_ReadFile ( ( char * ) name, (void **)&buffer);
01137     if (!buffer) {
01138         return;
01139     }
01140 
01141     buf_p = buffer;
01142 
01143     targa_header.id_length = *buf_p++;
01144     targa_header.colormap_type = *buf_p++;
01145     targa_header.image_type = *buf_p++;
01146     
01147     targa_header.colormap_index = LittleShort ( *(short *)buf_p );
01148     buf_p += 2;
01149     targa_header.colormap_length = LittleShort ( *(short *)buf_p );
01150     buf_p += 2;
01151     targa_header.colormap_size = *buf_p++;
01152     targa_header.x_origin = LittleShort ( *(short *)buf_p );
01153     buf_p += 2;
01154     targa_header.y_origin = LittleShort ( *(short *)buf_p );
01155     buf_p += 2;
01156     targa_header.width = LittleShort ( *(short *)buf_p );
01157     buf_p += 2;
01158     targa_header.height = LittleShort ( *(short *)buf_p );
01159     buf_p += 2;
01160     targa_header.pixel_size = *buf_p++;
01161     targa_header.attributes = *buf_p++;
01162 
01163     if (targa_header.image_type!=2 
01164         && targa_header.image_type!=10
01165         && targa_header.image_type != 3 ) 
01166     {
01167         ri.Error (ERR_DROP, "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
01168     }
01169 
01170     if ( targa_header.colormap_type != 0 )
01171     {
01172         ri.Error( ERR_DROP, "LoadTGA: colormaps not supported\n" );
01173     }
01174 
01175     if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
01176     {
01177         ri.Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
01178     }
01179 
01180     columns = targa_header.width;
01181     rows = targa_header.height;
01182     numPixels = columns * rows;
01183 
01184     if (width)
01185         *width = columns;
01186     if (height)
01187         *height = rows;
01188 
01189     targa_rgba = ri.Malloc (numPixels*4);
01190     *pic = targa_rgba;
01191 
01192     if (targa_header.id_length != 0)
01193         buf_p += targa_header.id_length;  // skip TARGA image comment
01194     
01195     if ( targa_header.image_type==2 || targa_header.image_type == 3 )
01196     { 
01197         // Uncompressed RGB or gray scale image
01198         for(row=rows-1; row>=0; row--) 
01199         {
01200             pixbuf = targa_rgba + row*columns*4;
01201             for(column=0; column<columns; column++) 
01202             {
01203                 unsigned char red,green,blue,alphabyte;
01204                 switch (targa_header.pixel_size) 
01205                 {
01206                     
01207                 case 8:
01208                     blue = *buf_p++;
01209                     green = blue;
01210                     red = blue;
01211                     *pixbuf++ = red;
01212                     *pixbuf++ = green;
01213                     *pixbuf++ = blue;
01214                     *pixbuf++ = 255;
01215                     break;
01216 
01217                 case 24:
01218                     blue = *buf_p++;
01219                     green = *buf_p++;
01220                     red = *buf_p++;
01221                     *pixbuf++ = red;
01222                     *pixbuf++ = green;
01223                     *pixbuf++ = blue;
01224                     *pixbuf++ = 255;
01225                     break;
01226                 case 32:
01227                     blue = *buf_p++;
01228                     green = *buf_p++;
01229                     red = *buf_p++;
01230                     alphabyte = *buf_p++;
01231                     *pixbuf++ = red;
01232                     *pixbuf++ = green;
01233                     *pixbuf++ = blue;
01234                     *pixbuf++ = alphabyte;
01235                     break;
01236                 default:
01237                     ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
01238                     break;
01239                 }
01240             }
01241         }
01242     }
01243     else if (targa_header.image_type==10) {   // Runlength encoded RGB images
01244         unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
01245 
01246         red = 0;
01247         green = 0;
01248         blue = 0;
01249         alphabyte = 0xff;
01250 
01251         for(row=rows-1; row>=0; row--) {
01252             pixbuf = targa_rgba + row*columns*4;
01253             for(column=0; column<columns; ) {
01254                 packetHeader= *buf_p++;
01255                 packetSize = 1 + (packetHeader & 0x7f);
01256                 if (packetHeader & 0x80) {        // run-length packet
01257                     switch (targa_header.pixel_size) {
01258                         case 24:
01259                                 blue = *buf_p++;
01260                                 green = *buf_p++;
01261                                 red = *buf_p++;
01262                                 alphabyte = 255;
01263                                 break;
01264                         case 32:
01265                                 blue = *buf_p++;
01266                                 green = *buf_p++;
01267                                 red = *buf_p++;
01268                                 alphabyte = *buf_p++;
01269                                 break;
01270                         default:
01271                             ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
01272                             break;
01273                     }
01274     
01275                     for(j=0;j<packetSize;j++) {
01276                         *pixbuf++=red;
01277                         *pixbuf++=green;
01278                         *pixbuf++=blue;
01279                         *pixbuf++=alphabyte;
01280                         column++;
01281                         if (column==columns) { // run spans across rows
01282                             column=0;
01283                             if (row>0)
01284                                 row--;
01285                             else
01286                                 goto breakOut;
01287                             pixbuf = targa_rgba + row*columns*4;
01288                         }
01289                     }
01290                 }
01291                 else {                            // non run-length packet
01292                     for(j=0;j<packetSize;j++) {
01293                         switch (targa_header.pixel_size) {
01294                             case 24:
01295                                     blue = *buf_p++;
01296                                     green = *buf_p++;
01297                                     red = *buf_p++;
01298                                     *pixbuf++ = red;
01299                                     *pixbuf++ = green;
01300                                     *pixbuf++ = blue;
01301                                     *pixbuf++ = 255;
01302                                     break;
01303                             case 32:
01304                                     blue = *buf_p++;
01305                                     green = *buf_p++;
01306                                     red = *buf_p++;
01307                                     alphabyte = *buf_p++;
01308                                     *pixbuf++ = red;
01309                                     *pixbuf++ = green;
01310                                     *pixbuf++ = blue;
01311                                     *pixbuf++ = alphabyte;
01312                                     break;
01313                             default:
01314                                 ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
01315                                 break;
01316                         }
01317                         column++;
01318                         if (column==columns) { // pixel packet run spans across rows
01319                             column=0;
01320                             if (row>0)
01321                                 row--;
01322                             else
01323                                 goto breakOut;
01324                             pixbuf = targa_rgba + row*columns*4;
01325                         }                       
01326                     }
01327                 }
01328             }
01329             breakOut:;
01330         }
01331     }
01332 
01333 #if 0 
01334   // TTimo: this is the chunk of code to ensure a behavior that meets TGA specs 
01335   // bk0101024 - fix from Leonardo
01336   // bit 5 set => top-down
01337   if (targa_header.attributes & 0x20) {
01338     unsigned char *flip = (unsigned char*)malloc (columns*4);
01339     unsigned char *src, *dst;
01340 
01341     for (row = 0; row < rows/2; row++) {
01342       src = targa_rgba + row * 4 * columns;
01343       dst = targa_rgba + (rows - row - 1) * 4 * columns;
01344 
01345       memcpy (flip, src, columns*4);
01346       memcpy (src, dst, columns*4);
01347       memcpy (dst, flip, columns*4);
01348     }
01349     free (flip);
01350   }
01351 #endif
01352   // instead we just print a warning
01353   if (targa_header.attributes & 0x20) {
01354     ri.Printf( PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, ignoring\n", name);
01355   }
01356 
01357   ri.FS_FreeFile (buffer);
01358 }
01359 
01360 static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) {
01361   /* This struct contains the JPEG decompression parameters and pointers to
01362    * working space (which is allocated as needed by the JPEG library).
01363    */
01364   struct jpeg_decompress_struct cinfo;
01365   /* We use our private extension JPEG error handler.
01366    * Note that this struct must live as long as the main JPEG parameter
01367    * struct, to avoid dangling-pointer problems.
01368    */
01369   /* This struct represents a JPEG error handler.  It is declared separately
01370    * because applications often want to supply a specialized error handler
01371    * (see the second half of this file for an example).  But here we just
01372    * take the easy way out and use the standard error handler, which will
01373    * print a message on stderr and call exit() if compression fails.
01374    * Note that this struct must live as long as the main JPEG parameter
01375    * struct, to avoid dangling-pointer problems.
01376    */
01377   struct jpeg_error_mgr jerr;
01378   /* More stuff */
01379   JSAMPARRAY buffer;        /* Output row buffer */
01380   int row_stride;       /* physical row width in output buffer */
01381   unsigned char *out;
01382   byte  *fbuffer;
01383   byte  *bbuf;
01384 
01385   /* In this example we want to open the input file before doing anything else,
01386    * so that the setjmp() error recovery below can assume the file is open.
01387    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
01388    * requires it in order to read binary files.
01389    */
01390 
01391   ri.FS_ReadFile ( ( char * ) filename, (void **)&fbuffer);
01392   if (!fbuffer) {
01393     return;
01394   }
01395 
01396   /* Step 1: allocate and initialize JPEG decompression object */
01397 
01398   /* We have to set up the error handler first, in case the initialization
01399    * step fails.  (Unlikely, but it could happen if you are out of memory.)
01400    * This routine fills in the contents of struct jerr, and returns jerr's
01401    * address which we place into the link field in cinfo.
01402    */
01403   cinfo.err = jpeg_std_error(&jerr);
01404 
01405   /* Now we can initialize the JPEG decompression object. */
01406   jpeg_create_decompress(&cinfo);
01407 
01408   /* Step 2: specify data source (eg, a file) */
01409 
01410   jpeg_stdio_src(&cinfo, fbuffer);
01411 
01412   /* Step 3: read file parameters with jpeg_read_header() */
01413 
01414   (void) jpeg_read_header(&cinfo, TRUE);
01415   /* We can ignore the return value from jpeg_read_header since
01416    *   (a) suspension is not possible with the stdio data source, and
01417    *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
01418    * See libjpeg.doc for more info.
01419    */
01420 
01421   /* Step 4: set parameters for decompression */
01422 
01423   /* In this example, we don't need to change any of the defaults set by
01424    * jpeg_read_header(), so we do nothing here.
01425    */
01426 
01427   /* Step 5: Start decompressor */
01428 
01429   (void) jpeg_start_decompress(&cinfo);
01430   /* We can ignore the return value since suspension is not possible
01431    * with the stdio data source.
01432    */
01433 
01434   /* We may need to do some setup of our own at this point before reading
01435    * the data.  After jpeg_start_decompress() we have the correct scaled
01436    * output image dimensions available, as well as the output colormap
01437    * if we asked for color quantization.
01438    * In this example, we need to make an output work buffer of the right size.
01439    */ 
01440   /* JSAMPLEs per row in output buffer */
01441   row_stride = cinfo.output_width * cinfo.output_components;
01442 
01443   out = ri.Malloc(cinfo.output_width*cinfo.output_height*cinfo.output_components);
01444 
01445   *pic = out;
01446   *width = cinfo.output_width;
01447   *height = cinfo.output_height;
01448 
01449   /* Step 6: while (scan lines remain to be read) */
01450   /*           jpeg_read_scanlines(...); */
01451 
01452   /* Here we use the library's state variable cinfo.output_scanline as the
01453    * loop counter, so that we don't have to keep track ourselves.
01454    */
01455   while (cinfo.output_scanline < cinfo.output_height) {
01456     /* jpeg_read_scanlines expects an array of pointers to scanlines.
01457      * Here the array is only one element long, but you could ask for
01458      * more than one scanline at a time if that's more convenient.
01459      */
01460     bbuf = ((out+(row_stride*cinfo.output_scanline)));
01461     buffer = &bbuf;
01462     (void) jpeg_read_scanlines(&cinfo, buffer, 1);
01463   }
01464 
01465   // clear all the alphas to 255
01466   {
01467       int   i, j;
01468         byte    *buf;
01469 
01470         buf = *pic;
01471 
01472       j = cinfo.output_width * cinfo.output_height * 4;
01473       for ( i = 3 ; i < j ; i+=4 ) {
01474           buf[i] = 255;
01475       }
01476   }
01477 
01478   /* Step 7: Finish decompression */
01479 
01480   (void) jpeg_finish_decompress(&cinfo);
01481   /* We can ignore the return value since suspension is not possible
01482    * with the stdio data source.
01483    */
01484 
01485   /* Step 8: Release JPEG decompression object */
01486 
01487   /* This is an important step since it will release a good deal of memory. */
01488   jpeg_destroy_decompress(&cinfo);
01489 
01490   /* After finish_decompress, we can close the input file.
01491    * Here we postpone it until after no more JPEG errors are possible,
01492    * so as to simplify the setjmp error logic above.  (Actually, I don't
01493    * think that jpeg_destroy can do an error exit, but why assume anything...)
01494    */
01495   ri.FS_FreeFile (fbuffer);
01496 
01497   /* At this point you may want to check to see whether any corrupt-data
01498    * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
01499    */
01500 
01501   /* And we're done! */
01502 }
01503 
01504 
01505 /* Expanded data destination object for stdio output */
01506 
01507 typedef struct {
01508   struct jpeg_destination_mgr pub; /* public fields */
01509 
01510   byte* outfile;        /* target stream */
01511   int   size;
01512 } my_destination_mgr;
01513 
01514 typedef my_destination_mgr * my_dest_ptr;
01515 
01516 
01517 /*
01518  * Initialize destination --- called by jpeg_start_compress
01519  * before any data is actually written.
01520  */
01521 
01522 void init_destination (j_compress_ptr cinfo)
01523 {
01524   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
01525 
01526   dest->pub.next_output_byte = dest->outfile;
01527   dest->pub.