r_image.c (13129B)
1 /* 2 Copyright (C) 1997-2001 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 21 #include "r_local.h" 22 23 24 #define MAX_RIMAGES 1024 25 image_t r_images[MAX_RIMAGES]; 26 int numr_images; 27 28 29 /* 30 =============== 31 R_ImageList_f 32 =============== 33 */ 34 void R_ImageList_f (void) 35 { 36 int i; 37 image_t *image; 38 int texels; 39 40 ri.Con_Printf (PRINT_ALL, "------------------\n"); 41 texels = 0; 42 43 for (i=0, image=r_images ; i<numr_images ; i++, image++) 44 { 45 if (image->registration_sequence <= 0) 46 continue; 47 texels += image->width*image->height; 48 switch (image->type) 49 { 50 case it_skin: 51 ri.Con_Printf (PRINT_ALL, "M"); 52 break; 53 case it_sprite: 54 ri.Con_Printf (PRINT_ALL, "S"); 55 break; 56 case it_wall: 57 ri.Con_Printf (PRINT_ALL, "W"); 58 break; 59 case it_pic: 60 ri.Con_Printf (PRINT_ALL, "P"); 61 break; 62 default: 63 ri.Con_Printf (PRINT_ALL, " "); 64 break; 65 } 66 67 ri.Con_Printf (PRINT_ALL, " %3i %3i : %s\n", 68 image->width, image->height, image->name); 69 } 70 ri.Con_Printf (PRINT_ALL, "Total texel count: %i\n", texels); 71 } 72 73 74 /* 75 ================================================================= 76 77 PCX LOADING 78 79 ================================================================= 80 */ 81 82 /* 83 ============== 84 LoadPCX 85 ============== 86 */ 87 void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height) 88 { 89 byte *raw; 90 pcx_t *pcx; 91 int x, y; 92 int len; 93 int dataByte, runLength; 94 byte *out, *pix; 95 96 *pic = NULL; 97 98 // 99 // load the file 100 // 101 len = ri.FS_LoadFile (filename, (void **)&raw); 102 if (!raw) 103 { 104 ri.Con_Printf (PRINT_DEVELOPER, "Bad pcx file %s\n", filename); 105 return; 106 } 107 108 // 109 // parse the PCX file 110 // 111 pcx = (pcx_t *)raw; 112 113 pcx->xmin = LittleShort(pcx->xmin); 114 pcx->ymin = LittleShort(pcx->ymin); 115 pcx->xmax = LittleShort(pcx->xmax); 116 pcx->ymax = LittleShort(pcx->ymax); 117 pcx->hres = LittleShort(pcx->hres); 118 pcx->vres = LittleShort(pcx->vres); 119 pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); 120 pcx->palette_type = LittleShort(pcx->palette_type); 121 122 raw = &pcx->data; 123 124 if (pcx->manufacturer != 0x0a 125 || pcx->version != 5 126 || pcx->encoding != 1 127 || pcx->bits_per_pixel != 8 128 || pcx->xmax >= 640 129 || pcx->ymax >= 480) 130 { 131 ri.Con_Printf (PRINT_ALL, "Bad pcx file %s\n", filename); 132 return; 133 } 134 135 out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) ); 136 137 *pic = out; 138 139 pix = out; 140 141 if (palette) 142 { 143 *palette = malloc(768); 144 memcpy (*palette, (byte *)pcx + len - 768, 768); 145 } 146 147 if (width) 148 *width = pcx->xmax+1; 149 if (height) 150 *height = pcx->ymax+1; 151 152 for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1) 153 { 154 for (x=0 ; x<=pcx->xmax ; ) 155 { 156 dataByte = *raw++; 157 158 if((dataByte & 0xC0) == 0xC0) 159 { 160 runLength = dataByte & 0x3F; 161 dataByte = *raw++; 162 } 163 else 164 runLength = 1; 165 166 while(runLength-- > 0) 167 pix[x++] = dataByte; 168 } 169 170 } 171 172 if ( raw - (byte *)pcx > len) 173 { 174 ri.Con_Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename); 175 free (*pic); 176 *pic = NULL; 177 } 178 179 ri.FS_FreeFile (pcx); 180 } 181 182 /* 183 ========================================================= 184 185 TARGA LOADING 186 187 ========================================================= 188 */ 189 190 typedef struct _TargaHeader { 191 unsigned char id_length, colormap_type, image_type; 192 unsigned short colormap_index, colormap_length; 193 unsigned char colormap_size; 194 unsigned short x_origin, y_origin, width, height; 195 unsigned char pixel_size, attributes; 196 } TargaHeader; 197 198 199 /* 200 ============= 201 LoadTGA 202 ============= 203 */ 204 void LoadTGA (char *name, byte **pic, int *width, int *height) 205 { 206 int columns, rows, numPixels; 207 byte *pixbuf; 208 int row, column; 209 byte *buf_p; 210 byte *buffer; 211 int length; 212 TargaHeader targa_header; 213 byte *targa_rgba; 214 215 *pic = NULL; 216 217 // 218 // load the file 219 // 220 length = ri.FS_LoadFile (name, (void **)&buffer); 221 if (!buffer) 222 { 223 ri.Con_Printf (PRINT_DEVELOPER, "Bad tga file %s\n", name); 224 return; 225 } 226 227 buf_p = buffer; 228 229 targa_header.id_length = *buf_p++; 230 targa_header.colormap_type = *buf_p++; 231 targa_header.image_type = *buf_p++; 232 233 targa_header.colormap_index = LittleShort ( *((short *)buf_p) ); 234 buf_p+=2; 235 targa_header.colormap_length = LittleShort ( *((short *)buf_p) ); 236 buf_p+=2; 237 targa_header.colormap_size = *buf_p++; 238 targa_header.x_origin = LittleShort ( *((short *)buf_p) ); 239 buf_p+=2; 240 targa_header.y_origin = LittleShort ( *((short *)buf_p) ); 241 buf_p+=2; 242 targa_header.width = LittleShort ( *((short *)buf_p) ); 243 buf_p+=2; 244 targa_header.height = LittleShort ( *((short *)buf_p) ); 245 buf_p+=2; 246 targa_header.pixel_size = *buf_p++; 247 targa_header.attributes = *buf_p++; 248 249 if (targa_header.image_type!=2 250 && targa_header.image_type!=10) 251 ri.Sys_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n"); 252 253 if (targa_header.colormap_type !=0 254 || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24)) 255 ri.Sys_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); 256 257 columns = targa_header.width; 258 rows = targa_header.height; 259 numPixels = columns * rows; 260 261 if (width) 262 *width = columns; 263 if (height) 264 *height = rows; 265 266 targa_rgba = malloc (numPixels*4); 267 *pic = targa_rgba; 268 269 if (targa_header.id_length != 0) 270 buf_p += targa_header.id_length; // skip TARGA image comment 271 272 if (targa_header.image_type==2) { // Uncompressed, RGB images 273 for(row=rows-1; row>=0; row--) { 274 pixbuf = targa_rgba + row*columns*4; 275 for(column=0; column<columns; column++) { 276 unsigned char red,green,blue,alphabyte; 277 switch (targa_header.pixel_size) { 278 case 24: 279 280 blue = *buf_p++; 281 green = *buf_p++; 282 red = *buf_p++; 283 *pixbuf++ = red; 284 *pixbuf++ = green; 285 *pixbuf++ = blue; 286 *pixbuf++ = 255; 287 break; 288 case 32: 289 blue = *buf_p++; 290 green = *buf_p++; 291 red = *buf_p++; 292 alphabyte = *buf_p++; 293 *pixbuf++ = red; 294 *pixbuf++ = green; 295 *pixbuf++ = blue; 296 *pixbuf++ = alphabyte; 297 break; 298 } 299 } 300 } 301 } 302 else if (targa_header.image_type==10) { // Runlength encoded RGB images 303 unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j; 304 for(row=rows-1; row>=0; row--) { 305 pixbuf = targa_rgba + row*columns*4; 306 for(column=0; column<columns; ) { 307 packetHeader= *buf_p++; 308 packetSize = 1 + (packetHeader & 0x7f); 309 if (packetHeader & 0x80) { // run-length packet 310 switch (targa_header.pixel_size) { 311 case 24: 312 blue = *buf_p++; 313 green = *buf_p++; 314 red = *buf_p++; 315 alphabyte = 255; 316 break; 317 case 32: 318 blue = *buf_p++; 319 green = *buf_p++; 320 red = *buf_p++; 321 alphabyte = *buf_p++; 322 break; 323 } 324 325 for(j=0;j<packetSize;j++) { 326 *pixbuf++=red; 327 *pixbuf++=green; 328 *pixbuf++=blue; 329 *pixbuf++=alphabyte; 330 column++; 331 if (column==columns) { // run spans across rows 332 column=0; 333 if (row>0) 334 row--; 335 else 336 goto breakOut; 337 pixbuf = targa_rgba + row*columns*4; 338 } 339 } 340 } 341 else { // non run-length packet 342 for(j=0;j<packetSize;j++) { 343 switch (targa_header.pixel_size) { 344 case 24: 345 blue = *buf_p++; 346 green = *buf_p++; 347 red = *buf_p++; 348 *pixbuf++ = red; 349 *pixbuf++ = green; 350 *pixbuf++ = blue; 351 *pixbuf++ = 255; 352 break; 353 case 32: 354 blue = *buf_p++; 355 green = *buf_p++; 356 red = *buf_p++; 357 alphabyte = *buf_p++; 358 *pixbuf++ = red; 359 *pixbuf++ = green; 360 *pixbuf++ = blue; 361 *pixbuf++ = alphabyte; 362 break; 363 } 364 column++; 365 if (column==columns) { // pixel packet run spans across rows 366 column=0; 367 if (row>0) 368 row--; 369 else 370 goto breakOut; 371 pixbuf = targa_rgba + row*columns*4; 372 } 373 } 374 } 375 } 376 breakOut:; 377 } 378 } 379 380 ri.FS_FreeFile (buffer); 381 } 382 383 384 //======================================================= 385 386 image_t *R_FindFreeImage (void) 387 { 388 image_t *image; 389 int i; 390 391 // find a free image_t 392 for (i=0, image=r_images ; i<numr_images ; i++,image++) 393 { 394 if (!image->registration_sequence) 395 break; 396 } 397 if (i == numr_images) 398 { 399 if (numr_images == MAX_RIMAGES) 400 ri.Sys_Error (ERR_DROP, "MAX_RIMAGES"); 401 numr_images++; 402 } 403 image = &r_images[i]; 404 405 return image; 406 } 407 408 /* 409 ================ 410 GL_LoadPic 411 412 ================ 413 */ 414 image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type) 415 { 416 image_t *image; 417 int i, c, b; 418 419 image = R_FindFreeImage (); 420 if (strlen(name) >= sizeof(image->name)) 421 ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name); 422 strcpy (image->name, name); 423 image->registration_sequence = registration_sequence; 424 425 image->width = width; 426 image->height = height; 427 image->type = type; 428 429 c = width*height; 430 image->pixels[0] = malloc (c); 431 image->transparent = false; 432 for (i=0 ; i<c ; i++) 433 { 434 b = pic[i]; 435 if (b == 255) 436 image->transparent = true; 437 image->pixels[0][i] = b; 438 } 439 440 return image; 441 } 442 443 /* 444 ================ 445 R_LoadWal 446 ================ 447 */ 448 image_t *R_LoadWal (char *name) 449 { 450 miptex_t *mt; 451 int ofs; 452 image_t *image; 453 int size; 454 455 ri.FS_LoadFile (name, (void **)&mt); 456 if (!mt) 457 { 458 ri.Con_Printf (PRINT_ALL, "R_LoadWal: can't load %s\n", name); 459 return r_notexture_mip; 460 } 461 462 image = R_FindFreeImage (); 463 strcpy (image->name, name); 464 image->width = LittleLong (mt->width); 465 image->height = LittleLong (mt->height); 466 image->type = it_wall; 467 image->registration_sequence = registration_sequence; 468 469 size = image->width*image->height * (256+64+16+4)/256; 470 image->pixels[0] = malloc (size); 471 image->pixels[1] = image->pixels[0] + image->width*image->height; 472 image->pixels[2] = image->pixels[1] + image->width*image->height/4; 473 image->pixels[3] = image->pixels[2] + image->width*image->height/16; 474 475 ofs = LittleLong (mt->offsets[0]); 476 memcpy ( image->pixels[0], (byte *)mt + ofs, size); 477 478 ri.FS_FreeFile ((void *)mt); 479 480 return image; 481 } 482 483 484 /* 485 =============== 486 R_FindImage 487 488 Finds or loads the given image 489 =============== 490 */ 491 image_t *R_FindImage (char *name, imagetype_t type) 492 { 493 image_t *image; 494 int i, len; 495 byte *pic, *palette; 496 int width, height; 497 498 if (!name) 499 return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: NULL name"); 500 len = strlen(name); 501 if (len<5) 502 return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad name: %s", name); 503 504 // look for it 505 for (i=0, image=r_images ; i<numr_images ; i++,image++) 506 { 507 if (!strcmp(name, image->name)) 508 { 509 image->registration_sequence = registration_sequence; 510 return image; 511 } 512 } 513 514 // 515 // load the pic from disk 516 // 517 pic = NULL; 518 palette = NULL; 519 if (!strcmp(name+len-4, ".pcx")) 520 { 521 LoadPCX (name, &pic, &palette, &width, &height); 522 if (!pic) 523 return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s", name); 524 image = GL_LoadPic (name, pic, width, height, type); 525 } 526 else if (!strcmp(name+len-4, ".wal")) 527 { 528 image = R_LoadWal (name); 529 } 530 else if (!strcmp(name+len-4, ".tga")) 531 return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s in software renderer", name); 532 else 533 return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad extension on: %s", name); 534 535 if (pic) 536 free(pic); 537 if (palette) 538 free(palette); 539 540 return image; 541 } 542 543 544 545 /* 546 =============== 547 R_RegisterSkin 548 =============== 549 */ 550 struct image_s *R_RegisterSkin (char *name) 551 { 552 return R_FindImage (name, it_skin); 553 } 554 555 556 /* 557 ================ 558 R_FreeUnusedImages 559 560 Any image that was not touched on this registration sequence 561 will be freed. 562 ================ 563 */ 564 void R_FreeUnusedImages (void) 565 { 566 int i; 567 image_t *image; 568 569 for (i=0, image=r_images ; i<numr_images ; i++, image++) 570 { 571 if (image->registration_sequence == registration_sequence) 572 { 573 Com_PageInMemory ((byte *)image->pixels[0], image->width*image->height); 574 continue; // used this sequence 575 } 576 if (!image->registration_sequence) 577 continue; // free texture 578 if (image->type == it_pic) 579 continue; // don't free pics 580 // free it 581 free (image->pixels[0]); // the other mip levels just follow 582 memset (image, 0, sizeof(*image)); 583 } 584 } 585 586 587 588 /* 589 =============== 590 R_InitImages 591 =============== 592 */ 593 void R_InitImages (void) 594 { 595 registration_sequence = 1; 596 } 597 598 /* 599 =============== 600 R_ShutdownImages 601 =============== 602 */ 603 void R_ShutdownImages (void) 604 { 605 int i; 606 image_t *image; 607 608 for (i=0, image=r_images ; i<numr_images ; i++, image++) 609 { 610 if (!image->registration_sequence) 611 continue; // free texture 612 // free it 613 free (image->pixels[0]); // the other mip levels just follow 614 memset (image, 0, sizeof(*image)); 615 } 616 } 617