LBMLIB.CPP (27293B)
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 // lbmlib.c 23 24 #include "stdafx.h" 25 #include "cmdlib.h" 26 #include "lbmlib.h" 27 #include "bmp.h" 28 #include "pakstuff.h" 29 #include "jpeglib.h" 30 31 32 /* 33 ============================================================================ 34 35 LBM STUFF 36 37 ============================================================================ 38 */ 39 40 41 typedef unsigned char UBYTE; 42 //conflicts with windows typedef short WORD; 43 typedef unsigned short UWORD; 44 typedef long LONG; 45 46 typedef enum 47 { 48 ms_none, 49 ms_mask, 50 ms_transcolor, 51 ms_lasso 52 } mask_t; 53 54 typedef enum 55 { 56 cm_none, 57 cm_rle1 58 } compress_t; 59 60 typedef struct 61 { 62 UWORD w,h; 63 short x,y; 64 UBYTE nPlanes; 65 UBYTE masking; 66 UBYTE compression; 67 UBYTE pad1; 68 UWORD transparentColor; 69 UBYTE xAspect,yAspect; 70 short pageWidth,pageHeight; 71 } bmhd_t; 72 73 extern bmhd_t bmhd; // will be in native byte order 74 75 76 77 #define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24)) 78 #define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24)) 79 #define PBMID ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24)) 80 #define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24)) 81 #define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24)) 82 #define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24)) 83 84 85 bmhd_t bmhd; 86 87 int Align (int l) 88 { 89 if (l&1) 90 return l+1; 91 return l; 92 } 93 94 95 96 /* 97 ================ 98 LBMRLEdecompress 99 100 Source must be evenly aligned! 101 ================ 102 */ 103 byte *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth) 104 { 105 int count; 106 byte b,rept; 107 108 count = 0; 109 110 do 111 { 112 rept = *source++; 113 114 if (rept > 0x80) 115 { 116 rept = (rept^0xff)+2; 117 b = *source++; 118 memset(unpacked,b,rept); 119 unpacked += rept; 120 } 121 else if (rept < 0x80) 122 { 123 rept++; 124 memcpy(unpacked,source,rept); 125 unpacked += rept; 126 source += rept; 127 } 128 else 129 rept = 0; // rept of 0x80 is NOP 130 131 count += rept; 132 133 } while (count<bpwidth); 134 135 if (count>bpwidth) 136 Error ("Decompression exceeded width!\n"); 137 138 139 return source; 140 } 141 142 143 /* 144 ================= 145 LoadLBM 146 ================= 147 */ 148 void LoadLBM (char *filename, byte **picture, byte **palette) 149 { 150 byte *LBMbuffer, *picbuffer, *cmapbuffer; 151 int y; 152 byte *LBM_P, *LBMEND_P; 153 byte *pic_p; 154 byte *body_p; 155 156 int formtype,formlength; 157 int chunktype,chunklength; 158 159 // qiet compiler warnings 160 picbuffer = NULL; 161 cmapbuffer = NULL; 162 163 // 164 // load the LBM 165 // 166 LoadFile (filename, (void **)&LBMbuffer); 167 168 if (LBMbuffer == NULL) 169 { 170 return; 171 } 172 // 173 // parse the LBM header 174 // 175 LBM_P = LBMbuffer; 176 if ( *(int *)LBMbuffer != LittleLong(FORMID) ) 177 Error ("No FORM ID at start of file!\n"); 178 179 LBM_P += 4; 180 formlength = BigLong( *(int *)LBM_P ); 181 LBM_P += 4; 182 LBMEND_P = LBM_P + Align(formlength); 183 184 formtype = LittleLong(*(int *)LBM_P); 185 186 if (formtype != ILBMID && formtype != PBMID) 187 Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff 188 ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff); 189 190 LBM_P += 4; 191 192 // 193 // parse chunks 194 // 195 196 while (LBM_P < LBMEND_P) 197 { 198 chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24); 199 LBM_P += 4; 200 chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24); 201 LBM_P += 4; 202 203 switch ( chunktype ) 204 { 205 case BMHDID: 206 memcpy (&bmhd,LBM_P,sizeof(bmhd)); 207 bmhd.w = BigShort(bmhd.w); 208 bmhd.h = BigShort(bmhd.h); 209 bmhd.x = BigShort(bmhd.x); 210 bmhd.y = BigShort(bmhd.y); 211 bmhd.pageWidth = BigShort(bmhd.pageWidth); 212 bmhd.pageHeight = BigShort(bmhd.pageHeight); 213 break; 214 215 case CMAPID: 216 cmapbuffer = (unsigned char*)malloc (768); 217 memset (cmapbuffer, 0, 768); 218 memcpy (cmapbuffer, LBM_P, chunklength); 219 break; 220 221 case BODYID: 222 body_p = LBM_P; 223 224 pic_p = picbuffer = (unsigned char*)malloc (bmhd.w*bmhd.h); 225 if (formtype == PBMID) 226 { 227 // 228 // unpack PBM 229 // 230 for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w) 231 { 232 if (bmhd.compression == cm_rle1) 233 body_p = LBMRLEDecompress ((byte *)body_p 234 , pic_p , bmhd.w); 235 else if (bmhd.compression == cm_none) 236 { 237 memcpy (pic_p,body_p,bmhd.w); 238 body_p += Align(bmhd.w); 239 } 240 } 241 242 } 243 else 244 { 245 // 246 // unpack ILBM 247 // 248 Error ("%s is an interlaced LBM, not packed", filename); 249 } 250 break; 251 } 252 253 LBM_P += Align(chunklength); 254 } 255 256 free (LBMbuffer); 257 258 *picture = picbuffer; 259 260 if (palette) 261 *palette = cmapbuffer; 262 } 263 264 265 /* 266 ============================================================================ 267 268 WRITE LBM 269 270 ============================================================================ 271 */ 272 273 /* 274 ============== 275 WriteLBMfile 276 ============== 277 */ 278 void WriteLBMfile (char *filename, byte *data, 279 int width, int height, byte *palette) 280 { 281 byte *lbm, *lbmptr; 282 int *formlength, *bmhdlength, *cmaplength, *bodylength; 283 int length; 284 bmhd_t basebmhd; 285 286 lbm = lbmptr = (unsigned char*)malloc (width*height+1000); 287 288 // 289 // start FORM 290 // 291 *lbmptr++ = 'F'; 292 *lbmptr++ = 'O'; 293 *lbmptr++ = 'R'; 294 *lbmptr++ = 'M'; 295 296 formlength = (int*)lbmptr; 297 lbmptr+=4; // leave space for length 298 299 *lbmptr++ = 'P'; 300 *lbmptr++ = 'B'; 301 *lbmptr++ = 'M'; 302 *lbmptr++ = ' '; 303 304 // 305 // write BMHD 306 // 307 *lbmptr++ = 'B'; 308 *lbmptr++ = 'M'; 309 *lbmptr++ = 'H'; 310 *lbmptr++ = 'D'; 311 312 bmhdlength = (int *)lbmptr; 313 lbmptr+=4; // leave space for length 314 315 memset (&basebmhd,0,sizeof(basebmhd)); 316 basebmhd.w = BigShort((short)width); 317 basebmhd.h = BigShort((short)height); 318 basebmhd.nPlanes = 8; 319 basebmhd.xAspect = 5; 320 basebmhd.yAspect = 6; 321 basebmhd.pageWidth = BigShort((short)width); 322 basebmhd.pageHeight = BigShort((short)height); 323 324 memcpy (lbmptr,&basebmhd,sizeof(basebmhd)); 325 lbmptr += sizeof(basebmhd); 326 327 length = lbmptr-(byte *)bmhdlength-4; 328 *bmhdlength = BigLong(length); 329 if (length&1) 330 *lbmptr++ = 0; // pad chunk to even offset 331 332 // 333 // write CMAP 334 // 335 *lbmptr++ = 'C'; 336 *lbmptr++ = 'M'; 337 *lbmptr++ = 'A'; 338 *lbmptr++ = 'P'; 339 340 cmaplength = (int *)lbmptr; 341 lbmptr+=4; // leave space for length 342 343 memcpy (lbmptr,palette,768); 344 lbmptr += 768; 345 346 length = lbmptr-(byte *)cmaplength-4; 347 *cmaplength = BigLong(length); 348 if (length&1) 349 *lbmptr++ = 0; // pad chunk to even offset 350 351 // 352 // write BODY 353 // 354 *lbmptr++ = 'B'; 355 *lbmptr++ = 'O'; 356 *lbmptr++ = 'D'; 357 *lbmptr++ = 'Y'; 358 359 bodylength = (int *)lbmptr; 360 lbmptr+=4; // leave space for length 361 362 memcpy (lbmptr,data,width*height); 363 lbmptr += width*height; 364 365 length = lbmptr-(byte *)bodylength-4; 366 *bodylength = BigLong(length); 367 if (length&1) 368 *lbmptr++ = 0; // pad chunk to even offset 369 370 // 371 // done 372 // 373 length = lbmptr-(byte *)formlength-4; 374 *formlength = BigLong(length); 375 if (length&1) 376 *lbmptr++ = 0; // pad chunk to even offset 377 378 // 379 // write output file 380 // 381 SaveFile (filename, lbm, lbmptr-lbm); 382 free (lbm); 383 } 384 385 /* 386 ============================================================================ 387 388 LOAD PCX 389 390 ============================================================================ 391 */ 392 typedef struct 393 { 394 char manufacturer; 395 char version; 396 char encoding; 397 char bits_per_pixel; 398 unsigned short xmin,ymin,xmax,ymax; 399 unsigned short hres,vres; 400 unsigned char palette[48]; 401 char reserved; 402 char color_planes; 403 unsigned short bytes_per_line; 404 unsigned short palette_type; 405 char filler[58]; 406 unsigned char data; // unbounded 407 } pcx_t; 408 409 /* 410 ============== 411 LoadPCX 412 ============== 413 */ 414 void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height) 415 { 416 byte *raw = 0; 417 pcx_t *pcx; 418 int x, y; 419 int len; 420 int dataByte, runLength; 421 byte *out, *pix; 422 423 if (pic) 424 *pic = NULL; 425 if (palette) 426 *palette = NULL; 427 if (width) 428 *width = 0; 429 if (height) 430 *height = 0; 431 432 // 433 // load the file 434 // 435 len = LoadFile (filename, (void **)&raw); 436 if (len == -1) 437 return; 438 439 // 440 // parse the PCX file 441 // 442 pcx = (pcx_t *)raw; 443 raw = &pcx->data; 444 445 pcx->xmin = LittleShort(pcx->xmin); 446 pcx->ymin = LittleShort(pcx->ymin); 447 pcx->xmax = LittleShort(pcx->xmax); 448 pcx->ymax = LittleShort(pcx->ymax); 449 pcx->hres = LittleShort(pcx->hres); 450 pcx->vres = LittleShort(pcx->vres); 451 pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); 452 pcx->palette_type = LittleShort(pcx->palette_type); 453 454 if (pcx->manufacturer != 0x0a 455 || pcx->version != 5 456 || pcx->encoding != 1 457 || pcx->bits_per_pixel != 8 458 || pcx->xmax >= 640 459 || pcx->ymax >= 480) 460 Error ("Bad pcx file %s", filename); 461 462 if (palette) 463 { 464 *palette = (unsigned char*)malloc(768); 465 memcpy (*palette, (byte *)pcx + len - 768, 768); 466 } 467 468 if (width) 469 *width = pcx->xmax+1; 470 if (height) 471 *height = pcx->ymax+1; 472 473 if (!pic) 474 { 475 free(pcx); 476 return; 477 } 478 479 out = (unsigned char*)malloc ( (pcx->ymax+1) * (pcx->xmax+1) ); 480 if (!out) 481 Error ("Skin_Cache: couldn't allocate"); 482 483 *pic = out; 484 485 pix = out; 486 487 for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1) 488 { 489 for (x=0 ; x<=pcx->xmax ; ) 490 { 491 dataByte = *raw++; 492 493 if((dataByte & 0xC0) == 0xC0) 494 { 495 runLength = dataByte & 0x3F; 496 dataByte = *raw++; 497 } 498 else 499 runLength = 1; 500 501 while(runLength-- > 0) 502 pix[x++] = dataByte; 503 } 504 505 } 506 507 if ( raw - (byte *)pcx > len) 508 Error ("PCX file %s was malformed", filename); 509 510 free (pcx); 511 } 512 /* 513 ============== 514 WritePCXfile 515 ============== 516 */ 517 void WritePCXfile (char *filename, byte *data, 518 int width, int height, byte *palette) 519 { 520 int i, j, length; 521 pcx_t *pcx; 522 byte *pack; 523 524 pcx = (pcx_t*)malloc (width*height*2+1000); 525 memset (pcx, 0, sizeof(*pcx)); 526 527 pcx->manufacturer = 0x0a; // PCX id 528 pcx->version = 5; // 256 color 529 pcx->encoding = 1; // uncompressed 530 pcx->bits_per_pixel = 8; // 256 color 531 pcx->xmin = 0; 532 pcx->ymin = 0; 533 pcx->xmax = LittleShort((short)(width-1)); 534 pcx->ymax = LittleShort((short)(height-1)); 535 pcx->hres = LittleShort((short)width); 536 pcx->vres = LittleShort((short)height); 537 pcx->color_planes = 1; // chunky image 538 pcx->bytes_per_line = LittleShort((short)width); 539 pcx->palette_type = LittleShort(2); // not a grey scale 540 541 // pack the image 542 pack = &pcx->data; 543 544 for (i=0 ; i<height ; i++) 545 { 546 for (j=0 ; j<width ; j++) 547 { 548 if ( (*data & 0xc0) != 0xc0) 549 *pack++ = *data++; 550 else 551 { 552 *pack++ = 0xc1; 553 *pack++ = *data++; 554 } 555 } 556 } 557 558 // write the palette 559 *pack++ = 0x0c; // palette ID byte 560 for (i=0 ; i<768 ; i++) 561 *pack++ = *palette++; 562 563 // write output file 564 length = pack - (byte *)pcx; 565 SaveFile (filename, pcx, length); 566 567 free (pcx); 568 } 569 570 /* 571 ============================================================================ 572 573 LOAD IMAGE 574 575 ============================================================================ 576 */ 577 578 /* 579 ============== 580 Load256Image 581 582 Will load either an lbm or pcx, depending on extension. 583 Any of the return pointers can be NULL if you don't want them. 584 ============== 585 */ 586 void Load256Image (char *name, byte **pixels, byte **palette, 587 int *width, int *height) 588 { 589 char ext[128]; 590 bitmap_t bmp; 591 592 ExtractFileExtension (name, ext); 593 if (stricmp(ext, "lbm")) 594 { 595 LoadLBM (name, pixels, palette); 596 if (width) 597 *width = bmhd.w; 598 if (height) 599 *height = bmhd.h; 600 } 601 else if (stricmp (ext, "pcx")) 602 { 603 LoadPCX (name, pixels, palette, width, height); 604 } 605 else if (stricmp (ext, "bmp")) 606 { 607 LoadBMP (name, &bmp); 608 if (bmp.palette) 609 { 610 *palette = (unsigned char*)malloc (768); 611 memcpy (*palette, bmp.palette, 768); 612 } 613 FreeBMP (&bmp); 614 } 615 else 616 Error ("%s doesn't have a known image extension", name); 617 } 618 619 620 /* 621 ============== 622 Save256Image 623 624 Will save either an lbm or pcx, depending on extension. 625 ============== 626 */ 627 void Save256Image (char *name, byte *pixels, byte *palette, 628 int width, int height) 629 { 630 char ext[128]; 631 632 ExtractFileExtension (name, ext); 633 if (!strcmp (ext, "lbm")) 634 { 635 WriteLBMfile (name, pixels, width, height, palette); 636 } 637 else if (!stricmp (ext, "pcx")) 638 { 639 WritePCXfile (name, pixels, width, height, palette); 640 } 641 else 642 Error ("%s doesn't have a known image extension", name); 643 } 644 645 646 647 /* 648 ============================================================================ 649 650 TARGA IMAGE 651 652 ============================================================================ 653 */ 654 typedef struct _TargaHeader { 655 unsigned char id_length, colormap_type, image_type; 656 unsigned short colormap_index, colormap_length; 657 unsigned char colormap_size; 658 unsigned short x_origin, y_origin, width, height; 659 unsigned char pixel_size, attributes; 660 } TargaHeader; 661 662 int fgetLittleShort (FILE *f) 663 { 664 byte b1, b2; 665 666 b1 = fgetc(f); 667 b2 = fgetc(f); 668 669 return (short)(b1 + b2*256); 670 } 671 672 int getLittleShort (byte*& p) 673 { 674 byte b1, b2; 675 b1 = *p++; 676 b2 = *p++; 677 return (short)(b1 + b2*256); 678 } 679 680 int getLittleLong (byte*& p) 681 { 682 byte b1, b2, b3, b4; 683 684 b1 = *p++; 685 b2 = *p++; 686 b3 = *p++; 687 b4 = *p++; 688 return b1 + (b2<<8) + (b3<<16) + (b4<<24); 689 } 690 691 char getc(byte*& p) 692 { 693 return *p++; 694 } 695 696 /* 697 ========================================================= 698 699 BMP LOADING 700 701 ========================================================= 702 */ 703 typedef struct 704 { 705 char id[2]; 706 unsigned long fileSize; 707 unsigned long reserved0; 708 unsigned long bitmapDataOffset; 709 unsigned long bitmapHeaderSize; 710 unsigned long width; 711 unsigned long height; 712 unsigned short planes; 713 unsigned short bitsPerPixel; 714 unsigned long compression; 715 unsigned long bitmapDataSize; 716 unsigned long hRes; 717 unsigned long vRes; 718 unsigned long colors; 719 unsigned long importantColors; 720 unsigned char palette[256][4]; 721 } BMPHeader_t; 722 723 static void LoadBMP( const char *name, byte **pic, int *width, int *height ) 724 { 725 int columns, rows, numPixels; 726 byte *pixbuf; 727 int row, column; 728 byte *buf_p; 729 byte *buffer; 730 unsigned int length; 731 BMPHeader_t bmpHeader; 732 byte *bmpRGBA; 733 734 *pic = NULL; 735 736 // 737 // load the file 738 // 739 length = LoadFile( ( char * ) name, (void **)&buffer); 740 if (length == -1) 741 { 742 length = PakLoadAnyFile( (char*)name, (void**)&buffer); 743 if (length == -1) 744 { 745 return; 746 } 747 } 748 749 buf_p = buffer; 750 751 bmpHeader.id[0] = *buf_p++; 752 bmpHeader.id[1] = *buf_p++; 753 bmpHeader.fileSize = LittleLong( * ( long * ) buf_p ); 754 buf_p += 4; 755 bmpHeader.reserved0 = LittleLong( * ( long * ) buf_p ); 756 buf_p += 4; 757 bmpHeader.bitmapDataOffset = LittleLong( * ( long * ) buf_p ); 758 buf_p += 4; 759 bmpHeader.bitmapHeaderSize = LittleLong( * ( long * ) buf_p ); 760 buf_p += 4; 761 bmpHeader.width = LittleLong( * ( long * ) buf_p ); 762 buf_p += 4; 763 bmpHeader.height = LittleLong( * ( long * ) buf_p ); 764 buf_p += 4; 765 bmpHeader.planes = LittleShort( * ( short * ) buf_p ); 766 buf_p += 2; 767 bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p ); 768 buf_p += 2; 769 bmpHeader.compression = LittleLong( * ( long * ) buf_p ); 770 buf_p += 4; 771 bmpHeader.bitmapDataSize = LittleLong( * ( long * ) buf_p ); 772 buf_p += 4; 773 bmpHeader.hRes = LittleLong( * ( long * ) buf_p ); 774 buf_p += 4; 775 bmpHeader.vRes = LittleLong( * ( long * ) buf_p ); 776 buf_p += 4; 777 bmpHeader.colors = LittleLong( * ( long * ) buf_p ); 778 buf_p += 4; 779 bmpHeader.importantColors = LittleLong( * ( long * ) buf_p ); 780 buf_p += 4; 781 782 memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) ); 783 784 if ( bmpHeader.bitsPerPixel == 8 ) 785 buf_p += 1024; 786 787 if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' ) 788 { 789 Sys_Printf("LoadBMP: only Windows-style BMP files supported (%s)\n", name ); 790 } 791 if ( bmpHeader.fileSize != length ) 792 { 793 Sys_Printf("LoadBMP: header size does not match file size (%d vs. %d) (%s)\n", bmpHeader.fileSize, length, name ); 794 } 795 if ( bmpHeader.compression != 0 ) 796 { 797 Sys_Printf("LoadBMP: only uncompressed BMP files supported (%s)\n", name ); 798 } 799 if ( bmpHeader.bitsPerPixel < 8 ) 800 { 801 Sys_Printf("LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name ); 802 } 803 804 columns = bmpHeader.width; 805 rows = bmpHeader.height; 806 if ( rows < 0 ) 807 rows = -rows; 808 numPixels = columns * rows; 809 810 if ( width ) 811 *width = columns; 812 if ( height ) 813 *height = rows; 814 815 bmpRGBA = reinterpret_cast<unsigned char*>(malloc( numPixels * 4 )); 816 *pic = bmpRGBA; 817 818 819 for ( row = rows-1; row >= 0; row-- ) 820 { 821 pixbuf = bmpRGBA + row*columns*4; 822 823 for ( column = 0; column < columns; column++ ) 824 { 825 unsigned char red, green, blue, alpha; 826 int palIndex; 827 unsigned short shortPixel; 828 829 switch ( bmpHeader.bitsPerPixel ) 830 { 831 case 8: 832 palIndex = *buf_p++; 833 *pixbuf++ = bmpHeader.palette[palIndex][2]; 834 *pixbuf++ = bmpHeader.palette[palIndex][1]; 835 *pixbuf++ = bmpHeader.palette[palIndex][0]; 836 *pixbuf++ = 0xff; 837 break; 838 case 16: 839 shortPixel = * ( unsigned short * ) pixbuf; 840 pixbuf += 2; 841 *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7; 842 *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2; 843 *pixbuf++ = ( shortPixel & ( 31 ) ) << 3; 844 *pixbuf++ = 0xff; 845 break; 846 847 case 24: 848 blue = *buf_p++; 849 green = *buf_p++; 850 red = *buf_p++; 851 *pixbuf++ = red; 852 *pixbuf++ = green; 853 *pixbuf++ = blue; 854 *pixbuf++ = 255; 855 break; 856 case 32: 857 blue = *buf_p++; 858 green = *buf_p++; 859 red = *buf_p++; 860 alpha = *buf_p++; 861 *pixbuf++ = red; 862 *pixbuf++ = green; 863 *pixbuf++ = blue; 864 *pixbuf++ = alpha; 865 break; 866 default: 867 Sys_Printf("LoadBMP: illegal pixel_size '%d' in file '%s'\n", bmpHeader.bitsPerPixel, name ); 868 break; 869 } 870 } 871 } 872 873 free( buffer ); 874 875 } 876 877 878 /* 879 ================================================================= 880 881 PCX LOADING 882 883 ================================================================= 884 */ 885 886 887 /* 888 ============== 889 LoadPCX 890 ============== 891 */ 892 static void LoadPCX ( const char *filename, byte **pic, byte **palette, int *width, int *height) 893 { 894 byte *raw; 895 pcx_t *pcx; 896 int x, y; 897 int len; 898 int dataByte, runLength; 899 byte *out, *pix; 900 int xmax, ymax; 901 902 *pic = NULL; 903 *palette = NULL; 904 905 // 906 // load the file 907 // 908 len = LoadFile( ( char * ) filename, (void **)&raw); 909 if (len == -1) 910 { 911 len = PakLoadAnyFile( (char*)filename, (void**)&raw); 912 if (len == -1) 913 { 914 return; 915 } 916 } 917 918 // 919 // parse the PCX file 920 // 921 pcx = (pcx_t *)raw; 922 raw = &pcx->data; 923 924 xmax = LittleShort(pcx->xmax); 925 ymax = LittleShort(pcx->ymax); 926 927 if (pcx->manufacturer != 0x0a 928 || pcx->version != 5 929 || pcx->encoding != 1 930 || pcx->bits_per_pixel != 8 931 || xmax >= 1024 932 || ymax >= 1024) 933 { 934 Sys_Printf ("Bad pcx file %s (%i x %i) (%i x %i)\n", filename, xmax+1, ymax+1, pcx->xmax, pcx->ymax); 935 return; 936 } 937 938 out = reinterpret_cast<unsigned char*>(malloc ( (ymax+1) * (xmax+1) )); 939 940 *pic = out; 941 942 pix = out; 943 944 if (palette) 945 { 946 *palette = reinterpret_cast<unsigned char*>(malloc(768)); 947 memcpy (*palette, (byte *)pcx + len - 768, 768); 948 } 949 950 if (width) 951 *width = xmax+1; 952 if (height) 953 *height = ymax+1; 954 // FIXME: use bytes_per_line here? 955 956 for (y=0 ; y<=ymax ; y++, pix += xmax+1) 957 { 958 for (x=0 ; x<=xmax ; ) 959 { 960 dataByte = *raw++; 961 962 if((dataByte & 0xC0) == 0xC0) 963 { 964 runLength = dataByte & 0x3F; 965 dataByte = *raw++; 966 } 967 else 968 runLength = 1; 969 970 while(runLength-- > 0) 971 pix[x++] = dataByte; 972 } 973 974 } 975 976 if ( raw - (byte *)pcx > len) 977 { 978 Sys_Printf ("PCX file %s was malformed", filename); 979 free (*pic); 980 *pic = NULL; 981 } 982 983 free(pcx); 984 } 985 986 987 /* 988 ============== 989 LoadPCX32 990 ============== 991 */ 992 static void LoadPCX32 ( const char *filename, byte **pic, int *width, int *height) { 993 byte *palette; 994 byte *pic8; 995 int i, c, p; 996 byte *pic32; 997 998 LoadPCX (filename, &pic8, &palette, width, height); 999 if (!pic8) { 1000 *pic = NULL; 1001 return; 1002 } 1003 1004 c = (*width) * (*height); 1005 pic32 = *pic = reinterpret_cast<unsigned char*>(malloc(4 * c )); 1006 for (i = 0 ; i < c ; i++) { 1007 p = pic8[i]; 1008 pic32[0] = palette[p*3]; 1009 pic32[1] = palette[p*3 + 1]; 1010 pic32[2] = palette[p*3 + 2]; 1011 pic32[3] = 255; 1012 pic32 += 4; 1013 } 1014 1015 free (pic8); 1016 free (palette); 1017 } 1018 1019 /* 1020 ========================================================= 1021 1022 TARGA LOADING 1023 1024 ========================================================= 1025 */ 1026 1027 /* 1028 ============= 1029 LoadTGA 1030 ============= 1031 */ 1032 void LoadTGA ( const char *name, byte **pic, int *width, int *height) 1033 { 1034 int columns, rows, numPixels; 1035 byte *pixbuf; 1036 int row, column; 1037 byte *buf_p; 1038 byte *buffer; 1039 TargaHeader targa_header; 1040 byte *targa_rgba; 1041 1042 *pic = NULL; 1043 1044 // 1045 // load the file 1046 // 1047 int nLen = LoadFile ( ( char * ) name, (void **)&buffer); 1048 if (nLen == -1) 1049 { 1050 nLen = PakLoadAnyFile((char*)name, (void**)&buffer); 1051 if (nLen == -1) 1052 { 1053 return; 1054 } 1055 } 1056 1057 buf_p = buffer; 1058 1059 targa_header.id_length = *buf_p++; 1060 targa_header.colormap_type = *buf_p++; 1061 targa_header.image_type = *buf_p++; 1062 1063 targa_header.colormap_index = LittleShort ( *(short *)buf_p ); 1064 buf_p += 2; 1065 targa_header.colormap_length = LittleShort ( *(short *)buf_p ); 1066 buf_p += 2; 1067 targa_header.colormap_size = *buf_p++; 1068 targa_header.x_origin = LittleShort ( *(short *)buf_p ); 1069 buf_p += 2; 1070 targa_header.y_origin = LittleShort ( *(short *)buf_p ); 1071 buf_p += 2; 1072 targa_header.width = LittleShort ( *(short *)buf_p ); 1073 buf_p += 2; 1074 targa_header.height = LittleShort ( *(short *)buf_p ); 1075 buf_p += 2; 1076 targa_header.pixel_size = *buf_p++; 1077 targa_header.attributes = *buf_p++; 1078 1079 //++timo debug 1080 if (targa_header.pixel_size == 32) 1081 Sys_Printf("%s is 32bit\n", name); 1082 bool bAlphaOK = false; 1083 1084 if (targa_header.image_type!=2 1085 && targa_header.image_type!=10 1086 && targa_header.image_type != 3 ) 1087 { 1088 Sys_Printf("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n"); 1089 } 1090 1091 if ( targa_header.colormap_type != 0 ) 1092 { 1093 Sys_Printf("LoadTGA: colormaps not supported\n" ); 1094 } 1095 1096 if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 ) 1097 { 1098 Sys_Printf("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); 1099 } 1100 1101 columns = targa_header.width; 1102 rows = targa_header.height; 1103 numPixels = columns * rows; 1104 1105 if (width) 1106 *width = columns; 1107 if (height) 1108 *height = rows; 1109 1110 targa_rgba = reinterpret_cast<unsigned char*>(malloc (numPixels*4)); 1111 *pic = targa_rgba; 1112 1113 if (targa_header.id_length != 0) 1114 buf_p += targa_header.id_length; // skip TARGA image comment 1115 1116 if ( targa_header.image_type==2 || targa_header.image_type == 3 ) 1117 { 1118 // Uncompressed RGB or gray scale image 1119 for(row=rows-1; row>=0; row--) 1120 { 1121 pixbuf = targa_rgba + row*columns*4; 1122 for(column=0; column<columns; column++) 1123 { 1124 unsigned char red,green,blue,alphabyte; 1125 switch (targa_header.pixel_size) 1126 { 1127 1128 case 8: 1129 blue = *buf_p++; 1130 green = blue; 1131 red = blue; 1132 *pixbuf++ = red; 1133 *pixbuf++ = green; 1134 *pixbuf++ = blue; 1135 *pixbuf++ = 255; 1136 break; 1137 1138 case 24: 1139 blue = *buf_p++; 1140 green = *buf_p++; 1141 red = *buf_p++; 1142 *pixbuf++ = red; 1143 *pixbuf++ = green; 1144 *pixbuf++ = blue; 1145 *pixbuf++ = 255; 1146 break; 1147 case 32: 1148 blue = *buf_p++; 1149 green = *buf_p++; 1150 red = *buf_p++; 1151 alphabyte = *buf_p++; 1152 //++timo debug: detect if the whole alpha channel is 0 1153 if (alphabyte != 0) 1154 bAlphaOK = true; 1155 *pixbuf++ = red; 1156 *pixbuf++ = green; 1157 *pixbuf++ = blue; 1158 *pixbuf++ = alphabyte; 1159 break; 1160 default: 1161 Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); 1162 break; 1163 } 1164 } 1165 } 1166 1167 //++timo debug 1168 if (bAlphaOK) 1169 Sys_Printf("alpha channel OK"); 1170 else 1171 Sys_Printf("empty alpha channel!"); 1172 } 1173 else if (targa_header.image_type==10) { // Runlength encoded RGB images 1174 1175 //++timo debug 1176 Sys_Printf("runlength encode RGB image"); 1177 1178 unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j; 1179 1180 red = 0; 1181 green = 0; 1182 blue = 0; 1183 alphabyte = 0xff; 1184 1185 for(row=rows-1; row>=0; row--) { 1186 pixbuf = targa_rgba + row*columns*4; 1187 for(column=0; column<columns; ) { 1188 packetHeader= *buf_p++; 1189 packetSize = 1 + (packetHeader & 0x7f); 1190 if (packetHeader & 0x80) { // run-length packet 1191 switch (targa_header.pixel_size) { 1192 case 24: 1193 blue = *buf_p++; 1194 green = *buf_p++; 1195 red = *buf_p++; 1196 alphabyte = 255; 1197 break; 1198 case 32: 1199 blue = *buf_p++; 1200 green = *buf_p++; 1201 red = *buf_p++; 1202 alphabyte = *buf_p++; 1203 break; 1204 default: 1205 Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); 1206 break; 1207 } 1208 1209 for(j=0;j<packetSize;j++) { 1210 *pixbuf++=red; 1211 *pixbuf++=green; 1212 *pixbuf++=blue; 1213 *pixbuf++=alphabyte; 1214 column++; 1215 if (column==columns) { // run spans across rows 1216 column=0; 1217 if (row>0) 1218 row--; 1219 else 1220 goto breakOut; 1221 pixbuf = targa_rgba + row*columns*4; 1222 } 1223 } 1224 } 1225 else { // non run-length packet 1226 for(j=0;j<packetSize;j++) { 1227 switch (targa_header.pixel_size) { 1228 case 24: 1229 blue = *buf_p++; 1230 green = *buf_p++; 1231 red = *buf_p++; 1232 *pixbuf++ = red; 1233 *pixbuf++ = green; 1234 *pixbuf++ = blue; 1235 *pixbuf++ = 255; 1236 break; 1237 case 32: 1238 blue = *buf_p++; 1239 green = *buf_p++; 1240 red = *buf_p++; 1241 alphabyte = *buf_p++; 1242 *pixbuf++ = red; 1243 *pixbuf++ = green; 1244 *pixbuf++ = blue; 1245 *pixbuf++ = alphabyte; 1246 break; 1247 default: 1248 Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); 1249 break; 1250 } 1251 column++; 1252 if (column==columns) { // pixel packet run spans across rows 1253 column=0; 1254 if (row>0) 1255 row--; 1256 else 1257 goto breakOut; 1258 pixbuf = targa_rgba + row*columns*4; 1259 } 1260 } 1261 } 1262 } 1263 breakOut:; 1264 } 1265 } 1266 1267 free(buffer); 1268 } 1269 1270 1271 1272 1273 void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) 1274 { 1275 byte *fbuffer = NULL; 1276 int nLen = LoadFile( ( char * ) filename, (void **)&fbuffer); 1277 if (nLen == -1) 1278 { 1279 nLen = PakLoadAnyFile((char*)filename, (void**)&fbuffer); 1280 if (nLen == -1) 1281 { 1282 return; 1283 } 1284 } 1285 LoadJPGBuff(fbuffer, pic, width, height); 1286 free(fbuffer); 1287 } 1288 1289 //=================================================================== 1290 1291 /* 1292 ================= 1293 LoadImage 1294 1295 Loads any of the supported image types into a cannonical 1296 32 bit format. 1297 ================= 1298 */ 1299 void LoadImage( const char *name, byte **pic, int *width, int *height ) 1300 { 1301 int len; 1302 *pic = NULL; 1303 *width = 0; 1304 *height = 0; 1305 1306 len = strlen(name); 1307 if (len<5) 1308 { 1309 return; 1310 } 1311 1312 if ( !stricmp( name+len-4, ".tga" ) ) 1313 { 1314 LoadTGA( name, pic, width, height ); 1315 } 1316 else if ( !stricmp(name+len-4, ".pcx") ) 1317 { 1318 LoadPCX32( name, pic, width, height ); 1319 } 1320 else if ( !stricmp( name+len-4, ".bmp" ) ) 1321 { 1322 LoadBMP( name, pic, width, height ); 1323 } 1324 else if ( !stricmp( name+len-4, ".jpg" ) ) 1325 { 1326 LoadJPG( name, pic, width, height ); 1327 } 1328 } 1329