Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

imagelib.c (24251B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 // imagelib.c
     23 
     24 #include "cmdlib.h"
     25 #include "imagelib.h"
     26 
     27 
     28 int fgetLittleShort (FILE *f)
     29 {
     30 	byte	b1, b2;
     31 
     32 	b1 = fgetc(f);
     33 	b2 = fgetc(f);
     34 
     35 	return (short)(b1 + b2*256);
     36 }
     37 
     38 int fgetLittleLong (FILE *f)
     39 {
     40 	byte	b1, b2, b3, b4;
     41 
     42 	b1 = fgetc(f);
     43 	b2 = fgetc(f);
     44 	b3 = fgetc(f);
     45 	b4 = fgetc(f);
     46 
     47 	return b1 + (b2<<8) + (b3<<16) + (b4<<24);
     48 }
     49 
     50 
     51 
     52 /*
     53 ============================================================================
     54 
     55 						LBM STUFF
     56 
     57 ============================================================================
     58 */
     59 
     60 
     61 typedef unsigned char	UBYTE;
     62 //conflicts with windows typedef short			WORD;
     63 typedef unsigned short	UWORD;
     64 typedef long			LONG;
     65 
     66 typedef enum
     67 {
     68 	ms_none,
     69 	ms_mask,
     70 	ms_transcolor,
     71 	ms_lasso
     72 } mask_t;
     73 
     74 typedef enum
     75 {
     76 	cm_none,
     77 	cm_rle1
     78 } compress_t;
     79 
     80 typedef struct
     81 {
     82 	UWORD		w,h;
     83 	short		x,y;
     84 	UBYTE		nPlanes;
     85 	UBYTE		masking;
     86 	UBYTE		compression;
     87 	UBYTE		pad1;
     88 	UWORD		transparentColor;
     89 	UBYTE		xAspect,yAspect;
     90 	short		pageWidth,pageHeight;
     91 } bmhd_t;
     92 
     93 extern	bmhd_t	bmhd;						// will be in native byte order
     94 
     95 
     96 
     97 #define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
     98 #define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
     99 #define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
    100 #define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
    101 #define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
    102 #define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
    103 
    104 
    105 bmhd_t  bmhd;
    106 
    107 int    Align (int l)
    108 {
    109 	if (l&1)
    110 		return l+1;
    111 	return l;
    112 }
    113 
    114 
    115 
    116 /*
    117 ================
    118 LBMRLEdecompress
    119 
    120 Source must be evenly aligned!
    121 ================
    122 */
    123 byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
    124 {
    125 	int     count;
    126 	byte    b,rept;
    127 
    128 	count = 0;
    129 
    130 	do
    131 	{
    132 		rept = *source++;
    133 
    134 		if (rept > 0x80)
    135 		{
    136 			rept = (rept^0xff)+2;
    137 			b = *source++;
    138 			memset(unpacked,b,rept);
    139 			unpacked += rept;
    140 		}
    141 		else if (rept < 0x80)
    142 		{
    143 			rept++;
    144 			memcpy(unpacked,source,rept);
    145 			unpacked += rept;
    146 			source += rept;
    147 		}
    148 		else
    149 			rept = 0;               // rept of 0x80 is NOP
    150 
    151 		count += rept;
    152 
    153 	} while (count<bpwidth);
    154 
    155 	if (count>bpwidth)
    156 		Error ("Decompression exceeded width!\n");
    157 
    158 
    159 	return source;
    160 }
    161 
    162 
    163 /*
    164 =================
    165 LoadLBM
    166 =================
    167 */
    168 void LoadLBM (const char *filename, byte **picture, byte **palette)
    169 {
    170 	byte    *LBMbuffer, *picbuffer, *cmapbuffer;
    171 	int             y;
    172 	byte    *LBM_P, *LBMEND_P;
    173 	byte    *pic_p;
    174 	byte    *body_p;
    175 
    176 	int    formtype,formlength;
    177 	int    chunktype,chunklength;
    178 
    179 // qiet compiler warnings
    180 	picbuffer = NULL;
    181 	cmapbuffer = NULL;
    182 
    183 //
    184 // load the LBM
    185 //
    186 	LoadFile (filename, (void **)&LBMbuffer);
    187 
    188 //
    189 // parse the LBM header
    190 //
    191 	LBM_P = LBMbuffer;
    192 	if ( *(int *)LBMbuffer != LittleLong(FORMID) )
    193 	   Error ("No FORM ID at start of file!\n");
    194 
    195 	LBM_P += 4;
    196 	formlength = BigLong( *(int *)LBM_P );
    197 	LBM_P += 4;
    198 	LBMEND_P = LBM_P + Align(formlength);
    199 
    200 	formtype = LittleLong(*(int *)LBM_P);
    201 
    202 	if (formtype != ILBMID && formtype != PBMID)
    203 		Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
    204 		,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
    205 
    206 	LBM_P += 4;
    207 
    208 //
    209 // parse chunks
    210 //
    211 
    212 	while (LBM_P < LBMEND_P)
    213 	{
    214 		chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
    215 		LBM_P += 4;
    216 		chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
    217 		LBM_P += 4;
    218 
    219 		switch ( chunktype )
    220 		{
    221 		case BMHDID:
    222 			memcpy (&bmhd,LBM_P,sizeof(bmhd));
    223 			bmhd.w = BigShort(bmhd.w);
    224 			bmhd.h = BigShort(bmhd.h);
    225 			bmhd.x = BigShort(bmhd.x);
    226 			bmhd.y = BigShort(bmhd.y);
    227 			bmhd.pageWidth = BigShort(bmhd.pageWidth);
    228 			bmhd.pageHeight = BigShort(bmhd.pageHeight);
    229 			break;
    230 
    231 		case CMAPID:
    232 			cmapbuffer = malloc (768);
    233 			memset (cmapbuffer, 0, 768);
    234 			memcpy (cmapbuffer, LBM_P, chunklength);
    235 			break;
    236 
    237 		case BODYID:
    238 			body_p = LBM_P;
    239 
    240 			pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
    241 			if (formtype == PBMID)
    242 			{
    243 			//
    244 			// unpack PBM
    245 			//
    246 				for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
    247 				{
    248 					if (bmhd.compression == cm_rle1)
    249 						body_p = LBMRLEDecompress ((byte *)body_p
    250 						, pic_p , bmhd.w);
    251 					else if (bmhd.compression == cm_none)
    252 					{
    253 						memcpy (pic_p,body_p,bmhd.w);
    254 						body_p += Align(bmhd.w);
    255 					}
    256 				}
    257 
    258 			}
    259 			else
    260 			{
    261 			//
    262 			// unpack ILBM
    263 			//
    264 				Error ("%s is an interlaced LBM, not packed", filename);
    265 			}
    266 			break;
    267 		}
    268 
    269 		LBM_P += Align(chunklength);
    270 	}
    271 
    272 	free (LBMbuffer);
    273 
    274 	*picture = picbuffer;
    275 
    276 	if (palette)
    277 		*palette = cmapbuffer;
    278 }
    279 
    280 
    281 /*
    282 ============================================================================
    283 
    284 							WRITE LBM
    285 
    286 ============================================================================
    287 */
    288 
    289 /*
    290 ==============
    291 WriteLBMfile
    292 ==============
    293 */
    294 void WriteLBMfile (const char *filename, byte *data,
    295 				   int width, int height, byte *palette)
    296 {
    297 	byte    *lbm, *lbmptr;
    298 	int    *formlength, *bmhdlength, *cmaplength, *bodylength;
    299 	int    length;
    300 	bmhd_t  basebmhd;
    301 
    302 	lbm = lbmptr = malloc (width*height+1000);
    303 
    304 //
    305 // start FORM
    306 //
    307 	*lbmptr++ = 'F';
    308 	*lbmptr++ = 'O';
    309 	*lbmptr++ = 'R';
    310 	*lbmptr++ = 'M';
    311 
    312 	formlength = (int*)lbmptr;
    313 	lbmptr+=4;                      // leave space for length
    314 
    315 	*lbmptr++ = 'P';
    316 	*lbmptr++ = 'B';
    317 	*lbmptr++ = 'M';
    318 	*lbmptr++ = ' ';
    319 
    320 //
    321 // write BMHD
    322 //
    323 	*lbmptr++ = 'B';
    324 	*lbmptr++ = 'M';
    325 	*lbmptr++ = 'H';
    326 	*lbmptr++ = 'D';
    327 
    328 	bmhdlength = (int *)lbmptr;
    329 	lbmptr+=4;                      // leave space for length
    330 
    331 	memset (&basebmhd,0,sizeof(basebmhd));
    332 	basebmhd.w = BigShort((short)width);
    333 	basebmhd.h = BigShort((short)height);
    334 	basebmhd.nPlanes = BigShort(8);
    335 	basebmhd.xAspect = BigShort(5);
    336 	basebmhd.yAspect = BigShort(6);
    337 	basebmhd.pageWidth = BigShort((short)width);
    338 	basebmhd.pageHeight = BigShort((short)height);
    339 
    340 	memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
    341 	lbmptr += sizeof(basebmhd);
    342 
    343 	length = lbmptr-(byte *)bmhdlength-4;
    344 	*bmhdlength = BigLong(length);
    345 	if (length&1)
    346 		*lbmptr++ = 0;          // pad chunk to even offset
    347 
    348 //
    349 // write CMAP
    350 //
    351 	*lbmptr++ = 'C';
    352 	*lbmptr++ = 'M';
    353 	*lbmptr++ = 'A';
    354 	*lbmptr++ = 'P';
    355 
    356 	cmaplength = (int *)lbmptr;
    357 	lbmptr+=4;                      // leave space for length
    358 
    359 	memcpy (lbmptr,palette,768);
    360 	lbmptr += 768;
    361 
    362 	length = lbmptr-(byte *)cmaplength-4;
    363 	*cmaplength = BigLong(length);
    364 	if (length&1)
    365 		*lbmptr++ = 0;          // pad chunk to even offset
    366 
    367 //
    368 // write BODY
    369 //
    370 	*lbmptr++ = 'B';
    371 	*lbmptr++ = 'O';
    372 	*lbmptr++ = 'D';
    373 	*lbmptr++ = 'Y';
    374 
    375 	bodylength = (int *)lbmptr;
    376 	lbmptr+=4;                      // leave space for length
    377 
    378 	memcpy (lbmptr,data,width*height);
    379 	lbmptr += width*height;
    380 
    381 	length = lbmptr-(byte *)bodylength-4;
    382 	*bodylength = BigLong(length);
    383 	if (length&1)
    384 		*lbmptr++ = 0;          // pad chunk to even offset
    385 
    386 //
    387 // done
    388 //
    389 	length = lbmptr-(byte *)formlength-4;
    390 	*formlength = BigLong(length);
    391 	if (length&1)
    392 		*lbmptr++ = 0;          // pad chunk to even offset
    393 
    394 //
    395 // write output file
    396 //
    397 	SaveFile (filename, lbm, lbmptr-lbm);
    398 	free (lbm);
    399 }
    400 
    401 
    402 /*
    403 ============================================================================
    404 
    405 LOAD PCX
    406 
    407 ============================================================================
    408 */
    409 
    410 typedef struct
    411 {
    412     char	manufacturer;
    413     char	version;
    414     char	encoding;
    415     char	bits_per_pixel;
    416     unsigned short	xmin,ymin,xmax,ymax;
    417     unsigned short	hres,vres;
    418     unsigned char	palette[48];
    419     char	reserved;
    420     char	color_planes;
    421     unsigned short	bytes_per_line;
    422     unsigned short	palette_type;
    423     char	filler[58];
    424     unsigned char	data;			// unbounded
    425 } pcx_t;
    426 
    427 
    428 /*
    429 ==============
    430 LoadPCX
    431 ==============
    432 */
    433 void LoadPCX (const char *filename, byte **pic, byte **palette, int *width, int *height)
    434 {
    435 	byte	*raw;
    436 	pcx_t	*pcx;
    437 	int		x, y;
    438 	int		len;
    439 	int		dataByte, runLength;
    440 	byte	*out, *pix;
    441 
    442 	//
    443 	// load the file
    444 	//
    445 	len = LoadFile (filename, (void **)&raw);
    446 
    447 	//
    448 	// parse the PCX file
    449 	//
    450 	pcx = (pcx_t *)raw;
    451 	raw = &pcx->data;
    452 
    453 	pcx->xmin = LittleShort(pcx->xmin);
    454 	pcx->ymin = LittleShort(pcx->ymin);
    455 	pcx->xmax = LittleShort(pcx->xmax);
    456 	pcx->ymax = LittleShort(pcx->ymax);
    457 	pcx->hres = LittleShort(pcx->hres);
    458 	pcx->vres = LittleShort(pcx->vres);
    459 	pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
    460 	pcx->palette_type = LittleShort(pcx->palette_type);
    461 
    462 	if (pcx->manufacturer != 0x0a
    463 		|| pcx->version != 5
    464 		|| pcx->encoding != 1
    465 		|| pcx->bits_per_pixel != 8
    466 		|| pcx->xmax >= 640
    467 		|| pcx->ymax >= 480)
    468 		Error ("Bad pcx file %s", filename);
    469 	
    470 	if (palette)
    471 	{
    472 		*palette = malloc(768);
    473 		memcpy (*palette, (byte *)pcx + len - 768, 768);
    474 	}
    475 
    476 	if (width)
    477 		*width = pcx->xmax+1;
    478 	if (height)
    479 		*height = pcx->ymax+1;
    480 
    481 	if (!pic)
    482 		return;
    483 
    484 	out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
    485 	if (!out)
    486 		Error ("Skin_Cache: couldn't allocate");
    487 
    488 	*pic = out;
    489 
    490 	pix = out;
    491 
    492 	for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
    493 	{
    494 		for (x=0 ; x<=pcx->xmax ; )
    495 		{
    496 			dataByte = *raw++;
    497 
    498 			if((dataByte & 0xC0) == 0xC0)
    499 			{
    500 				runLength = dataByte & 0x3F;
    501 				dataByte = *raw++;
    502 			}
    503 			else
    504 				runLength = 1;
    505 
    506 			// FIXME: this shouldn't happen, but it does.  Are we decoding the file wrong?
    507 			// Truncate runLength so we don't overrun the end of the buffer
    508 			if ( ( y == pcx->ymax ) && ( x + runLength > pcx->xmax + 1 ) ) {
    509 				runLength = pcx->xmax - x + 1;
    510 			}
    511 
    512 			while(runLength-- > 0)
    513 				pix[x++] = dataByte;
    514 		}
    515 
    516 	}
    517 
    518 	if ( raw - (byte *)pcx > len)
    519 		Error ("PCX file %s was malformed", filename);
    520 
    521 	free (pcx);
    522 }
    523 
    524 /* 
    525 ============== 
    526 WritePCXfile 
    527 ============== 
    528 */ 
    529 void WritePCXfile (const char *filename, byte *data, 
    530 				   int width, int height, byte *palette) 
    531 {
    532 	int		i, j, length;
    533 	pcx_t	*pcx;
    534 	byte		*pack;
    535 	  
    536 	pcx = malloc (width*height*2+1000);
    537 	memset (pcx, 0, sizeof(*pcx));
    538 
    539 	pcx->manufacturer = 0x0a;	// PCX id
    540 	pcx->version = 5;			// 256 color
    541  	pcx->encoding = 1;		// uncompressed
    542 	pcx->bits_per_pixel = 8;		// 256 color
    543 	pcx->xmin = 0;
    544 	pcx->ymin = 0;
    545 	pcx->xmax = LittleShort((short)(width-1));
    546 	pcx->ymax = LittleShort((short)(height-1));
    547 	pcx->hres = LittleShort((short)width);
    548 	pcx->vres = LittleShort((short)height);
    549 	pcx->color_planes = 1;		// chunky image
    550 	pcx->bytes_per_line = LittleShort((short)width);
    551 	pcx->palette_type = LittleShort(1);		// not a grey scale
    552 
    553 	// pack the image
    554 	pack = &pcx->data;
    555 	
    556 	for (i=0 ; i<height ; i++)
    557 	{
    558 		for (j=0 ; j<width ; j++)
    559 		{
    560 			if ( (*data & 0xc0) != 0xc0)
    561 				*pack++ = *data++;
    562 			else
    563 			{
    564 				*pack++ = 0xc1;
    565 				*pack++ = *data++;
    566 			}
    567 		}
    568 	}
    569 			
    570 	// write the palette
    571 	*pack++ = 0x0c;	// palette ID byte
    572 	for (i=0 ; i<768 ; i++)
    573 		*pack++ = *palette++;
    574 		
    575 // write output file 
    576 	length = pack - (byte *)pcx;
    577 	SaveFile (filename, pcx, length);
    578 
    579 	free (pcx);
    580 } 
    581  
    582 /*
    583 ============================================================================
    584 
    585 LOAD BMP
    586 
    587 ============================================================================
    588 */
    589 
    590 
    591 /*
    592 
    593 // we can't just use these structures, because
    594 // compiler structure alignment will not be portable
    595 // on this unaligned stuff
    596 
    597 typedef struct tagBITMAPFILEHEADER { // bmfh 
    598         WORD    bfType;				// BM
    599         DWORD   bfSize; 
    600         WORD    bfReserved1; 
    601         WORD    bfReserved2; 
    602         DWORD   bfOffBits; 
    603 } BITMAPFILEHEADER; 
    604  
    605 typedef struct tagBITMAPINFOHEADER{ // bmih 
    606    DWORD  biSize; 
    607    LONG   biWidth; 
    608    LONG   biHeight; 
    609    WORD   biPlanes; 
    610    WORD   biBitCount 
    611    DWORD  biCompression; 
    612    DWORD  biSizeImage; 
    613    LONG   biXPelsPerMeter; 
    614    LONG   biYPelsPerMeter; 
    615    DWORD  biClrUsed; 
    616    DWORD  biClrImportant; 
    617 } BITMAPINFOHEADER; 
    618  
    619 typedef struct tagBITMAPINFO { // bmi 
    620    BITMAPINFOHEADER bmiHeader; 
    621    RGBQUAD          bmiColors[1]; 
    622 } BITMAPINFO; 
    623 
    624 typedef struct tagBITMAPCOREHEADER { // bmch 
    625         DWORD   bcSize; 
    626         WORD    bcWidth; 
    627         WORD    bcHeight; 
    628         WORD    bcPlanes; 
    629         WORD    bcBitCount; 
    630 } BITMAPCOREHEADER; 
    631  
    632 typedef struct _BITMAPCOREINFO {    // bmci 
    633         BITMAPCOREHEADER  bmciHeader; 
    634         RGBTRIPLE         bmciColors[1]; 
    635 } BITMAPCOREINFO; 
    636  
    637 */
    638 
    639 /*
    640 ==============
    641 LoadBMP
    642 ==============
    643 */
    644 void LoadBMP (const char *filename, byte **pic, byte **palette, int *width, int *height)
    645 {
    646 	byte	*out;
    647 	FILE	*fin;
    648 	int		i;
    649     int		bfSize; 
    650     int		bfOffBits; 
    651 	int		structSize;
    652     int		bcWidth; 
    653     int     bcHeight; 
    654     int	    bcPlanes; 
    655     int		bcBitCount; 
    656 	byte	bcPalette[1024];
    657 	qboolean	flipped;
    658 
    659 	fin = fopen (filename, "rb");
    660 	if (!fin) {
    661 		Error ("Couldn't read %s", filename);
    662 	}
    663 
    664 	i = fgetLittleShort (fin);
    665 	if (i != 'B' + ('M'<<8) ) {
    666 		Error ("%s is not a bmp file", filename);
    667 	}
    668 
    669 	bfSize = fgetLittleLong (fin);
    670 	fgetLittleShort(fin);
    671 	fgetLittleShort(fin);
    672 	bfOffBits = fgetLittleLong (fin);
    673 
    674 	// the size will tell us if it is a
    675 	// bitmapinfo or a bitmapcore
    676 	structSize = fgetLittleLong (fin);
    677 	if (structSize == 40) {
    678 		// bitmapinfo
    679         bcWidth = fgetLittleLong(fin); 
    680         bcHeight= fgetLittleLong(fin); 
    681         bcPlanes = fgetLittleShort(fin); 
    682         bcBitCount = fgetLittleShort(fin); 
    683 
    684 		fseek (fin, 24, SEEK_CUR);
    685 
    686 		if (palette) {
    687 			fread (bcPalette, 1, 1024, fin);
    688 			*palette = malloc(768);
    689 
    690 			for (i = 0 ; i < 256 ; i++) {
    691 				(*palette)[i * 3 + 0] = bcPalette[i * 4 + 2];
    692 				(*palette)[i * 3 + 1] = bcPalette[i * 4 + 1];
    693 				(*palette)[i * 3 + 2] = bcPalette[i * 4 + 0];
    694 			}
    695 		}
    696 	} else if (structSize == 12) {
    697 		// bitmapcore
    698         bcWidth = fgetLittleShort(fin); 
    699         bcHeight= fgetLittleShort(fin); 
    700         bcPlanes = fgetLittleShort(fin); 
    701         bcBitCount = fgetLittleShort(fin); 
    702 
    703 		if (palette) {
    704 			fread (bcPalette, 1, 768, fin);
    705 			*palette = malloc(768);
    706 
    707 			for (i = 0 ; i < 256 ; i++) {
    708 				(*palette)[i * 3 + 0] = bcPalette[i * 3 + 2];
    709 				(*palette)[i * 3 + 1] = bcPalette[i * 3 + 1];
    710 				(*palette)[i * 3 + 2] = bcPalette[i * 3 + 0];
    711 			}
    712 		}
    713 	} else {
    714 		Error ("%s had strange struct size", filename);
    715 	}
    716 	
    717 	if (bcPlanes != 1) {
    718 		Error ("%s was not a single plane image", filename);
    719 	}
    720 
    721 	if (bcBitCount != 8) {
    722 		Error ("%s was not an 8 bit image", filename);
    723 	}
    724 
    725 	if (bcHeight < 0) {
    726 		bcHeight = -bcHeight;
    727 		flipped = qtrue;
    728 	} else {
    729 		flipped = qfalse;
    730 	}
    731 
    732 	if (width)
    733 		*width = bcWidth;
    734 	if (height)
    735 		*height = bcHeight;
    736 
    737 	if (!pic) {
    738 		fclose (fin);
    739 		return;
    740 	}
    741 
    742 	out = malloc ( bcWidth * bcHeight );
    743 	*pic = out;
    744 	fseek (fin, bfOffBits, SEEK_SET);
    745 
    746 	if (flipped) {
    747 		for (i = 0 ; i < bcHeight ; i++) {
    748 			fread (out + bcWidth * (bcHeight - 1 - i), 1, bcWidth, fin);
    749 		}
    750 	} else {
    751 		fread (out, 1, bcWidth*bcHeight, fin);
    752 	}
    753 
    754 	fclose (fin);
    755 }
    756 
    757 
    758 /*
    759 ============================================================================
    760 
    761 LOAD IMAGE
    762 
    763 ============================================================================
    764 */
    765 
    766 /*
    767 ==============
    768 Load256Image
    769 
    770 Will load either an lbm or pcx, depending on extension.
    771 Any of the return pointers can be NULL if you don't want them.
    772 ==============
    773 */
    774 void Load256Image (const char *name, byte **pixels, byte **palette,
    775 				   int *width, int *height)
    776 {
    777 	char	ext[128];
    778 
    779 	ExtractFileExtension (name, ext);
    780 	if (!Q_stricmp (ext, "lbm"))
    781 	{
    782 		LoadLBM (name, pixels, palette);
    783 		if (width)
    784 			*width = bmhd.w;
    785 		if (height)
    786 			*height = bmhd.h;
    787 	}
    788 	else if (!Q_stricmp (ext, "pcx"))
    789 	{
    790 		LoadPCX (name, pixels, palette, width, height);
    791 	}
    792 	else if (!Q_stricmp (ext, "bmp"))
    793 	{
    794 		LoadBMP (name, pixels, palette, width, height);
    795 	}
    796 	else
    797 		Error ("%s doesn't have a known image extension", name);
    798 }
    799 
    800 
    801 /*
    802 ==============
    803 Save256Image
    804 
    805 Will save either an lbm or pcx, depending on extension.
    806 ==============
    807 */
    808 void Save256Image (const char *name, byte *pixels, byte *palette,
    809 				   int width, int height)
    810 {
    811 	char	ext[128];
    812 
    813 	ExtractFileExtension (name, ext);
    814 	if (!Q_stricmp (ext, "lbm"))
    815 	{
    816 		WriteLBMfile (name, pixels, width, height, palette);
    817 	}
    818 	else if (!Q_stricmp (ext, "pcx"))
    819 	{
    820 		WritePCXfile (name, pixels, width, height, palette);
    821 	}
    822 	else
    823 		Error ("%s doesn't have a known image extension", name);
    824 }
    825 
    826 
    827 
    828 
    829 /*
    830 ============================================================================
    831 
    832 TARGA IMAGE
    833 
    834 ============================================================================
    835 */
    836 
    837 typedef struct _TargaHeader {
    838 	unsigned char 	id_length, colormap_type, image_type;
    839 	unsigned short	colormap_index, colormap_length;
    840 	unsigned char	colormap_size;
    841 	unsigned short	x_origin, y_origin, width, height;
    842 	unsigned char	pixel_size, attributes;
    843 } TargaHeader;
    844 
    845 /*
    846 =============
    847 LoadTGABuffer
    848 =============
    849 */
    850 void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height)
    851 {
    852 	int		columns, rows, numPixels;
    853 	byte	*pixbuf;
    854 	int		row, column;
    855 	byte	*buf_p;
    856 	TargaHeader	targa_header;
    857 	byte		*targa_rgba;
    858 
    859 	*pic = NULL;
    860 
    861 	buf_p = buffer;
    862 
    863 	targa_header.id_length = *buf_p++;
    864 	targa_header.colormap_type = *buf_p++;
    865 	targa_header.image_type = *buf_p++;
    866 	
    867 	targa_header.colormap_index = LittleShort ( *(short *)buf_p );
    868 	buf_p += 2;
    869 	targa_header.colormap_length = LittleShort ( *(short *)buf_p );
    870 	buf_p += 2;
    871 	targa_header.colormap_size = *buf_p++;
    872 	targa_header.x_origin = LittleShort ( *(short *)buf_p );
    873 	buf_p += 2;
    874 	targa_header.y_origin = LittleShort ( *(short *)buf_p );
    875 	buf_p += 2;
    876 	targa_header.width = LittleShort ( *(short *)buf_p );
    877 	buf_p += 2;
    878 	targa_header.height = LittleShort ( *(short *)buf_p );
    879 	buf_p += 2;
    880 	targa_header.pixel_size = *buf_p++;
    881 	targa_header.attributes = *buf_p++;
    882 
    883 	if (targa_header.image_type!=2 
    884 		&& targa_header.image_type!=10
    885 		&& targa_header.image_type != 3 ) 
    886 	{
    887 		Error("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
    888 	}
    889 
    890 	if ( targa_header.colormap_type != 0 )
    891 	{
    892 		Error("LoadTGA: colormaps not supported\n" );
    893 	}
    894 
    895 	if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
    896 	{
    897 		Error("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
    898 	}
    899 
    900 	columns = targa_header.width;
    901 	rows = targa_header.height;
    902 	numPixels = columns * rows;
    903 
    904 	if (width)
    905 		*width = columns;
    906 	if (height)
    907 		*height = rows;
    908 
    909 	targa_rgba = malloc (numPixels*4);
    910 	*pic = targa_rgba;
    911 
    912 	if (targa_header.id_length != 0)
    913 		buf_p += targa_header.id_length;  // skip TARGA image comment
    914 	
    915 	if ( targa_header.image_type==2 || targa_header.image_type == 3 )
    916 	{ 
    917 		// Uncompressed RGB or gray scale image
    918 		for(row=rows-1; row>=0; row--) 
    919 		{
    920 			pixbuf = targa_rgba + row*columns*4;
    921 			for(column=0; column<columns; column++) 
    922 			{
    923 				unsigned char red,green,blue,alphabyte;
    924 				switch (targa_header.pixel_size) 
    925 				{
    926 					
    927 				case 8:
    928 					blue = *buf_p++;
    929 					green = blue;
    930 					red = blue;
    931 					*pixbuf++ = red;
    932 					*pixbuf++ = green;
    933 					*pixbuf++ = blue;
    934 					*pixbuf++ = 255;
    935 					break;
    936 
    937 				case 24:
    938 					blue = *buf_p++;
    939 					green = *buf_p++;
    940 					red = *buf_p++;
    941 					*pixbuf++ = red;
    942 					*pixbuf++ = green;
    943 					*pixbuf++ = blue;
    944 					*pixbuf++ = 255;
    945 					break;
    946 				case 32:
    947 					blue = *buf_p++;
    948 					green = *buf_p++;
    949 					red = *buf_p++;
    950 					alphabyte = *buf_p++;
    951 					*pixbuf++ = red;
    952 					*pixbuf++ = green;
    953 					*pixbuf++ = blue;
    954 					*pixbuf++ = alphabyte;
    955 					break;
    956 				default:
    957 					//Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
    958 					break;
    959 				}
    960 			}
    961 		}
    962 	}
    963 	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
    964 		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
    965 
    966 		red = 0;
    967 		green = 0;
    968 		blue = 0;
    969 		alphabyte = 0xff;
    970 
    971 		for(row=rows-1; row>=0; row--) {
    972 			pixbuf = targa_rgba + row*columns*4;
    973 			for(column=0; column<columns; ) {
    974 				packetHeader= *buf_p++;
    975 				packetSize = 1 + (packetHeader & 0x7f);
    976 				if (packetHeader & 0x80) {        // run-length packet
    977 					switch (targa_header.pixel_size) {
    978 						case 24:
    979 								blue = *buf_p++;
    980 								green = *buf_p++;
    981 								red = *buf_p++;
    982 								alphabyte = 255;
    983 								break;
    984 						case 32:
    985 								blue = *buf_p++;
    986 								green = *buf_p++;
    987 								red = *buf_p++;
    988 								alphabyte = *buf_p++;
    989 								break;
    990 						default:
    991 							//Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
    992 							break;
    993 					}
    994 	
    995 					for(j=0;j<packetSize;j++) {
    996 						*pixbuf++=red;
    997 						*pixbuf++=green;
    998 						*pixbuf++=blue;
    999 						*pixbuf++=alphabyte;
   1000 						column++;
   1001 						if (column==columns) { // run spans across rows
   1002 							column=0;
   1003 							if (row>0)
   1004 								row--;
   1005 							else
   1006 								goto breakOut;
   1007 							pixbuf = targa_rgba + row*columns*4;
   1008 						}
   1009 					}
   1010 				}
   1011 				else {                            // non run-length packet
   1012 					for(j=0;j<packetSize;j++) {
   1013 						switch (targa_header.pixel_size) {
   1014 							case 24:
   1015 									blue = *buf_p++;
   1016 									green = *buf_p++;
   1017 									red = *buf_p++;
   1018 									*pixbuf++ = red;
   1019 									*pixbuf++ = green;
   1020 									*pixbuf++ = blue;
   1021 									*pixbuf++ = 255;
   1022 									break;
   1023 							case 32:
   1024 									blue = *buf_p++;
   1025 									green = *buf_p++;
   1026 									red = *buf_p++;
   1027 									alphabyte = *buf_p++;
   1028 									*pixbuf++ = red;
   1029 									*pixbuf++ = green;
   1030 									*pixbuf++ = blue;
   1031 									*pixbuf++ = alphabyte;
   1032 									break;
   1033 							default:
   1034 								//Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
   1035 								break;
   1036 						}
   1037 						column++;
   1038 						if (column==columns) { // pixel packet run spans across rows
   1039 							column=0;
   1040 							if (row>0)
   1041 								row--;
   1042 							else
   1043 								goto breakOut;
   1044 							pixbuf = targa_rgba + row*columns*4;
   1045 						}						
   1046 					}
   1047 				}
   1048 			}
   1049 			breakOut:;
   1050 		}
   1051 	}
   1052 
   1053 	//free(buffer);
   1054 }
   1055 
   1056 
   1057 
   1058 /*
   1059 =============
   1060 LoadTGA
   1061 =============
   1062 */
   1063 void LoadTGA (const char *name, byte **pixels, int *width, int *height)
   1064 {
   1065 	byte			*buffer;
   1066   int nLen;
   1067 	//
   1068 	// load the file
   1069 	//
   1070 	nLen = LoadFile ( ( char * ) name, (void **)&buffer);
   1071 	if (nLen == -1) 
   1072   {
   1073 		Error ("Couldn't read %s", name);
   1074   }
   1075 
   1076   LoadTGABuffer(buffer, pixels, width, height);
   1077 
   1078 }
   1079 
   1080 
   1081 /*
   1082 ================
   1083 WriteTGA
   1084 ================
   1085 */
   1086 void WriteTGA (const char *filename, byte *data, int width, int height) {
   1087 	byte	*buffer;
   1088 	int		i;
   1089 	int		c;
   1090 	FILE	*f;
   1091 
   1092 	buffer = malloc(width*height*4 + 18);
   1093 	memset (buffer, 0, 18);
   1094 	buffer[2] = 2;		// uncompressed type
   1095 	buffer[12] = width&255;
   1096 	buffer[13] = width>>8;
   1097 	buffer[14] = height&255;
   1098 	buffer[15] = height>>8;
   1099 	buffer[16] = 32;	// pixel size
   1100 
   1101 	// swap rgb to bgr
   1102 	c = 18 + width * height * 4;
   1103 	for (i=18 ; i<c ; i+=4)
   1104 	{
   1105 		buffer[i] = data[i-18+2];		// blue
   1106 		buffer[i+1] = data[i-18+1];		// green
   1107 		buffer[i+2] = data[i-18+0];		// red
   1108 		buffer[i+3] = data[i-18+3];		// alpha
   1109 	}
   1110 
   1111 	f = fopen (filename, "wb");
   1112 	fwrite (buffer, 1, c, f);
   1113 	fclose (f);
   1114 
   1115 	free (buffer);
   1116 }
   1117 
   1118 /*
   1119 ============================================================================
   1120 
   1121 LOAD32BITIMAGE
   1122 
   1123 ============================================================================
   1124 */
   1125 
   1126 /*
   1127 ==============
   1128 Load32BitImage
   1129 
   1130 Any of the return pointers can be NULL if you don't want them.
   1131 ==============
   1132 */
   1133 void Load32BitImage (const char *name, unsigned **pixels,  int *width, int *height)
   1134 {
   1135 	char	ext[128];
   1136 	byte	*palette;
   1137 	byte	*pixels8;
   1138 	byte	*pixels32;
   1139 	int		size;
   1140 	int		i;
   1141 	int		v;
   1142 
   1143 	ExtractFileExtension (name, ext);
   1144 	if (!Q_stricmp (ext, "tga")) {
   1145 		LoadTGA (name, (byte **)pixels, width, height);
   1146 	} else {
   1147 		Load256Image (name, &pixels8, &palette, width, height);
   1148 		if (!pixels) {
   1149 			return;
   1150 		}
   1151 		size = *width * *height;
   1152 		pixels32 = malloc(size * 4);
   1153 		*pixels = (unsigned *)pixels32;
   1154 		for (i = 0 ; i < size ; i++) {
   1155 			v = pixels8[i];
   1156 			pixels32[i*4 + 0] = palette[ v * 3 + 0 ];
   1157 			pixels32[i*4 + 1] = palette[ v * 3 + 1 ];
   1158 			pixels32[i*4 + 2] = palette[ v * 3 + 2 ];
   1159 			pixels32[i*4 + 3] = 0xff;
   1160 		}
   1161 	}
   1162 }
   1163 
   1164