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

LBMLIB.CPP

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 // lbmlib.c
00023 
00024 #include "stdafx.h"
00025 #include "cmdlib.h"
00026 #include "lbmlib.h"
00027 #include "bmp.h"
00028 #include "pakstuff.h"
00029 #include "jpeglib.h"
00030 
00031 
00032 /*
00033 ============================================================================
00034 
00035                         LBM STUFF
00036 
00037 ============================================================================
00038 */
00039 
00040 
00041 typedef unsigned char   UBYTE;
00042 //conflicts with windows typedef short          WORD;
00043 typedef unsigned short  UWORD;
00044 typedef long            LONG;
00045 
00046 typedef enum
00047 {
00048     ms_none,
00049     ms_mask,
00050     ms_transcolor,
00051     ms_lasso
00052 } mask_t;
00053 
00054 typedef enum
00055 {
00056     cm_none,
00057     cm_rle1
00058 } compress_t;
00059 
00060 typedef struct
00061 {
00062     UWORD       w,h;
00063     short       x,y;
00064     UBYTE       nPlanes;
00065     UBYTE       masking;
00066     UBYTE       compression;
00067     UBYTE       pad1;
00068     UWORD       transparentColor;
00069     UBYTE       xAspect,yAspect;
00070     short       pageWidth,pageHeight;
00071 } bmhd_t;
00072 
00073 extern  bmhd_t  bmhd;                       // will be in native byte order
00074 
00075 
00076 
00077 #define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
00078 #define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
00079 #define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
00080 #define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
00081 #define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
00082 #define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
00083 
00084 
00085 bmhd_t  bmhd;
00086 
00087 int    Align (int l)
00088 {
00089     if (l&1)
00090         return l+1;
00091     return l;
00092 }
00093 
00094 
00095 
00096 /*
00097 ================
00098 LBMRLEdecompress
00099 
00100 Source must be evenly aligned!
00101 ================
00102 */
00103 byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
00104 {
00105     int     count;
00106     byte    b,rept;
00107 
00108     count = 0;
00109 
00110     do
00111     {
00112         rept = *source++;
00113 
00114         if (rept > 0x80)
00115         {
00116             rept = (rept^0xff)+2;
00117             b = *source++;
00118             memset(unpacked,b,rept);
00119             unpacked += rept;
00120         }
00121         else if (rept < 0x80)
00122         {
00123             rept++;
00124             memcpy(unpacked,source,rept);
00125             unpacked += rept;
00126             source += rept;
00127         }
00128         else
00129             rept = 0;               // rept of 0x80 is NOP
00130 
00131         count += rept;
00132 
00133     } while (count<bpwidth);
00134 
00135     if (count>bpwidth)
00136         Error ("Decompression exceeded width!\n");
00137 
00138 
00139     return source;
00140 }
00141 
00142 
00143 /*
00144 =================
00145 LoadLBM
00146 =================
00147 */
00148 void LoadLBM (char *filename, byte **picture, byte **palette)
00149 {
00150     byte    *LBMbuffer, *picbuffer, *cmapbuffer;
00151     int             y;
00152     byte    *LBM_P, *LBMEND_P;
00153     byte    *pic_p;
00154     byte    *body_p;
00155 
00156     int    formtype,formlength;
00157     int    chunktype,chunklength;
00158 
00159 // qiet compiler warnings
00160     picbuffer = NULL;
00161     cmapbuffer = NULL;
00162 
00163 //
00164 // load the LBM
00165 //
00166     LoadFile (filename, (void **)&LBMbuffer);
00167 
00168   if (LBMbuffer == NULL)
00169   {
00170     return;
00171   }
00172 //
00173 // parse the LBM header
00174 //
00175     LBM_P = LBMbuffer;
00176     if ( *(int *)LBMbuffer != LittleLong(FORMID) )
00177        Error ("No FORM ID at start of file!\n");
00178 
00179     LBM_P += 4;
00180     formlength = BigLong( *(int *)LBM_P );
00181     LBM_P += 4;
00182     LBMEND_P = LBM_P + Align(formlength);
00183 
00184     formtype = LittleLong(*(int *)LBM_P);
00185 
00186     if (formtype != ILBMID && formtype != PBMID)
00187         Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
00188         ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
00189 
00190     LBM_P += 4;
00191 
00192 //
00193 // parse chunks
00194 //
00195 
00196     while (LBM_P < LBMEND_P)
00197     {
00198         chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
00199         LBM_P += 4;
00200         chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
00201         LBM_P += 4;
00202 
00203         switch ( chunktype )
00204         {
00205         case BMHDID:
00206             memcpy (&bmhd,LBM_P,sizeof(bmhd));
00207             bmhd.w = BigShort(bmhd.w);
00208             bmhd.h = BigShort(bmhd.h);
00209             bmhd.x = BigShort(bmhd.x);
00210             bmhd.y = BigShort(bmhd.y);
00211             bmhd.pageWidth = BigShort(bmhd.pageWidth);
00212             bmhd.pageHeight = BigShort(bmhd.pageHeight);
00213             break;
00214 
00215         case CMAPID:
00216             cmapbuffer = (unsigned char*)malloc (768);
00217             memset (cmapbuffer, 0, 768);
00218             memcpy (cmapbuffer, LBM_P, chunklength);
00219             break;
00220 
00221         case BODYID:
00222             body_p = LBM_P;
00223 
00224             pic_p = picbuffer = (unsigned char*)malloc (bmhd.w*bmhd.h);
00225             if (formtype == PBMID)
00226             {
00227             //
00228             // unpack PBM
00229             //
00230                 for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
00231                 {
00232                     if (bmhd.compression == cm_rle1)
00233                         body_p = LBMRLEDecompress ((byte *)body_p
00234                         , pic_p , bmhd.w);
00235                     else if (bmhd.compression == cm_none)
00236                     {
00237                         memcpy (pic_p,body_p,bmhd.w);
00238                         body_p += Align(bmhd.w);
00239                     }
00240                 }
00241 
00242             }
00243             else
00244             {
00245             //
00246             // unpack ILBM
00247             //
00248                 Error ("%s is an interlaced LBM, not packed", filename);
00249             }
00250             break;
00251         }
00252 
00253         LBM_P += Align(chunklength);
00254     }
00255 
00256     free (LBMbuffer);
00257 
00258     *picture = picbuffer;
00259 
00260     if (palette)
00261         *palette = cmapbuffer;
00262 }
00263 
00264 
00265 /*
00266 ============================================================================
00267 
00268                             WRITE LBM
00269 
00270 ============================================================================
00271 */
00272 
00273 /*
00274 ==============
00275 WriteLBMfile
00276 ==============
00277 */
00278 void WriteLBMfile (char *filename, byte *data,
00279                    int width, int height, byte *palette)
00280 {
00281     byte    *lbm, *lbmptr;
00282     int    *formlength, *bmhdlength, *cmaplength, *bodylength;
00283     int    length;
00284     bmhd_t  basebmhd;
00285 
00286     lbm = lbmptr = (unsigned char*)malloc (width*height+1000);
00287 
00288 //
00289 // start FORM
00290 //
00291     *lbmptr++ = 'F';
00292     *lbmptr++ = 'O';
00293     *lbmptr++ = 'R';
00294     *lbmptr++ = 'M';
00295 
00296     formlength = (int*)lbmptr;
00297     lbmptr+=4;                      // leave space for length
00298 
00299     *lbmptr++ = 'P';
00300     *lbmptr++ = 'B';
00301     *lbmptr++ = 'M';
00302     *lbmptr++ = ' ';
00303 
00304 //
00305 // write BMHD
00306 //
00307     *lbmptr++ = 'B';
00308     *lbmptr++ = 'M';
00309     *lbmptr++ = 'H';
00310     *lbmptr++ = 'D';
00311 
00312     bmhdlength = (int *)lbmptr;
00313     lbmptr+=4;                      // leave space for length
00314 
00315     memset (&basebmhd,0,sizeof(basebmhd));
00316     basebmhd.w = BigShort((short)width);
00317     basebmhd.h = BigShort((short)height);
00318     basebmhd.nPlanes = 8;
00319     basebmhd.xAspect = 5;
00320     basebmhd.yAspect = 6;
00321     basebmhd.pageWidth = BigShort((short)width);
00322     basebmhd.pageHeight = BigShort((short)height);
00323 
00324     memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
00325     lbmptr += sizeof(basebmhd);
00326 
00327     length = lbmptr-(byte *)bmhdlength-4;
00328     *bmhdlength = BigLong(length);
00329     if (length&1)
00330         *lbmptr++ = 0;          // pad chunk to even offset
00331 
00332 //
00333 // write CMAP
00334 //
00335     *lbmptr++ = 'C';
00336     *lbmptr++ = 'M';
00337     *lbmptr++ = 'A';
00338     *lbmptr++ = 'P';
00339 
00340     cmaplength = (int *)lbmptr;
00341     lbmptr+=4;                      // leave space for length
00342 
00343     memcpy (lbmptr,palette,768);
00344     lbmptr += 768;
00345 
00346     length = lbmptr-(byte *)cmaplength-4;
00347     *cmaplength = BigLong(length);
00348     if (length&1)
00349         *lbmptr++ = 0;          // pad chunk to even offset
00350 
00351 //
00352 // write BODY
00353 //
00354     *lbmptr++ = 'B';
00355     *lbmptr++ = 'O';
00356     *lbmptr++ = 'D';
00357     *lbmptr++ = 'Y';
00358 
00359     bodylength = (int *)lbmptr;
00360     lbmptr+=4;                      // leave space for length
00361 
00362     memcpy (lbmptr,data,width*height);
00363     lbmptr += width*height;
00364 
00365     length = lbmptr-(byte *)bodylength-4;
00366     *bodylength = BigLong(length);
00367     if (length&1)
00368         *lbmptr++ = 0;          // pad chunk to even offset
00369 
00370 //
00371 // done
00372 //
00373     length = lbmptr-(byte *)formlength-4;
00374     *formlength = BigLong(length);
00375     if (length&1)
00376         *lbmptr++ = 0;          // pad chunk to even offset
00377 
00378 //
00379 // write output file
00380 //
00381     SaveFile (filename, lbm, lbmptr-lbm);
00382     free (lbm);
00383 }
00384 
00385 /*
00386 ============================================================================
00387 
00388 LOAD PCX
00389 
00390 ============================================================================
00391 */
00392 typedef struct
00393 {
00394     char    manufacturer;
00395     char    version;
00396     char    encoding;
00397     char    bits_per_pixel;
00398     unsigned short  xmin,ymin,xmax,ymax;
00399     unsigned short  hres,vres;
00400     unsigned char   palette[48];
00401     char    reserved;
00402     char    color_planes;
00403     unsigned short  bytes_per_line;
00404     unsigned short  palette_type;
00405     char    filler[58];
00406     unsigned char   data;           // unbounded
00407 } pcx_t;
00408 
00409 /*
00410 ==============
00411 LoadPCX
00412 ==============
00413 */
00414 void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
00415 {
00416     byte    *raw = 0;
00417     pcx_t   *pcx;
00418     int     x, y;
00419     int     len;
00420     int     dataByte, runLength;
00421     byte    *out, *pix;
00422 
00423     if (pic)
00424         *pic = NULL;
00425     if (palette)
00426         *palette = NULL;
00427     if (width)
00428         *width = 0;
00429     if (height)
00430         *height = 0;
00431 
00432     //
00433     // load the file
00434     //
00435     len = LoadFile (filename, (void **)&raw);
00436     if (len == -1)
00437         return;
00438 
00439     //
00440     // parse the PCX file
00441     //
00442     pcx = (pcx_t *)raw;
00443     raw = &pcx->data;
00444 
00445     pcx->xmin = LittleShort(pcx->xmin);
00446     pcx->ymin = LittleShort(pcx->ymin);
00447     pcx->xmax = LittleShort(pcx->xmax);
00448     pcx->ymax = LittleShort(pcx->ymax);
00449     pcx->hres = LittleShort(pcx->hres);
00450     pcx->vres = LittleShort(pcx->vres);
00451     pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
00452     pcx->palette_type = LittleShort(pcx->palette_type);
00453 
00454     if (pcx->manufacturer != 0x0a
00455         || pcx->version != 5
00456         || pcx->encoding != 1
00457         || pcx->bits_per_pixel != 8
00458         || pcx->xmax >= 640
00459         || pcx->ymax >= 480)
00460         Error ("Bad pcx file %s", filename);
00461     
00462     if (palette)
00463     {
00464         *palette = (unsigned char*)malloc(768);
00465         memcpy (*palette, (byte *)pcx + len - 768, 768);
00466     }
00467 
00468     if (width)
00469         *width = pcx->xmax+1;
00470     if (height)
00471         *height = pcx->ymax+1;
00472 
00473     if (!pic)
00474   {
00475     free(pcx);
00476         return;
00477   }
00478 
00479     out = (unsigned char*)malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
00480     if (!out)
00481         Error ("Skin_Cache: couldn't allocate");
00482 
00483     *pic = out;
00484 
00485     pix = out;
00486 
00487     for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
00488     {
00489         for (x=0 ; x<=pcx->xmax ; )
00490         {
00491             dataByte = *raw++;
00492 
00493             if((dataByte & 0xC0) == 0xC0)
00494             {
00495                 runLength = dataByte & 0x3F;
00496                 dataByte = *raw++;
00497             }
00498             else
00499                 runLength = 1;
00500 
00501             while(runLength-- > 0)
00502                 pix[x++] = dataByte;
00503         }
00504 
00505     }
00506 
00507     if ( raw - (byte *)pcx > len)
00508         Error ("PCX file %s was malformed", filename);
00509 
00510     free (pcx);
00511 }
00512 /* 
00513 ============== 
00514 WritePCXfile 
00515 ============== 
00516 */ 
00517 void WritePCXfile (char *filename, byte *data, 
00518                    int width, int height, byte *palette) 
00519 {
00520     int     i, j, length;
00521     pcx_t   *pcx;
00522     byte        *pack;
00523       
00524     pcx = (pcx_t*)malloc (width*height*2+1000);
00525     memset (pcx, 0, sizeof(*pcx));
00526 
00527     pcx->manufacturer = 0x0a;   // PCX id
00528     pcx->version = 5;           // 256 color
00529     pcx->encoding = 1;      // uncompressed
00530     pcx->bits_per_pixel = 8;        // 256 color
00531     pcx->xmin = 0;
00532     pcx->ymin = 0;
00533     pcx->xmax = LittleShort((short)(width-1));
00534     pcx->ymax = LittleShort((short)(height-1));
00535     pcx->hres = LittleShort((short)width);
00536     pcx->vres = LittleShort((short)height);
00537     pcx->color_planes = 1;      // chunky image
00538     pcx->bytes_per_line = LittleShort((short)width);
00539     pcx->palette_type = LittleShort(2);     // not a grey scale
00540 
00541     // pack the image
00542     pack = &pcx->data;
00543     
00544     for (i=0 ; i<height ; i++)
00545     {
00546         for (j=0 ; j<width ; j++)
00547         {
00548             if ( (*data & 0xc0) != 0xc0)
00549                 *pack++ = *data++;
00550             else
00551             {
00552                 *pack++ = 0xc1;
00553                 *pack++ = *data++;
00554             }
00555         }
00556     }
00557             
00558     // write the palette
00559     *pack++ = 0x0c; // palette ID byte
00560     for (i=0 ; i<768 ; i++)
00561         *pack++ = *palette++;
00562         
00563 // write output file 
00564     length = pack - (byte *)pcx;
00565     SaveFile (filename, pcx, length);
00566 
00567     free (pcx);
00568 } 
00569 
00570 /*
00571 ============================================================================
00572 
00573 LOAD IMAGE
00574 
00575 ============================================================================
00576 */
00577 
00578 /*
00579 ==============
00580 Load256Image
00581 
00582 Will load either an lbm or pcx, depending on extension.
00583 Any of the return pointers can be NULL if you don't want them.
00584 ==============
00585 */
00586 void Load256Image (char *name, byte **pixels, byte **palette,
00587                    int *width, int *height)
00588 {
00589     char    ext[128];
00590     bitmap_t    bmp;
00591 
00592     ExtractFileExtension (name, ext);
00593     if (stricmp(ext, "lbm"))
00594     {
00595         LoadLBM (name, pixels, palette);
00596         if (width)
00597             *width = bmhd.w;
00598         if (height)
00599             *height = bmhd.h;
00600     }
00601     else if (stricmp (ext, "pcx"))
00602     {
00603         LoadPCX (name, pixels, palette, width, height);
00604     }
00605     else if (stricmp (ext, "bmp"))
00606     {
00607         LoadBMP (name, &bmp);
00608         if (bmp.palette)
00609         {
00610             *palette = (unsigned char*)malloc (768);
00611             memcpy (*palette, bmp.palette, 768);
00612         }
00613         FreeBMP (&bmp);     
00614     }
00615     else
00616         Error ("%s doesn't have a known image extension", name);
00617 }
00618 
00619 
00620 /*
00621 ==============
00622 Save256Image
00623 
00624 Will save either an lbm or pcx, depending on extension.
00625 ==============
00626 */
00627 void Save256Image (char *name, byte *pixels, byte *palette,
00628                    int width, int height)
00629 {
00630     char    ext[128];
00631 
00632     ExtractFileExtension (name, ext);
00633     if (!strcmp (ext, "lbm"))
00634     {
00635         WriteLBMfile (name, pixels, width, height, palette);
00636     }
00637     else if (!stricmp (ext, "pcx"))
00638     {
00639         WritePCXfile (name, pixels, width, height, palette);
00640     }
00641     else
00642         Error ("%s doesn't have a known image extension", name);
00643 }
00644 
00645 
00646 
00647 /*
00648 ============================================================================
00649 
00650 TARGA IMAGE
00651 
00652 ============================================================================
00653 */
00654 typedef struct _TargaHeader {
00655     unsigned char   id_length, colormap_type, image_type;
00656     unsigned short  colormap_index, colormap_length;
00657     unsigned char   colormap_size;
00658     unsigned short  x_origin, y_origin, width, height;
00659     unsigned char   pixel_size, attributes;
00660 } TargaHeader;
00661 
00662 int fgetLittleShort (FILE *f)
00663 {
00664     byte    b1, b2;
00665 
00666     b1 = fgetc(f);
00667     b2 = fgetc(f);
00668 
00669     return (short)(b1 + b2*256);
00670 }
00671 
00672 int getLittleShort (byte*& p)
00673 {
00674     byte    b1, b2;
00675     b1 = *p++;
00676     b2 = *p++;
00677     return (short)(b1 + b2*256);
00678 }
00679 
00680 int getLittleLong (byte*& p)
00681 {
00682     byte    b1, b2, b3, b4;
00683 
00684     b1 = *p++;
00685     b2 = *p++;
00686     b3 = *p++;
00687     b4 = *p++;
00688     return b1 + (b2<<8) + (b3<<16) + (b4<<24);
00689 }
00690 
00691 char getc(byte*& p)
00692 {
00693   return *p++;
00694 }
00695 
00696 /*
00697 =========================================================
00698 
00699 BMP LOADING
00700 
00701 =========================================================
00702 */
00703 typedef struct
00704 {
00705     char id[2];
00706     unsigned long fileSize;
00707     unsigned long reserved0;
00708     unsigned long bitmapDataOffset;
00709     unsigned long bitmapHeaderSize;
00710     unsigned long width;
00711     unsigned long height;
00712     unsigned short planes;
00713     unsigned short bitsPerPixel;
00714     unsigned long compression;
00715     unsigned long bitmapDataSize;
00716     unsigned long hRes;
00717     unsigned long vRes;
00718     unsigned long colors;
00719     unsigned long importantColors;
00720     unsigned char palette[256][4];
00721 } BMPHeader_t;
00722 
00723 static void LoadBMP( const char *name, byte **pic, int *width, int *height )
00724 {
00725     int     columns, rows, numPixels;
00726     byte    *pixbuf;
00727     int     row, column;
00728     byte    *buf_p;
00729     byte    *buffer;
00730     unsigned int        length;
00731     BMPHeader_t bmpHeader;
00732     byte        *bmpRGBA;
00733 
00734     *pic = NULL;
00735 
00736     //
00737     // load the file
00738     //
00739     length = LoadFile( ( char * ) name, (void **)&buffer);
00740     if (length == -1)
00741   {
00742     length = PakLoadAnyFile( (char*)name, (void**)&buffer);
00743     if (length == -1)
00744     {
00745           return;
00746     }
00747   }
00748 
00749     buf_p = buffer;
00750 
00751     bmpHeader.id[0] = *buf_p++;
00752     bmpHeader.id[1] = *buf_p++;
00753     bmpHeader.fileSize = LittleLong( * ( long * ) buf_p );
00754     buf_p += 4;
00755     bmpHeader.reserved0 = LittleLong( * ( long * ) buf_p );
00756     buf_p += 4;
00757     bmpHeader.bitmapDataOffset = LittleLong( * ( long * ) buf_p );
00758     buf_p += 4;
00759     bmpHeader.bitmapHeaderSize = LittleLong( * ( long * ) buf_p );
00760     buf_p += 4;
00761     bmpHeader.width = LittleLong( * ( long * ) buf_p );
00762     buf_p += 4;
00763     bmpHeader.height = LittleLong( * ( long * ) buf_p );
00764     buf_p += 4;
00765     bmpHeader.planes = LittleShort( * ( short * ) buf_p );
00766     buf_p += 2;
00767     bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p );
00768     buf_p += 2;
00769     bmpHeader.compression = LittleLong( * ( long * ) buf_p );
00770     buf_p += 4;
00771     bmpHeader.bitmapDataSize = LittleLong( * ( long * ) buf_p );
00772     buf_p += 4;
00773     bmpHeader.hRes = LittleLong( * ( long * ) buf_p );
00774     buf_p += 4;
00775     bmpHeader.vRes = LittleLong( * ( long * ) buf_p );
00776     buf_p += 4;
00777     bmpHeader.colors = LittleLong( * ( long * ) buf_p );
00778     buf_p += 4;
00779     bmpHeader.importantColors = LittleLong( * ( long * ) buf_p );
00780     buf_p += 4;
00781 
00782     memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
00783 
00784     if ( bmpHeader.bitsPerPixel == 8 )
00785         buf_p += 1024;
00786 
00787     if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' ) 
00788     {
00789         Sys_Printf("LoadBMP: only Windows-style BMP files supported (%s)\n", name );
00790     }
00791     if ( bmpHeader.fileSize != length )
00792     {
00793         Sys_Printf("LoadBMP: header size does not match file size (%d vs. %d) (%s)\n", bmpHeader.fileSize, length, name );
00794     }
00795     if ( bmpHeader.compression != 0 )
00796     {
00797         Sys_Printf("LoadBMP: only uncompressed BMP files supported (%s)\n", name );
00798     }
00799     if ( bmpHeader.bitsPerPixel < 8 )
00800     {
00801         Sys_Printf("LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name );
00802     }
00803 
00804     columns = bmpHeader.width;
00805     rows = bmpHeader.height;
00806     if ( rows < 0 )
00807         rows = -rows;
00808     numPixels = columns * rows;
00809 
00810     if ( width ) 
00811         *width = columns;
00812     if ( height )
00813         *height = rows;
00814 
00815     bmpRGBA = reinterpret_cast<unsigned char*>(malloc( numPixels * 4 ));
00816     *pic = bmpRGBA;
00817 
00818 
00819     for ( row = rows-1; row >= 0; row-- )
00820     {
00821         pixbuf = bmpRGBA + row*columns*4;
00822 
00823         for ( column = 0; column < columns; column++ )
00824         {
00825             unsigned char red, green, blue, alpha;
00826             int palIndex;
00827             unsigned short shortPixel;
00828 
00829             switch ( bmpHeader.bitsPerPixel )
00830             {
00831             case 8:
00832                 palIndex = *buf_p++;
00833                 *pixbuf++ = bmpHeader.palette[palIndex][2];
00834                 *pixbuf++ = bmpHeader.palette[palIndex][1];
00835                 *pixbuf++ = bmpHeader.palette[palIndex][0];
00836                 *pixbuf++ = 0xff;
00837                 break;
00838             case 16:
00839                 shortPixel = * ( unsigned short * ) pixbuf;
00840                 pixbuf += 2;
00841                 *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
00842                 *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
00843                 *pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
00844                 *pixbuf++ = 0xff;
00845                 break;
00846 
00847             case 24:
00848                 blue = *buf_p++;
00849                 green = *buf_p++;
00850                 red = *buf_p++;
00851                 *pixbuf++ = red;
00852                 *pixbuf++ = green;
00853                 *pixbuf++ = blue;
00854                 *pixbuf++ = 255;
00855                 break;
00856             case 32:
00857                 blue = *buf_p++;
00858                 green = *buf_p++;
00859                 red = *buf_p++;
00860                 alpha = *buf_p++;
00861                 *pixbuf++ = red;
00862                 *pixbuf++ = green;
00863                 *pixbuf++ = blue;
00864                 *pixbuf++ = alpha;
00865                 break;
00866             default:
00867                 Sys_Printf("LoadBMP: illegal pixel_size '%d' in file '%s'\n", bmpHeader.bitsPerPixel, name );
00868                 break;
00869             }
00870         }
00871     }
00872 
00873     free( buffer );
00874 
00875 }
00876 
00877 
00878 /*
00879 =================================================================
00880 
00881 PCX LOADING
00882 
00883 =================================================================
00884 */
00885 
00886 
00887 /*
00888 ==============
00889 LoadPCX
00890 ==============
00891 */
00892 static void LoadPCX ( const char *filename, byte **pic, byte **palette, int *width, int *height)
00893 {
00894     byte    *raw;
00895     pcx_t   *pcx;
00896     int     x, y;
00897     int     len;
00898     int     dataByte, runLength;
00899     byte    *out, *pix;
00900     int     xmax, ymax;
00901 
00902     *pic = NULL;
00903     *palette = NULL;
00904 
00905     //
00906     // load the file
00907     //
00908     len = LoadFile( ( char * ) filename, (void **)&raw);
00909     if (len == -1) 
00910   {
00911     len = PakLoadAnyFile( (char*)filename, (void**)&raw);
00912     if (len == -1)
00913     {
00914           return;
00915     }
00916     }
00917 
00918     //
00919     // parse the PCX file
00920     //
00921     pcx = (pcx_t *)raw;
00922     raw = &pcx->data;
00923 
00924     xmax = LittleShort(pcx->xmax);
00925     ymax = LittleShort(pcx->ymax);
00926 
00927     if (pcx->manufacturer != 0x0a
00928         || pcx->version != 5
00929         || pcx->encoding != 1
00930         || pcx->bits_per_pixel != 8
00931         || xmax >= 1024
00932         || ymax >= 1024)
00933     {
00934         Sys_Printf ("Bad pcx file %s (%i x %i) (%i x %i)\n", filename, xmax+1, ymax+1, pcx->xmax, pcx->ymax);
00935         return;
00936     }
00937 
00938     out = reinterpret_cast<unsigned char*>(malloc ( (ymax+1) * (xmax+1) ));
00939 
00940     *pic = out;
00941 
00942     pix = out;
00943 
00944     if (palette)
00945     {
00946         *palette = reinterpret_cast<unsigned char*>(malloc(768));
00947         memcpy (*palette, (byte *)pcx + len - 768, 768);
00948     }
00949 
00950     if (width)
00951         *width = xmax+1;
00952     if (height)
00953         *height = ymax+1;
00954 // FIXME: use bytes_per_line here?
00955 
00956     for (y=0 ; y<=ymax ; y++, pix += xmax+1)
00957     {
00958         for (x=0 ; x<=xmax ; )
00959         {
00960             dataByte = *raw++;
00961 
00962             if((dataByte & 0xC0) == 0xC0)
00963             {
00964                 runLength = dataByte & 0x3F;
00965                 dataByte = *raw++;
00966             }
00967             else
00968                 runLength = 1;
00969 
00970             while(runLength-- > 0)
00971                 pix[x++] = dataByte;
00972         }
00973 
00974     }
00975 
00976     if ( raw - (byte *)pcx > len)
00977     {
00978         Sys_Printf ("PCX file %s was malformed", filename);
00979         free (*pic);
00980         *pic = NULL;
00981     }
00982 
00983     free(pcx);
00984 }
00985 
00986 
00987 /*
00988 ==============
00989 LoadPCX32
00990 ==============
00991 */
00992 static void LoadPCX32 ( const char *filename, byte **pic, int *width, int *height) {
00993     byte    *palette;
00994     byte    *pic8;
00995     int     i, c, p;
00996     byte    *pic32;
00997 
00998     LoadPCX (filename, &pic8, &palette, width, height);
00999     if (!pic8) {
01000         *pic = NULL;
01001         return;
01002     }
01003 
01004     c = (*width) * (*height);
01005     pic32 = *pic = reinterpret_cast<unsigned char*>(malloc(4 * c ));
01006     for (i = 0 ; i < c ; i++) {
01007         p = pic8[i];
01008         pic32[0] = palette[p*3];
01009         pic32[1] = palette[p*3 + 1];
01010         pic32[2] = palette[p*3 + 2];
01011         pic32[3] = 255;
01012         pic32 += 4;
01013     }
01014 
01015     free (pic8);
01016     free (palette);
01017 }
01018 
01019 /*
01020 =========================================================
01021 
01022 TARGA LOADING
01023 
01024 =========================================================
01025 */
01026 
01027 /*
01028 =============
01029 LoadTGA
01030 =============
01031 */
01032 void LoadTGA ( const char *name, byte **pic, int *width, int *height)
01033 {
01034     int     columns, rows, numPixels;
01035     byte    *pixbuf;
01036     int     row, column;
01037     byte    *buf_p;
01038     byte    *buffer;
01039     TargaHeader targa_header;
01040     byte        *targa_rgba;
01041 
01042     *pic = NULL;
01043 
01044     //
01045     // load the file
01046     //
01047     int nLen = LoadFile ( ( char * ) name, (void **)&buffer);
01048     if (nLen == -1) 
01049   {
01050     nLen = PakLoadAnyFile((char*)name, (void**)&buffer);
01051     if (nLen == -1)
01052     {
01053           return;
01054     }
01055     }
01056 
01057     buf_p = buffer;
01058 
01059     targa_header.id_length = *buf_p++;
01060     targa_header.colormap_type = *buf_p++;
01061     targa_header.image_type = *buf_p++;
01062     
01063     targa_header.colormap_index = LittleShort ( *(short *)buf_p );
01064     buf_p += 2;
01065     targa_header.colormap_length = LittleShort ( *(short *)buf_p );
01066     buf_p += 2;
01067     targa_header.colormap_size = *buf_p++;
01068     targa_header.x_origin = LittleShort ( *(short *)buf_p );
01069     buf_p += 2;
01070     targa_header.y_origin = LittleShort ( *(short *)buf_p );
01071     buf_p += 2;
01072     targa_header.width = LittleShort ( *(short *)buf_p );
01073     buf_p += 2;
01074     targa_header.height = LittleShort ( *(short *)buf_p );
01075     buf_p += 2;
01076     targa_header.pixel_size = *buf_p++;
01077     targa_header.attributes = *buf_p++;
01078 
01079     //++timo debug
01080     if (targa_header.pixel_size == 32)
01081         Sys_Printf("%s is 32bit\n", name);
01082     bool bAlphaOK = false;
01083 
01084     if (targa_header.image_type!=2 
01085         && targa_header.image_type!=10
01086         && targa_header.image_type != 3 ) 
01087     {
01088         Sys_Printf("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
01089     }
01090 
01091     if ( targa_header.colormap_type != 0 )
01092     {
01093         Sys_Printf("LoadTGA: colormaps not supported\n" );
01094     }
01095 
01096     if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
01097     {
01098         Sys_Printf("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
01099     }
01100 
01101     columns = targa_header.width;
01102     rows = targa_header.height;
01103     numPixels = columns * rows;
01104 
01105     if (width)
01106         *width = columns;
01107     if (height)
01108         *height = rows;
01109 
01110     targa_rgba = reinterpret_cast<unsigned char*>(malloc (numPixels*4));
01111     *pic = targa_rgba;
01112 
01113     if (targa_header.id_length != 0)
01114         buf_p += targa_header.id_length;  // skip TARGA image comment
01115     
01116     if ( targa_header.image_type==2 || targa_header.image_type == 3 )
01117     { 
01118         // Uncompressed RGB or gray scale image
01119         for(row=rows-1; row>=0; row--) 
01120         {
01121             pixbuf = targa_rgba + row*columns*4;
01122             for(column=0; column<columns; column++) 
01123             {
01124                 unsigned char red,green,blue,alphabyte;
01125                 switch (targa_header.pixel_size) 
01126                 {
01127                     
01128                 case 8:
01129                     blue = *buf_p++;
01130                     green = blue;
01131                     red = blue;
01132                     *pixbuf++ = red;
01133                     *pixbuf++ = green;
01134                     *pixbuf++ = blue;
01135                     *pixbuf++ = 255;
01136                     break;
01137 
01138                 case 24:
01139                     blue = *buf_p++;
01140                     green = *buf_p++;
01141                     red = *buf_p++;
01142                     *pixbuf++ = red;
01143                     *pixbuf++ = green;
01144                     *pixbuf++ = blue;
01145                     *pixbuf++ = 255;
01146                     break;
01147                 case 32:
01148                     blue = *buf_p++;
01149                     green = *buf_p++;
01150                     red = *buf_p++;
01151                     alphabyte = *buf_p++;
01152                     //++timo debug: detect if the whole alpha channel is 0
01153                     if (alphabyte != 0)
01154                         bAlphaOK = true;
01155                     *pixbuf++ = red;
01156                     *pixbuf++ = green;
01157                     *pixbuf++ = blue;
01158                     *pixbuf++ = alphabyte;
01159                     break;
01160                 default:
01161                     Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
01162                     break;
01163                 }
01164             }
01165         }
01166 
01167         //++timo debug
01168         if (bAlphaOK)
01169             Sys_Printf("alpha channel OK");
01170         else
01171             Sys_Printf("empty alpha channel!");
01172     }
01173     else if (targa_header.image_type==10) {   // Runlength encoded RGB images
01174 
01175         //++timo debug
01176         Sys_Printf("runlength encode RGB image");
01177 
01178         unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
01179 
01180         red = 0;
01181         green = 0;
01182         blue = 0;
01183         alphabyte = 0xff;
01184 
01185         for(row=rows-1; row>=0; row--) {
01186             pixbuf = targa_rgba + row*columns*4;
01187             for(column=0; column<columns; ) {
01188                 packetHeader= *buf_p++;
01189                 packetSize = 1 + (packetHeader & 0x7f);
01190                 if (packetHeader & 0x80) {        // run-length packet
01191                     switch (targa_header.pixel_size) {
01192                         case 24:
01193                                 blue = *buf_p++;
01194                                 green = *buf_p++;
01195                                 red = *buf_p++;
01196                                 alphabyte = 255;
01197                                 break;
01198                         case 32:
01199                                 blue = *buf_p++;
01200                                 green = *buf_p++;
01201                                 red = *buf_p++;
01202                                 alphabyte = *buf_p++;
01203                                 break;
01204                         default:
01205                             Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
01206                             break;
01207                     }
01208     
01209                     for(j=0;j<packetSize;j++) {
01210                         *pixbuf++=red;
01211                         *pixbuf++=green;
01212                         *pixbuf++=blue;
01213                         *pixbuf++=alphabyte;
01214                         column++;
01215                         if (column==columns) { // run spans across rows
01216                             column=0;
01217                             if (row>0)
01218                                 row--;
01219                             else
01220                                 goto breakOut;
01221                             pixbuf = targa_rgba + row*columns*4;
01222                         }
01223                     }
01224                 }
01225                 else {                            // non run-length packet
01226                     for(j=0;j<packetSize;j++) {
01227                         switch (targa_header.pixel_size) {
01228                             case 24:
01229                                     blue = *buf_p++;
01230                                     green = *buf_p++;
01231                                     red = *buf_p++;
01232                                     *pixbuf++ = red;
01233                                     *pixbuf++ = green;
01234                                     *pixbuf++ = blue;
01235                                     *pixbuf++ = 255;
01236                                     break;
01237                             case 32:
01238                                     blue = *buf_p++;
01239                                     green = *buf_p++;
01240                                     red = *buf_p++;
01241                                     alphabyte = *buf_p++;
01242                                     *pixbuf++ = red;
01243                                     *pixbuf++ = green;
01244                                     *pixbuf++ = blue;
01245                                     *pixbuf++ = alphabyte;
01246                                     break;
01247                             default:
01248                                 Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
01249                                 break;
01250                         }
01251                         column++;
01252                         if (column==columns) { // pixel packet run spans across rows
01253                             column=0;
01254                             if (row>0)
01255                                 row--;
01256                             else
01257                                 goto breakOut;
01258                             pixbuf = targa_rgba + row*columns*4;
01259                         }                       
01260                     }
01261                 }
01262             }
01263             breakOut:;
01264         }
01265     }
01266 
01267     free(buffer);
01268 }
01269 
01270 
01271 
01272 
01273 void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) 
01274 {
01275   byte  *fbuffer = NULL;
01276   int nLen = LoadFile( ( char * ) filename, (void **)&fbuffer);
01277   if (nLen == -1) 
01278   {
01279     nLen = PakLoadAnyFile((char*)filename, (void**)&fbuffer);
01280     if (nLen == -1)
01281     {
01282           return;
01283     }
01284   }
01285   LoadJPGBuff(fbuffer, pic, width, height);
01286   free(fbuffer);
01287 }
01288 
01289 //===================================================================
01290 
01291 /*
01292 =================
01293 LoadImage
01294 
01295 Loads any of the supported image types into a cannonical
01296 32 bit format.
01297 =================
01298 */
01299 void LoadImage( const char *name, byte **pic, int *width, int *height ) 
01300 {
01301     int     len;
01302     *pic = NULL;
01303     *width = 0;
01304     *height = 0;
01305 
01306     len = strlen(name);
01307     if (len<5) 
01308   {
01309         return;
01310     }
01311 
01312     if ( !stricmp( name+len-4, ".tga" ) ) 
01313   {
01314       LoadTGA( name, pic, width, height );
01315     }
01316   else if ( !stricmp(name+len-4, ".pcx") ) 
01317   {
01318     LoadPCX32( name, pic, width, height );
01319     } 
01320   else if ( !stricmp( name+len-4, ".bmp" ) ) 
01321   {
01322         LoadBMP( name, pic, width, height );
01323     } 
01324   else if ( !stricmp( name+len-4, ".jpg" ) ) 
01325   {
01326         LoadJPG( name, pic, width, height ); 
01327     }
01328 }
01329 

Generated on Thu Aug 25 12:38:30 2005 for Quake III Arena by  doxygen 1.3.9.1