8 #include "libtxc_dxtn.h"
9 #include "s2tc_common.h"
11 /* START stuff that originates from image.c in DarkPlaces */
12 int image_width, image_height;
14 typedef struct _TargaHeader
16 unsigned char id_length, colormap_type, image_type;
17 unsigned short colormap_index, colormap_length;
18 unsigned char colormap_size;
19 unsigned short x_origin, y_origin, width, height;
20 unsigned char pixel_size, attributes;
24 unsigned char *LoadTGA_BGRA (const unsigned char *f, int filesize)
26 int x, y, pix_inc, row_inci, runlen, alphabits;
27 unsigned char *image_buffer;
28 unsigned int *pixbufi;
29 const unsigned char *fin, *enddata;
30 TargaHeader targa_header;
31 unsigned int palettei[256];
42 enddata = f + filesize;
44 targa_header.id_length = f[0];
45 targa_header.colormap_type = f[1];
46 targa_header.image_type = f[2];
48 targa_header.colormap_index = f[3] + f[4] * 256;
49 targa_header.colormap_length = f[5] + f[6] * 256;
50 targa_header.colormap_size = f[7];
51 targa_header.x_origin = f[8] + f[9] * 256;
52 targa_header.y_origin = f[10] + f[11] * 256;
53 targa_header.width = image_width = f[12] + f[13] * 256;
54 targa_header.height = image_height = f[14] + f[15] * 256;
55 targa_header.pixel_size = f[16];
56 targa_header.attributes = f[17];
58 if (image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0)
60 printf("LoadTGA: invalid size\n");
64 /* advance to end of header */
67 /* skip TARGA image comment (usually 0 bytes) */
68 fin += targa_header.id_length;
70 /* read/skip the colormap if present (note: according to the TARGA spec it */
71 /* can be present even on 1color or greyscale images, just not used by */
73 if (targa_header.colormap_type)
75 if (targa_header.colormap_length > 256)
77 printf("LoadTGA: only up to 256 colormap_length supported\n");
80 if (targa_header.colormap_index)
82 printf("LoadTGA: colormap_index not supported\n");
85 if (targa_header.colormap_size == 24)
87 for (x = 0;x < targa_header.colormap_length;x++)
96 else if (targa_header.colormap_size == 32)
98 memcpy(palettei, fin, targa_header.colormap_length*4);
99 fin += targa_header.colormap_length * 4;
103 printf("LoadTGA: Only 32 and 24 bit colormap_size supported\n");
108 /* check our pixel_size restrictions according to image_type */
109 switch (targa_header.image_type & ~8)
112 if (targa_header.pixel_size != 24 && targa_header.pixel_size != 32)
114 printf("LoadTGA: only 24bit and 32bit pixel sizes supported for type 2 and type 10 images\n");
119 /* set up a palette to make the loader easier */
120 for (x = 0;x < 256;x++)
122 bgra.b[0] = bgra.b[1] = bgra.b[2] = x;
124 palettei[x] = bgra.i;
126 /* fall through to colormap case */
128 if (targa_header.pixel_size != 8)
130 printf("LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n");
135 printf("LoadTGA: Only type 1, 2, 3, 9, 10, and 11 targa RGB images supported, image_type = %i\n", targa_header.image_type);
139 if (targa_header.attributes & 0x10)
141 printf("LoadTGA: origin must be in top left or bottom left, top right and bottom right are not supported\n");
145 /* number of attribute bits per pixel, we only support 0 or 8 */
146 alphabits = targa_header.attributes & 0x0F;
147 if (alphabits != 8 && alphabits != 0)
149 printf("LoadTGA: only 0 or 8 attribute (alpha) bits supported\n");
153 image_buffer = (unsigned char *)malloc(image_width * image_height * 4);
156 printf("LoadTGA: not enough memory for %i by %i image\n", image_width, image_height);
160 /* If bit 5 of attributes isn't set, the image has been stored from bottom to top */
161 if ((targa_header.attributes & 0x20) == 0)
163 pixbufi = (unsigned int*)image_buffer + (image_height - 1)*image_width;
164 row_inci = -image_width*2;
168 pixbufi = (unsigned int*)image_buffer;
175 if ((targa_header.image_type & ~8) == 2)
176 pix_inc = (targa_header.pixel_size + 7) / 8;
177 switch (targa_header.image_type)
179 case 1: /* colormapped, uncompressed */
180 case 3: /* greyscale, uncompressed */
181 if (fin + image_width * image_height * pix_inc > enddata)
183 for (y = 0;y < image_height;y++, pixbufi += row_inci)
184 for (x = 0;x < image_width;x++)
185 *pixbufi++ = palettei[*fin++];
188 /* BGR or BGRA, uncompressed */
189 if (fin + image_width * image_height * pix_inc > enddata)
191 if (targa_header.pixel_size == 32 && alphabits)
193 for (y = 0;y < image_height;y++)
194 memcpy(pixbufi + y * (image_width + row_inci), fin + y * image_width * pix_inc, image_width*4);
198 for (y = 0;y < image_height;y++, pixbufi += row_inci)
200 for (x = 0;x < image_width;x++, fin += pix_inc)
211 case 9: /* colormapped, RLE */
212 case 11: /* greyscale, RLE */
213 for (y = 0;y < image_height;y++, pixbufi += row_inci)
215 for (x = 0;x < image_width;)
218 break; /* error - truncated file */
222 /* RLE - all pixels the same color */
224 if (fin + pix_inc > enddata)
225 break; /* error - truncated file */
226 if (x + runlen > image_width)
227 break; /* error - line exceeds width */
228 bgra.i = palettei[*fin++];
234 /* uncompressed - all pixels different color */
236 if (fin + pix_inc * runlen > enddata)
237 break; /* error - truncated file */
238 if (x + runlen > image_width)
239 break; /* error - line exceeds width */
241 *pixbufi++ = palettei[*fin++];
245 if (x != image_width)
247 /* pixbufi is useless now */
248 printf("LoadTGA: corrupt file\n");
254 /* BGR or BGRA, RLE */
255 if (targa_header.pixel_size == 32 && alphabits)
257 for (y = 0;y < image_height;y++, pixbufi += row_inci)
259 for (x = 0;x < image_width;)
262 break; /* error - truncated file */
266 /* RLE - all pixels the same color */
268 if (fin + pix_inc > enddata)
269 break; /* error - truncated file */
270 if (x + runlen > image_width)
271 break; /* error - line exceeds width */
282 /* uncompressed - all pixels different color */
284 if (fin + pix_inc * runlen > enddata)
285 break; /* error - truncated file */
286 if (x + runlen > image_width)
287 break; /* error - line exceeds width */
300 if (x != image_width)
302 /* pixbufi is useless now */
303 printf("LoadTGA: corrupt file\n");
310 for (y = 0;y < image_height;y++, pixbufi += row_inci)
312 for (x = 0;x < image_width;)
315 break; /* error - truncated file */
319 /* RLE - all pixels the same color */
321 if (fin + pix_inc > enddata)
322 break; /* error - truncated file */
323 if (x + runlen > image_width)
324 break; /* error - line exceeds width */
335 /* uncompressed - all pixels different color */
337 if (fin + pix_inc * runlen > enddata)
338 break; /* error - truncated file */
339 if (x + runlen > image_width)
340 break; /* error - line exceeds width */
353 if (x != image_width)
355 /* pixbufi is useless now */
356 printf("LoadTGA: corrupt file\n");
363 /* unknown image_type */
370 // in can be the same as out
371 void Image_MipReduce32(const unsigned char *in, unsigned char *out, int *width, int *height, int destwidth, int destheight)
373 const unsigned char *inrow;
375 // note: if given odd width/height this discards the last row/column of
376 // pixels, rather than doing a proper box-filter scale down
378 nextrow = *width * 4;
379 if (*width > destwidth)
382 if (*height > destheight)
386 for (y = 0;y < *height;y++, inrow += nextrow * 2)
388 for (in = inrow, x = 0;x < *width;x++)
390 out[0] = (unsigned char) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
391 out[1] = (unsigned char) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
392 out[2] = (unsigned char) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
393 out[3] = (unsigned char) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
402 for (y = 0;y < *height;y++, inrow += nextrow)
404 for (in = inrow, x = 0;x < *width;x++)
406 out[0] = (unsigned char) ((in[0] + in[4]) >> 1);
407 out[1] = (unsigned char) ((in[1] + in[5]) >> 1);
408 out[2] = (unsigned char) ((in[2] + in[6]) >> 1);
409 out[3] = (unsigned char) ((in[3] + in[7]) >> 1);
418 if (*height > destheight)
422 for (y = 0;y < *height;y++, inrow += nextrow * 2)
424 for (in = inrow, x = 0;x < *width;x++)
426 out[0] = (unsigned char) ((in[0] + in[nextrow ]) >> 1);
427 out[1] = (unsigned char) ((in[1] + in[nextrow+1]) >> 1);
428 out[2] = (unsigned char) ((in[2] + in[nextrow+2]) >> 1);
429 out[3] = (unsigned char) ((in[3] + in[nextrow+3]) >> 1);
437 unsigned char *FS_LoadFile(const char *fn, int *len)
439 unsigned char *buf = NULL;
441 FILE *f = fn ? fopen(fn, "rb") : stdin;
447 buf = (unsigned char *) realloc(buf, *len + 65536);
456 n = fread(buf + *len, 1, 65536, f);
473 /* end of darkplaces stuff */
475 uint32_t LittleLong(uint32_t w)
490 int usage(const char *me)
492 fprintf(stderr, "usage:\n"
495 " [-o outfile.dds]\n"
496 " [-t {DXT1|DXT3|DXT5}]\n",
501 int main(int argc, char **argv)
503 unsigned char *pic, *picdata;
507 GLenum dxt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
508 const char *infile = NULL, *outfile = NULL;
512 while((opt = getopt(argc, argv, "i:o:t:r:c:")) != -1)
523 if(!strcasecmp(optarg, "DXT1"))
524 dxt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
525 else if(!strcasecmp(optarg, "DXT3"))
526 dxt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
527 else if(!strcasecmp(optarg, "DXT5"))
528 dxt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
530 return usage(argv[0]);
533 return usage(argv[0]);
538 outfh = outfile ? fopen(outfile, "wb") : stdout;
541 printf("opening output failed\n");
545 picdata = FS_LoadFile(infile, &piclen);
548 printf("FS_LoadFile failed\n");
551 pic = LoadTGA_BGRA(picdata, piclen);
553 for(int x = 0; x < image_width*image_height; ++x)
554 std::swap(pic[4*x], pic[4*x+2]);
557 while(image_width >= (1 << mipcount) || image_height >= (1 << mipcount))
559 // now, (1 << mipcount) >= width, height
563 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
567 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
572 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
579 uint32_t picsize = LittleLong(((image_width+3)/4) * ((image_height+3)/4) * blocksize);
580 uint32_t ddssize = LittleLong(0x7c);
581 uint32_t dds_flags = LittleLong(0xa1007);
582 uint32_t one = LittleLong(1);
583 uint32_t zero = LittleLong(0);
584 uint32_t dds_format_flags = LittleLong(0x04);
585 uint32_t dds_caps1 = LittleLong(0x401008);
586 uint32_t dds_caps2 = LittleLong(0);
587 uint32_t dds_format_size = LittleLong(32);
588 uint32_t dds_mipcount = LittleLong(mipcount);
591 fwrite("DDS ", 4, 1, outfh);
592 fwrite(&ddssize, 4, 1, outfh);
593 fwrite(&dds_flags, 4, 1, outfh);
594 fwrite(&image_height, 4, 1, outfh);
595 fwrite(&image_width, 4, 1, outfh);
596 fwrite(&picsize, 4, 1, outfh);
597 fwrite(&one, 4, 1, outfh);
598 fwrite(&dds_mipcount, 4, 1, outfh);
601 fwrite(&zero, 4, 1, outfh);
602 fwrite(&zero, 4, 1, outfh);
603 fwrite(&zero, 4, 1, outfh);
604 fwrite(&zero, 4, 1, outfh);
605 fwrite(&zero, 4, 1, outfh);
606 fwrite(&zero, 4, 1, outfh);
607 fwrite(&zero, 4, 1, outfh);
608 fwrite(&zero, 4, 1, outfh);
611 fwrite(&zero, 4, 1, outfh);
612 fwrite(&zero, 4, 1, outfh);
613 fwrite(&zero, 4, 1, outfh);
614 fwrite(&dds_format_size, 4, 1, outfh);
615 fwrite(&dds_format_flags, 4, 1, outfh);
616 fwrite(fourcc, 4, 1, outfh);
617 fwrite("\x18\x00\x00\x00", 4, 1, outfh);
618 fwrite("\x00\x00\xff\x00", 4, 1, outfh);
621 fwrite("\x00\xff\x00\x00", 4, 1, outfh);
622 fwrite("\xff\x00\x00\x00", 4, 1, outfh);
623 fwrite(&zero, 4, 1, outfh);
624 fwrite(&dds_caps1, 4, 1, outfh);
625 fwrite(&dds_caps2, 4, 1, outfh);
626 fwrite(&zero, 4, 1, outfh);
627 fwrite(&zero, 4, 1, outfh);
628 fwrite(&zero, 4, 1, outfh);
633 int blocks_w = (image_width + 3) / 4;
634 int blocks_h = (image_height + 3) / 4;
635 GLubyte *obuf = (GLubyte *) malloc(blocksize * blocks_w * blocks_h);
636 tx_compress_dxtn(4, image_width, image_height, pic, dxt, obuf, blocks_w * blocksize);
637 fwrite(obuf, blocksize * blocks_w * blocks_h, 1, outfh);
639 if(image_width == 1 && image_height == 1)
641 Image_MipReduce32(pic, pic, &image_width, &image_height, 1, 1);