icculus quake2 doxygen  1.0 dev
r_image.c
Go to the documentation of this file.
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
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);
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 {
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  default:
324  blue = 0;
325  green = 0;
326  red = 0;
327  alphabyte = 0;
328  break;
329  }
330 
331  for(j=0;j<packetSize;j++) {
332  *pixbuf++=red;
333  *pixbuf++=green;
334  *pixbuf++=blue;
335  *pixbuf++=alphabyte;
336  column++;
337  if (column==columns) { // run spans across rows
338  column=0;
339  if (row>0)
340  row--;
341  else
342  goto breakOut;
343  pixbuf = targa_rgba + row*columns*4;
344  }
345  }
346  }
347  else { // non run-length packet
348  for(j=0;j<packetSize;j++) {
349  switch (targa_header.pixel_size) {
350  case 24:
351  blue = *buf_p++;
352  green = *buf_p++;
353  red = *buf_p++;
354  *pixbuf++ = red;
355  *pixbuf++ = green;
356  *pixbuf++ = blue;
357  *pixbuf++ = 255;
358  break;
359  case 32:
360  blue = *buf_p++;
361  green = *buf_p++;
362  red = *buf_p++;
363  alphabyte = *buf_p++;
364  *pixbuf++ = red;
365  *pixbuf++ = green;
366  *pixbuf++ = blue;
367  *pixbuf++ = alphabyte;
368  break;
369  }
370  column++;
371  if (column==columns) { // pixel packet run spans across rows
372  column=0;
373  if (row>0)
374  row--;
375  else
376  goto breakOut;
377  pixbuf = targa_rgba + row*columns*4;
378  }
379  }
380  }
381  }
382  breakOut:;
383  }
384  }
385 
387 }
388 
389 
390 //=======================================================
391 
393 {
394  image_t *image;
395  int i;
396 
397  // find a free image_t
398  for (i=0, image=r_images ; i<numr_images ; i++,image++)
399  {
400  if (!image->registration_sequence)
401  break;
402  }
403  if (i == numr_images)
404  {
405  if (numr_images == MAX_RIMAGES)
406  ri.Sys_Error (ERR_DROP, "MAX_RIMAGES");
407  numr_images++;
408  }
409  image = &r_images[i];
410 
411  return image;
412 }
413 
414 /*
415 ================
416 GL_LoadPic
417 
418 ================
419 */
420 image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
421 {
422  image_t *image;
423  int i, c, b;
424 
425  image = R_FindFreeImage ();
426  if (strlen(name) >= sizeof(image->name))
427  ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
428  strcpy (image->name, name);
430 
431  image->width = width;
432  image->height = height;
433  image->type = type;
434 
435  c = width*height;
436  image->pixels[0] = malloc (c);
437  image->transparent = false;
438  for (i=0 ; i<c ; i++)
439  {
440  b = pic[i];
441  if (b == 255)
442  image->transparent = true;
443  image->pixels[0][i] = b;
444  }
445 
446  return image;
447 }
448 
449 /*
450 ================
451 R_LoadWal
452 ================
453 */
455 {
456  miptex_t *mt;
457  int ofs;
458  image_t *image;
459  int size;
460 
461  ri.FS_LoadFile (name, (void **)&mt);
462  if (!mt)
463  {
464  ri.Con_Printf (PRINT_ALL, "R_LoadWal: can't load %s\n", name);
465  return r_notexture_mip;
466  }
467 
468  image = R_FindFreeImage ();
469  strcpy (image->name, name);
470  image->width = LittleLong (mt->width);
471  image->height = LittleLong (mt->height);
472  image->type = it_wall;
474 
475  size = image->width*image->height * (256+64+16+4)/256;
476  image->pixels[0] = malloc (size);
477  image->pixels[1] = image->pixels[0] + image->width*image->height;
478  image->pixels[2] = image->pixels[1] + image->width*image->height/4;
479  image->pixels[3] = image->pixels[2] + image->width*image->height/16;
480 
481  ofs = LittleLong (mt->offsets[0]);
482  memcpy ( image->pixels[0], (byte *)mt + ofs, size);
483 
484  ri.FS_FreeFile ((void *)mt);
485 
486  return image;
487 }
488 
489 
490 /*
491 ===============
492 R_FindImage
493 
494 Finds or loads the given image
495 ===============
496 */
498 {
499  image_t *image;
500  int i, len;
501  byte *pic, *palette;
502  int width, height;
503  char *ptr;
504 
505  if (!name)
506  return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: NULL name");
507  len = strlen(name);
508  if (len<5)
509  return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad name: %s", name);
510 
511 #ifndef _WIN32
512  // fix backslashes
513  while ((ptr=strchr(name,'\\'))) {
514  *ptr = '/';
515  }
516 #endif
517 
518  // look for it
519  for (i=0, image=r_images ; i<numr_images ; i++,image++)
520  {
521  if (!strcmp(name, image->name))
522  {
524  return image;
525  }
526  }
527 
528  //
529  // load the pic from disk
530  //
531  pic = NULL;
532  palette = NULL;
533  if (!strcmp(name+len-4, ".pcx"))
534  {
535  LoadPCX (name, &pic, &palette, &width, &height);
536  if (!pic)
537  return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s", name);
538  image = GL_LoadPic (name, pic, width, height, type);
539  }
540  else if (!strcmp(name+len-4, ".wal"))
541  {
542  image = R_LoadWal (name);
543  }
544  else if (!strcmp(name+len-4, ".tga"))
545  return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s in software renderer", name);
546  else
547  return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad extension on: %s", name);
548 
549  if (pic)
550  free(pic);
551  if (palette)
552  free(palette);
553 
554  return image;
555 }
556 
557 
558 
559 /*
560 ===============
561 R_RegisterSkin
562 ===============
563 */
564 struct image_s *R_RegisterSkin (char *name)
565 {
566  return R_FindImage (name, it_skin);
567 }
568 
569 
570 /*
571 ================
572 R_FreeUnusedImages
573 
574 Any image that was not touched on this registration sequence
575 will be freed.
576 ================
577 */
579 {
580  int i;
581  image_t *image;
582 
583  for (i=0, image=r_images ; i<numr_images ; i++, image++)
584  {
586  {
587  Com_PageInMemory ((byte *)image->pixels[0], image->width*image->height);
588  continue; // used this sequence
589  }
590  if (!image->registration_sequence)
591  continue; // free texture
592  if (image->type == it_pic)
593  continue; // don't free pics
594  // free it
595  free (image->pixels[0]); // the other mip levels just follow
596  memset (image, 0, sizeof(*image));
597  }
598 }
599 
600 
601 
602 /*
603 ===============
604 R_InitImages
605 ===============
606 */
607 void R_InitImages (void)
608 {
610 }
611 
612 /*
613 ===============
614 R_ShutdownImages
615 ===============
616 */
617 void R_ShutdownImages (void)
618 {
619  int i;
620  image_t *image;
621 
622  for (i=0, image=r_images ; i<numr_images ; i++, image++)
623  {
624  if (!image->registration_sequence)
625  continue; // free texture
626  // free it
627  free (image->pixels[0]); // the other mip levels just follow
628  memset (image, 0, sizeof(*image));
629  }
630 }
631 
it_sprite
@ it_sprite
Definition: r_local.h:59
height
GLsizei height
Definition: qgl_win.c:69
GL_LoadPic
image_t * GL_LoadPic(char *name, byte *pic, int width, int height, imagetype_t type)
Definition: r_image.c:420
R_InitImages
void R_InitImages(void)
Definition: r_image.c:607
LittleShort
short LittleShort(short l)
Definition: q_shared.c:946
green
GLfloat green
Definition: qgl_win.c:74
R_ShutdownImages
void R_ShutdownImages(void)
Definition: r_image.c:617
_TargaHeader::y_origin
unsigned short y_origin
Definition: r_image.c:194
imagetype_t
imagetype_t
Definition: r_local.h:56
ri
refimport_t ri
Definition: r_main.c:25
pcx_t
Definition: qfiles.h:60
PRINT_DEVELOPER
#define PRINT_DEVELOPER
Definition: qcommon.h:744
miptex_s
Definition: qfiles.h:198
it_wall
@ it_wall
Definition: r_local.h:60
_TargaHeader::x_origin
unsigned short x_origin
Definition: r_image.c:194
_TargaHeader::pixel_size
unsigned char pixel_size
Definition: r_image.c:195
LoadTGA
void LoadTGA(char *name, byte **pic, int *width, int *height)
Definition: r_image.c:204
refimport_t::FS_LoadFile
int(* FS_LoadFile)(char *name, void **buf)
Definition: ref.h:235
pcx_t::version
char version
Definition: qfiles.h:63
pcx_t::data
unsigned char data
Definition: qfiles.h:74
R_FindImage
image_t * R_FindImage(char *name, imagetype_t type)
Definition: r_image.c:497
x
GLint GLenum GLint x
Definition: qgl_win.c:116
i
int i
Definition: q_shared.c:305
r_notexture_mip
image_t * r_notexture_mip
Definition: r_main.c:104
R_ImageList_f
void R_ImageList_f(void)
Definition: r_image.c:34
buffer
GLenum GLfloat * buffer
Definition: qgl_win.c:151
_TargaHeader::image_type
unsigned char image_type
Definition: r_image.c:191
width
GLint GLsizei width
Definition: qgl_win.c:115
pcx_t::hres
unsigned short hres
Definition: qfiles.h:67
image_s::registration_sequence
int registration_sequence
Definition: r_local.h:71
type
GLenum type
Definition: qgl_win.c:72
r_local.h
_TargaHeader::colormap_size
unsigned char colormap_size
Definition: r_image.c:193
_TargaHeader::colormap_index
unsigned short colormap_index
Definition: r_image.c:192
refimport_t::FS_FreeFile
void(* FS_FreeFile)(void *buf)
Definition: ref.h:236
j
GLint j
Definition: qgl_win.c:150
R_FreeUnusedImages
void R_FreeUnusedImages(void)
Definition: r_image.c:578
refimport_t::Con_Printf
void(* Con_Printf)(int print_level, char *str,...)
Definition: ref.h:228
PRINT_ALL
#define PRINT_ALL
Definition: qcommon.h:743
pcx_t::ymin
unsigned short ymin
Definition: qfiles.h:66
TargaHeader
struct _TargaHeader TargaHeader
it_pic
@ it_pic
Definition: r_local.h:61
R_LoadWal
image_t * R_LoadWal(char *name)
Definition: r_image.c:454
LittleLong
int LittleLong(int l)
Definition: q_shared.c:948
image_s::height
int height
Definition: r_local.h:69
_TargaHeader::colormap_length
unsigned short colormap_length
Definition: r_image.c:192
r_images
image_t r_images[MAX_RIMAGES]
Definition: r_image.c:25
R_RegisterSkin
struct image_s * R_RegisterSkin(char *name)
Definition: r_image.c:564
refimport_t::Sys_Error
void(* Sys_Error)(int err_level, char *str,...)
Definition: ref.h:220
_TargaHeader::attributes
unsigned char attributes
Definition: r_image.c:195
pcx_t::ymax
unsigned short ymax
Definition: qfiles.h:66
image_s::type
imagetype_t type
Definition: r_local.h:68
pcx_t::encoding
char encoding
Definition: qfiles.h:64
NULL
#define NULL
Definition: q_shared.h:60
image_s::pixels
byte * pixels[4]
Definition: r_local.h:72
image_s::width
int width
Definition: r_local.h:69
numr_images
int numr_images
Definition: r_image.c:26
pcx_t::palette_type
unsigned short palette_type
Definition: qfiles.h:72
image_s::name
char name[MAX_QPATH]
Definition: r_local.h:67
image_s::transparent
qboolean transparent
Definition: r_local.h:70
ERR_DROP
#define ERR_DROP
Definition: qcommon.h:736
it_skin
@ it_skin
Definition: r_local.h:58
pcx_t::bits_per_pixel
char bits_per_pixel
Definition: qfiles.h:65
name
cvar_t * name
Definition: cl_main.c:94
pcx_t::xmin
unsigned short xmin
Definition: qfiles.h:66
y
GLint y
Definition: qgl_win.c:115
_TargaHeader
Definition: r_image.c:190
R_FindFreeImage
image_t * R_FindFreeImage(void)
Definition: r_image.c:392
Com_PageInMemory
void Com_PageInMemory(byte *buffer, int size)
Definition: q_shared.c:1161
blue
GLfloat GLfloat blue
Definition: qgl_win.c:74
pcx_t::manufacturer
char manufacturer
Definition: qfiles.h:62
_TargaHeader::colormap_type
unsigned char colormap_type
Definition: r_image.c:191
_TargaHeader::width
unsigned short width
Definition: r_image.c:194
_TargaHeader::id_length
unsigned char id_length
Definition: r_image.c:191
pcx_t::vres
unsigned short vres
Definition: qfiles.h:67
MAX_RIMAGES
#define MAX_RIMAGES
Definition: r_image.c:24
_TargaHeader::height
unsigned short height
Definition: r_image.c:194
registration_sequence
int registration_sequence
Definition: r_model.c:44
image_s
Definition: r_local.h:65
pcx_t::xmax
unsigned short xmax
Definition: qfiles.h:66
LoadPCX
void LoadPCX(char *filename, byte **pic, byte **palette, int *width, int *height)
Definition: r_image.c:87
pcx_t::bytes_per_line
unsigned short bytes_per_line
Definition: qfiles.h:71