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] = texgamma[in[0]];
50 out[1] = texgamma[in[1]];
51 out[2] = texgamma[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;
88 byte* LoadPCX (byte *f, int matchwidth, int matchheight)
91 byte *palette, *a, *b, *image_rgba, *fin, *pbuf;
92 int x, y, dataByte, runLength;
96 memcpy(&pcx, fin, sizeof(pcx));
99 // LordHavoc: big-endian support ported from QF newtree
100 pcx.xmax = LittleShort (pcx.xmax);
101 pcx.xmin = LittleShort (pcx.xmin);
102 pcx.ymax = LittleShort (pcx.ymax);
103 pcx.ymin = LittleShort (pcx.ymin);
104 pcx.hres = LittleShort (pcx.hres);
105 pcx.vres = LittleShort (pcx.vres);
106 pcx.bytes_per_line = LittleShort (pcx.bytes_per_line);
107 pcx.palette_type = LittleShort (pcx.palette_type);
109 if (pcx.manufacturer != 0x0a || pcx.version != 5 || pcx.encoding != 1 || pcx.bits_per_pixel != 8 || pcx.xmax > 320 || pcx.ymax > 256)
111 Con_Printf ("Bad pcx file\n");
116 if (matchwidth && (pcx.xmax+1) != matchwidth)
121 if (matchheight && (pcx.ymax+1) != matchheight)
127 image_width = pcx.xmax+1;
128 image_height = pcx.ymax+1;
130 image_rgba = qmalloc(image_width*image_height*4);
131 pbuf = image_rgba + image_width*image_height*3;
133 for (y = 0;y < image_height;y++)
135 a = pbuf + y * image_width;
136 for (x = 0;x < image_width;)
141 runLength = dataByte & 0x3F;
162 for(x = 0;x < image_width*image_height;x++)
176 =========================================================
180 =========================================================
183 typedef struct _TargaHeader
185 unsigned char id_length, colormap_type, image_type;
186 unsigned short colormap_index, colormap_length;
187 unsigned char colormap_size;
188 unsigned short x_origin, y_origin, width, height;
189 unsigned char pixel_size, attributes;
193 TargaHeader targa_header;
201 byte* LoadTGA (byte *f, int matchwidth, int matchheight)
203 int columns, rows, numPixels, row, column;
204 byte *pixbuf, *image_rgba, *fin;
206 targa_header.id_length = f[0];
207 targa_header.colormap_type = f[1];
208 targa_header.image_type = f[2];
210 targa_header.colormap_index = f[3] + f[4] * 256;
211 targa_header.colormap_length = f[5] + f[6] * 256;
212 targa_header.colormap_size = f[7];
213 targa_header.x_origin = f[8] + f[9] * 256;
214 targa_header.y_origin = f[10] + f[11] * 256;
215 targa_header.width = f[12] + f[13] * 256;
216 targa_header.height = f[14] + f[15] * 256;
217 if (matchwidth && targa_header.width != matchwidth)
219 if (matchheight && targa_header.height != matchheight)
221 targa_header.pixel_size = f[16];
222 targa_header.attributes = f[17];
224 if (targa_header.image_type != 2 && targa_header.image_type != 10)
225 Host_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
227 if (targa_header.colormap_type != 0 || (targa_header.pixel_size != 32 && targa_header.pixel_size != 24))
228 Host_Error ("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
230 columns = targa_header.width;
231 rows = targa_header.height;
232 numPixels = columns * rows;
234 image_rgba = qmalloc(numPixels*4);
237 if (targa_header.id_length != 0)
238 fin += targa_header.id_length; // skip TARGA image comment
240 if (targa_header.image_type == 2)
242 // Uncompressed, RGB images
243 for(row = rows - 1;row >= 0;row--)
245 pixbuf = image_rgba + row*columns*4;
246 for(column = 0;column < columns;column++)
248 switch (targa_header.pixel_size)
268 else if (targa_header.image_type==10)
270 // Runlength encoded RGB images
271 unsigned char red = 0, green = 0, blue = 0, alphabyte = 0, packetHeader, packetSize, j;
272 for(row = rows - 1;row >= 0;row--)
274 pixbuf = image_rgba + row * columns * 4;
275 for(column = 0;column < columns;)
277 packetHeader = *fin++;
278 packetSize = 1 + (packetHeader & 0x7f);
279 if (packetHeader & 0x80)
282 switch (targa_header.pixel_size)
298 for(j = 0;j < packetSize;j++)
303 *pixbuf++ = alphabyte;
305 if (column == columns)
307 // run spans across rows
313 pixbuf = image_rgba + row * columns * 4;
319 // non run-length packet
320 for(j = 0;j < packetSize;j++)
322 switch (targa_header.pixel_size)
340 if (column == columns)
342 // pixel packet run spans across rows
348 pixbuf = image_rgba + row * columns * 4;
357 image_width = columns;
368 byte* LoadLMP (byte *f, int matchwidth, int matchheight)
373 // parse the very complicated header *chuckle*
374 width = LittleLong(((int *)f)[0]);
375 height = LittleLong(((int *)f)[1]);
376 if ((unsigned) width > 4096 || (unsigned) height > 4096)
379 Host_Error("LoadLMP: invalid size\n");
381 if (matchwidth && width != matchwidth)
386 if (matchheight && height != matchheight)
392 image_rgba = qmalloc(width*height*4);
393 Image_Copy8bitRGBA(f + 8, image_rgba, width*height, d_8to24table);
395 image_height = height;
400 void Image_StripImageExtension (char *in, char *out)
403 end = in + strlen(in);
407 if (strcmp(temp, ".tga") == 0 || strcmp(temp, ".pcx") == 0 || strcmp(temp, ".lmp") == 0)
417 byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight)
420 char basename[256], name[256];
422 Image_StripImageExtension(filename, basename); // strip .tga, .pcx and .lmp extensions to allow replacement by other types
423 // replace *'s with #, so commandline utils don't get confused when dealing with the external files
424 for (c = basename;*c;c++)
427 sprintf (name, "textures/%s.tga", basename);
428 f = COM_LoadMallocFile(name, true);
430 return LoadTGA (f, matchwidth, matchheight);
431 sprintf (name, "textures/%s.pcx", basename);
432 f = COM_LoadMallocFile(name, true);
434 return LoadPCX (f, matchwidth, matchheight);
435 sprintf (name, "%s.tga", basename);
436 f = COM_LoadMallocFile(name, true);
438 return LoadTGA (f, matchwidth, matchheight);
439 sprintf (name, "%s.pcx", basename);
440 f = COM_LoadMallocFile(name, true);
442 return LoadPCX (f, matchwidth, matchheight);
443 sprintf (name, "%s.lmp", basename);
444 f = COM_LoadMallocFile(name, true);
446 return LoadLMP (f, matchwidth, matchheight);
448 Con_Printf ("Couldn't load %s.tga, .pcx, .lmp\n", filename);
452 int image_makemask (byte *in, byte *out, int size)
456 for (i = 0;i < size;i++)
458 out[0] = out[1] = out[2] = 255;
468 byte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, int matchheight)
471 in = data = loadimagepixels(filename, complain, matchwidth, matchheight);
474 if (image_makemask(data, data, image_width * image_height))
475 return data; // some transparency
479 return NULL; // all opaque
483 rtexture_t *loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache)
487 if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
489 rt = R_LoadTexture (filename, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0));
494 rtexture_t *loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache)
498 if (!(data = loadimagepixelsmask (filename, complain, matchwidth, matchheight)))
500 rt = R_LoadTexture (filename, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0));
505 rtexture_t *image_masktex;
506 rtexture_t *loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache)
512 image_masktex = NULL;
513 if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
515 rt = R_LoadTexture (filename, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0));
516 count = image_makemask(data, data, image_width * image_height);
519 filename2 = qmalloc(strlen(filename) + 6);
520 sprintf(filename2, "%s_mask", filename);
521 image_masktex = R_LoadTexture (filename2, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0));
528 void Image_WriteTGARGB_preflipped (char *filename, int width, int height, byte *data)
530 byte *buffer, *in, *out, *end;
532 buffer = qmalloc(width*height*3 + 18);
534 memset (buffer, 0, 18);
535 buffer[2] = 2; // uncompressed type
536 buffer[12] = (width >> 0) & 0xFF;
537 buffer[13] = (width >> 8) & 0xFF;
538 buffer[14] = (height >> 0) & 0xFF;
539 buffer[15] = (height >> 8) & 0xFF;
540 buffer[16] = 24; // pixel size
545 end = in + width*height*3;
546 for (;in < end;in += 3)
552 COM_WriteFile (filename, buffer, width*height*3 + 18 );
557 void Image_WriteTGARGB (char *filename, int width, int height, byte *data)
560 byte *buffer, *in, *out, *end;
562 buffer = qmalloc(width*height*3 + 18);
564 memset (buffer, 0, 18);
565 buffer[2] = 2; // uncompressed type
566 buffer[12] = (width >> 0) & 0xFF;
567 buffer[13] = (width >> 8) & 0xFF;
568 buffer[14] = (height >> 0) & 0xFF;
569 buffer[15] = (height >> 8) & 0xFF;
570 buffer[16] = 24; // pixel size
572 // swap rgb to bgr and flip upside down
574 for (y = height - 1;y >= 0;y--)
576 in = data + y * width * 3;
577 end = in + width * 3;
578 for (;in < end;in += 3)
585 COM_WriteFile (filename, buffer, width*height*3 + 18 );
590 void Image_WriteTGARGBA (char *filename, int width, int height, byte *data)
593 byte *buffer, *in, *out, *end;
595 buffer = qmalloc(width*height*4 + 18);
597 memset (buffer, 0, 18);
598 buffer[2] = 2; // uncompressed type
599 buffer[12] = (width >> 0) & 0xFF;
600 buffer[13] = (width >> 8) & 0xFF;
601 buffer[14] = (height >> 0) & 0xFF;
602 buffer[15] = (height >> 8) & 0xFF;
603 buffer[16] = 32; // pixel size
605 // swap rgba to bgra and flip upside down
607 for (y = height - 1;y >= 0;y--)
609 in = data + y * width * 4;
610 end = in + width * 4;
611 for (;in < end;in += 4)
619 COM_WriteFile (filename, buffer, width*height*4 + 18 );
624 qboolean Image_CheckAlpha(byte *data, int size, qboolean rgba)
630 for (end = data + size * 4, data += 3;data < end;data += 4)
636 // color 255 is transparent
637 for (end = data + size;data < end;data++)