00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00036
00037
00038
00039
00040
00041 typedef unsigned char UBYTE;
00042
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;
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
00099
00100
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;
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
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
00160 picbuffer = NULL;
00161 cmapbuffer = NULL;
00162
00163
00164
00165
00166 LoadFile (filename, (void **)&LBMbuffer);
00167
00168 if (LBMbuffer == NULL)
00169 {
00170 return;
00171 }
00172
00173
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
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
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
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
00269
00270
00271
00272
00273
00274
00275
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
00290
00291 *lbmptr++ = 'F';
00292 *lbmptr++ = 'O';
00293 *lbmptr++ = 'R';
00294 *lbmptr++ = 'M';
00295
00296 formlength = (int*)lbmptr;
00297 lbmptr+=4;
00298
00299 *lbmptr++ = 'P';
00300 *lbmptr++ = 'B';
00301 *lbmptr++ = 'M';
00302 *lbmptr++ = ' ';
00303
00304
00305
00306
00307 *lbmptr++ = 'B';
00308 *lbmptr++ = 'M';
00309 *lbmptr++ = 'H';
00310 *lbmptr++ = 'D';
00311
00312 bmhdlength = (int *)lbmptr;
00313 lbmptr+=4;
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;
00331
00332
00333
00334
00335 *lbmptr++ = 'C';
00336 *lbmptr++ = 'M';
00337 *lbmptr++ = 'A';
00338 *lbmptr++ = 'P';
00339
00340 cmaplength = (int *)lbmptr;
00341 lbmptr+=4;
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;
00350
00351
00352
00353
00354 *lbmptr++ = 'B';
00355 *lbmptr++ = 'O';
00356 *lbmptr++ = 'D';
00357 *lbmptr++ = 'Y';
00358
00359 bodylength = (int *)lbmptr;
00360 lbmptr+=4;
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;
00369
00370
00371
00372
00373 length = lbmptr-(byte *)formlength-4;
00374 *formlength = BigLong(length);
00375 if (length&1)
00376 *lbmptr++ = 0;
00377
00378
00379
00380
00381 SaveFile (filename, lbm, lbmptr-lbm);
00382 free (lbm);
00383 }
00384
00385
00386
00387
00388
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;
00407 } pcx_t;
00408
00409
00410
00411
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
00434
00435 len = LoadFile (filename, (void **)&raw);
00436 if (len == -1)
00437 return;
00438
00439
00440
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
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;
00528 pcx->version = 5;
00529 pcx->encoding = 1;
00530 pcx->bits_per_pixel = 8;
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;
00538 pcx->bytes_per_line = LittleShort((short)width);
00539 pcx->palette_type = LittleShort(2);
00540
00541
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
00559 *pack++ = 0x0c;
00560 for (i=0 ; i<768 ; i++)
00561 *pack++ = *palette++;
00562
00563
00564 length = pack - (byte *)pcx;
00565 SaveFile (filename, pcx, length);
00566
00567 free (pcx);
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
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
00623
00624
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
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
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
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
00882
00883
00884
00885
00886
00887
00888
00889
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
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
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
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
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
01023
01024
01025
01026
01027
01028
01029
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
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
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;
01115
01116 if ( targa_header.image_type==2 || targa_header.image_type == 3 )
01117 {
01118
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
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
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) {
01174
01175
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) {
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) {
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 {
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) {
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
01294
01295
01296
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