7 // note: pal must be 32bit color
8 void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal)
10 int *iout = (void *)out;
45 void Image_CopyRGBAGamma(byte *in, byte *out, int pixels)
49 out[0] = qgamma[in[0]];
50 out[1] = qgamma[in[1]];
51 out[2] = qgamma[in[2]];
60 =================================================================
64 =================================================================
73 unsigned short xmin,ymin,xmax,ymax;
74 unsigned short hres,vres;
75 unsigned char palette[48];
78 unsigned short bytes_per_line;
79 unsigned short palette_type;
81 unsigned data; // unbounded
89 byte* LoadPCX (FILE *f, int matchwidth, int matchheight)
93 byte *pix, *image_rgba;
95 int dataByte, runLength;
101 fread (&pcxbuf, 1, sizeof(pcxbuf), f);
105 // LordHavoc: big-endian support ported from QF newtree
106 pcx->xmax = LittleShort (pcx->xmax);
107 pcx->xmin = LittleShort (pcx->xmin);
108 pcx->ymax = LittleShort (pcx->ymax);
109 pcx->ymin = LittleShort (pcx->ymin);
110 pcx->hres = LittleShort (pcx->hres);
111 pcx->vres = LittleShort (pcx->vres);
112 pcx->bytes_per_line = LittleShort (pcx->bytes_per_line);
113 pcx->palette_type = LittleShort (pcx->palette_type);
115 if (pcx->manufacturer != 0x0a || pcx->version != 5 || pcx->encoding != 1 || pcx->bits_per_pixel != 8 || pcx->xmax > 320 || pcx->ymax > 256)
117 Con_Printf ("Bad pcx file\n");
121 if (matchwidth && (pcx->xmax+1) != matchwidth)
123 if (matchheight && (pcx->ymax+1) != matchheight)
127 fseek (f, -768, SEEK_END);
128 fread (palette, 1, 768, f);
130 fseek (f, sizeof(pcxbuf) - 4, SEEK_SET);
132 count = (pcx->xmax+1) * (pcx->ymax+1);
133 image_rgba = malloc( count * 4);
135 for (y=0 ; y<=pcx->ymax ; y++)
137 pix = image_rgba + 4*y*(pcx->xmax+1);
138 for (x=0 ; x<=pcx->xmax ; )
142 if((dataByte & 0xC0) == 0xC0)
144 runLength = dataByte & 0x3F;
151 pix[0] = palette[dataByte*3];
152 pix[1] = palette[dataByte*3+1];
153 pix[2] = palette[dataByte*3+2];
162 pix[0] = palette[dataByte*3];
163 pix[1] = palette[dataByte*3+1];
164 pix[2] = palette[dataByte*3+2];
172 image_width = pcx->xmax+1;
173 image_height = pcx->ymax+1;
178 =========================================================
182 =========================================================
185 typedef struct _TargaHeader {
186 unsigned char id_length, colormap_type, image_type;
187 unsigned short colormap_index, colormap_length;
188 unsigned char colormap_size;
189 unsigned short x_origin, y_origin, width, height;
190 unsigned char pixel_size, attributes;
194 TargaHeader targa_header;
196 int fgetLittleShort (FILE *f)
203 return (short)(b1 + b2*256);
206 int fgetLittleLong (FILE *f)
215 return b1 + (b2<<8) + (b3<<16) + (b4<<24);
224 byte* LoadTGA (FILE *fin, int matchwidth, int matchheight)
226 int columns, rows, numPixels;
231 targa_header.id_length = fgetc(fin);
232 targa_header.colormap_type = fgetc(fin);
233 targa_header.image_type = fgetc(fin);
235 targa_header.colormap_index = fgetLittleShort(fin);
236 targa_header.colormap_length = fgetLittleShort(fin);
237 targa_header.colormap_size = fgetc(fin);
238 targa_header.x_origin = fgetLittleShort(fin);
239 targa_header.y_origin = fgetLittleShort(fin);
240 targa_header.width = fgetLittleShort(fin);
241 targa_header.height = fgetLittleShort(fin);
242 if (matchwidth && targa_header.width != matchwidth)
244 if (matchheight && targa_header.height != matchheight)
246 targa_header.pixel_size = fgetc(fin);
247 targa_header.attributes = fgetc(fin);
249 if (targa_header.image_type!=2
250 && targa_header.image_type!=10)
251 Host_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
253 if (targa_header.colormap_type !=0
254 || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
255 Host_Error ("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
257 columns = targa_header.width;
258 rows = targa_header.height;
259 numPixels = columns * rows;
261 image_rgba = malloc (numPixels*4);
263 if (targa_header.id_length != 0)
264 fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment
266 if (targa_header.image_type==2) { // Uncompressed, RGB images
267 for(row=rows-1; row>=0; row--) {
268 pixbuf = image_rgba + row*columns*4;
269 for(column=0; column<columns; column++) {
270 unsigned char red = 0,green = 0,blue = 0,alphabyte = 0;
271 switch (targa_header.pixel_size) {
286 alphabyte = getc(fin);
290 *pixbuf++ = alphabyte;
296 else if (targa_header.image_type==10) { // Runlength encoded RGB images
297 unsigned char red = 0,green = 0,blue = 0,alphabyte = 0,packetHeader,packetSize,j;
298 for(row=rows-1; row>=0; row--) {
299 pixbuf = image_rgba + row*columns*4;
300 for(column=0; column<columns; ) {
301 packetHeader=getc(fin);
302 packetSize = 1 + (packetHeader & 0x7f);
303 if (packetHeader & 0x80) { // run-length packet
304 switch (targa_header.pixel_size) {
315 alphabyte = getc(fin);
319 for(j=0;j<packetSize;j++) {
325 if (column==columns) { // run spans across rows
331 pixbuf = image_rgba + row*columns*4;
335 else { // non run-length packet
336 for(j=0;j<packetSize;j++) {
337 switch (targa_header.pixel_size) {
351 alphabyte = getc(fin);
355 *pixbuf++ = alphabyte;
359 if (column==columns) { // pixel packet run spans across rows
365 pixbuf = image_rgba + row*columns*4;
375 image_width = columns;
385 byte* LoadLMP (FILE *f, int matchwidth, int matchheight)
390 // parse the very complicated header *chuckle*
391 width = fgetLittleLong(f);
392 height = fgetLittleLong(f);
393 if ((unsigned) width > 4096 || (unsigned) height > 4096)
394 Host_Error("LoadLMP: invalid size\n");
395 if (matchwidth && width != matchwidth)
397 if (matchheight && height != matchheight)
400 image_rgba = malloc(width*height*4);
401 fread(image_rgba + width*height*3, 1, width*height, f);
404 Image_Copy8bitRGBA(image_rgba + width*height*3, image_rgba, width*height, d_8to24table);
406 image_height = height;
410 void Image_StripImageExtension (char *in, char *out)
413 end = in + strlen(in);
416 if (strcmp(end - 4, ".tga") == 0 || strcmp(end - 4, ".pcx") == 0 || strcmp(end - 4, ".lmp") == 0)
426 byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight)
429 char basename[256], name[256];
430 byte *image_rgba, *c;
431 Image_StripImageExtension(filename, basename); // strip .tga, .pcx and .lmp extensions to allow replacement by other types
432 // replace *'s with #, so commandline utils don't get confused when dealing with the external files
433 for (c = basename;*c;c++)
436 sprintf (name, "textures/%s.tga", basename);
437 COM_FOpenFile (name, &f, true);
439 return LoadTGA (f, matchwidth, matchheight);
440 sprintf (name, "textures/%s.pcx", basename);
441 COM_FOpenFile (name, &f, true);
443 return LoadPCX (f, matchwidth, matchheight);
444 sprintf (name, "%s.tga", basename);
445 Con_Printf("name = %s : ", name);
446 COM_FOpenFile (name, &f, true);
449 Con_Printf("succeeded\n");
450 return LoadTGA (f, matchwidth, matchheight);
453 Con_Printf("failed\n");
454 sprintf (name, "%s.pcx", basename);
455 COM_FOpenFile (name, &f, true);
457 return LoadPCX (f, matchwidth, matchheight);
458 sprintf (name, "%s.lmp", basename);
459 COM_FOpenFile (name, &f, true);
461 return LoadLMP (f, matchwidth, matchheight);
462 if ((image_rgba = W_GetTexture(basename, matchwidth, matchheight)))
464 COM_StripExtension(filename, basename); // do it again with a * this time
465 if ((image_rgba = W_GetTexture(basename, matchwidth, matchheight)))
468 Con_Printf ("Couldn't load %s.tga or .pcx\n", filename);
472 int image_makemask (byte *in, byte *out, int size)
476 for (i = 0;i < size;i++)
478 out[0] = out[1] = out[2] = 255;
488 byte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, int matchheight)
491 in = data = loadimagepixels(filename, complain, matchwidth, matchheight);
494 if (image_makemask(data, data, image_width * image_height))
495 return data; // some transparency
499 return NULL; // all opaque
503 int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap)
507 if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
509 texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
514 int loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap)
518 if (!(data = loadimagepixelsmask (filename, complain, matchwidth, matchheight)))
520 texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
525 int image_masktexnum;
526 int loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap)
531 image_masktexnum = 0;
532 if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
534 texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
535 count = image_makemask(data, data, image_width * image_height);
538 filename2 = malloc(strlen(filename) + 6);
539 sprintf(filename2, "%s_mask", filename);
540 image_masktexnum = GL_LoadTexture (filename2, image_width, image_height, data, mipmap, true, 4);
547 void Image_WriteTGARGB (char *filename, int width, int height, byte *data)
549 byte *buffer, *in, *out, *end;
551 buffer = malloc(width*height*3 + 18);
553 memset (buffer, 0, 18);
554 buffer[2] = 2; // uncompressed type
555 buffer[12] = (width >> 0) & 0xFF;
556 buffer[13] = (width >> 8) & 0xFF;
557 buffer[14] = (height >> 0) & 0xFF;
558 buffer[15] = (height >> 8) & 0xFF;
559 buffer[16] = 24; // pixel size
563 end = in + width*height*3;
565 for (;in < end;in += 3)
571 COM_WriteFile (filename, buffer, glwidth*glheight*3 + 18 );