vkQuake2 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  }
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 
381 }
382 
383 
384 //=======================================================
385 
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);
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 */
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;
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 */
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 = (int)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  {
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 */
565 {
566  int i;
567  image_t *image;
568 
569  for (i=0, image=r_images ; i<numr_images ; i++, image++)
570  {
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 {
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 
it_sprite
@ it_sprite
Definition: r_local.h:65
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:414
R_InitImages
void R_InitImages(void)
Definition: r_image.c:593
LittleShort
short LittleShort(short l)
Definition: q_shared.c:946
int
CONST PIXELFORMATDESCRIPTOR int
Definition: qgl_win.c:35
green
GLfloat green
Definition: qgl_win.c:74
R_ShutdownImages
void R_ShutdownImages(void)
Definition: r_image.c:603
_TargaHeader::y_origin
unsigned short y_origin
Definition: r_image.c:194
imagetype_t
imagetype_t
Definition: r_local.h:62
ri
refimport_t ri
Definition: r_main.c:25
pcx_t
Definition: qfiles.h:60
PRINT_DEVELOPER
#define PRINT_DEVELOPER
Definition: qcommon.h:752
miptex_s
Definition: qfiles.h:198
it_wall
@ it_wall
Definition: r_local.h:66
_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:209
pix
static int pix
Definition: r_part.c:472
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:491
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:110
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:77
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:210
j
GLint j
Definition: qgl_win.c:150
R_FreeUnusedImages
void R_FreeUnusedImages(void)
Definition: r_image.c:564
refimport_t::Con_Printf
void(* Con_Printf)(int print_level, char *str,...)
Definition: ref.h:202
PRINT_ALL
#define PRINT_ALL
Definition: qcommon.h:751
pcx_t::ymin
unsigned short ymin
Definition: qfiles.h:66
TargaHeader
struct _TargaHeader TargaHeader
it_pic
@ it_pic
Definition: r_local.h:67
R_LoadWal
image_t * R_LoadWal(char *name)
Definition: r_image.c:448
LittleLong
int LittleLong(int l)
Definition: q_shared.c:948
image_s::height
int height
Definition: r_local.h:75
_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:550
refimport_t::Sys_Error
void(* Sys_Error)(int err_level, char *str,...)
Definition: ref.h:194
_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:74
pcx_t::encoding
char encoding
Definition: qfiles.h:64
NULL
#define NULL
Definition: q_shared.h:67
image_s::pixels
byte * pixels[4]
Definition: r_local.h:78
image_s::width
int width
Definition: r_local.h:75
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:73
image_s::transparent
qboolean transparent
Definition: r_local.h:76
ERR_DROP
#define ERR_DROP
Definition: qcommon.h:744
it_skin
@ it_skin
Definition: r_local.h:64
pcx_t::bits_per_pixel
char bits_per_pixel
Definition: qfiles.h:65
name
cvar_t * name
Definition: cl_main.c:79
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:386
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:71
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