7 #include "libtxc_dxtn.h"
8 #include "s2tc_common.h"
10 /* START stuff that originates from image.c in DarkPlaces */
11 int image_width, image_height;
13 typedef struct _TargaHeader
15 unsigned char id_length, colormap_type, image_type;
16 unsigned short colormap_index, colormap_length;
17 unsigned char colormap_size;
18 unsigned short x_origin, y_origin, width, height;
19 unsigned char pixel_size, attributes;
23 unsigned char *LoadTGA_BGRA (const unsigned char *f, int filesize)
25 int x, y, pix_inc, row_inci, runlen, alphabits;
26 unsigned char *image_buffer;
27 unsigned int *pixbufi;
28 const unsigned char *fin, *enddata;
29 TargaHeader targa_header;
30 unsigned int palettei[256];
41 enddata = f + filesize;
43 targa_header.id_length = f[0];
44 targa_header.colormap_type = f[1];
45 targa_header.image_type = f[2];
47 targa_header.colormap_index = f[3] + f[4] * 256;
48 targa_header.colormap_length = f[5] + f[6] * 256;
49 targa_header.colormap_size = f[7];
50 targa_header.x_origin = f[8] + f[9] * 256;
51 targa_header.y_origin = f[10] + f[11] * 256;
52 targa_header.width = image_width = f[12] + f[13] * 256;
53 targa_header.height = image_height = f[14] + f[15] * 256;
54 targa_header.pixel_size = f[16];
55 targa_header.attributes = f[17];
57 if (image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0)
59 printf("LoadTGA: invalid size\n");
63 /* advance to end of header */
66 /* skip TARGA image comment (usually 0 bytes) */
67 fin += targa_header.id_length;
69 /* read/skip the colormap if present (note: according to the TARGA spec it */
70 /* can be present even on 1color or greyscale images, just not used by */
72 if (targa_header.colormap_type)
74 if (targa_header.colormap_length > 256)
76 printf("LoadTGA: only up to 256 colormap_length supported\n");
79 if (targa_header.colormap_index)
81 printf("LoadTGA: colormap_index not supported\n");
84 if (targa_header.colormap_size == 24)
86 for (x = 0;x < targa_header.colormap_length;x++)
95 else if (targa_header.colormap_size == 32)
97 memcpy(palettei, fin, targa_header.colormap_length*4);
98 fin += targa_header.colormap_length * 4;
102 printf("LoadTGA: Only 32 and 24 bit colormap_size supported\n");
107 /* check our pixel_size restrictions according to image_type */
108 switch (targa_header.image_type & ~8)
111 if (targa_header.pixel_size != 24 && targa_header.pixel_size != 32)
113 printf("LoadTGA: only 24bit and 32bit pixel sizes supported for type 2 and type 10 images\n");
118 /* set up a palette to make the loader easier */
119 for (x = 0;x < 256;x++)
121 bgra.b[0] = bgra.b[1] = bgra.b[2] = x;
123 palettei[x] = bgra.i;
125 /* fall through to colormap case */
127 if (targa_header.pixel_size != 8)
129 printf("LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n");
134 printf("LoadTGA: Only type 1, 2, 3, 9, 10, and 11 targa RGB images supported, image_type = %i\n", targa_header.image_type);
138 if (targa_header.attributes & 0x10)
140 printf("LoadTGA: origin must be in top left or bottom left, top right and bottom right are not supported\n");
144 /* number of attribute bits per pixel, we only support 0 or 8 */
145 alphabits = targa_header.attributes & 0x0F;
146 if (alphabits != 8 && alphabits != 0)
148 printf("LoadTGA: only 0 or 8 attribute (alpha) bits supported\n");
152 image_buffer = (unsigned char *)malloc(image_width * image_height * 4);
155 printf("LoadTGA: not enough memory for %i by %i image\n", image_width, image_height);
159 /* If bit 5 of attributes isn't set, the image has been stored from bottom to top */
160 if ((targa_header.attributes & 0x20) == 0)
162 pixbufi = (unsigned int*)image_buffer + (image_height - 1)*image_width;
163 row_inci = -image_width*2;
167 pixbufi = (unsigned int*)image_buffer;
174 if ((targa_header.image_type & ~8) == 2)
175 pix_inc = (targa_header.pixel_size + 7) / 8;
176 switch (targa_header.image_type)
178 case 1: /* colormapped, uncompressed */
179 case 3: /* greyscale, uncompressed */
180 if (fin + image_width * image_height * pix_inc > enddata)
182 for (y = 0;y < image_height;y++, pixbufi += row_inci)
183 for (x = 0;x < image_width;x++)
184 *pixbufi++ = palettei[*fin++];
187 /* BGR or BGRA, uncompressed */
188 if (fin + image_width * image_height * pix_inc > enddata)
190 if (targa_header.pixel_size == 32 && alphabits)
192 for (y = 0;y < image_height;y++)
193 memcpy(pixbufi + y * (image_width + row_inci), fin + y * image_width * pix_inc, image_width*4);
197 for (y = 0;y < image_height;y++, pixbufi += row_inci)
199 for (x = 0;x < image_width;x++, fin += pix_inc)
210 case 9: /* colormapped, RLE */
211 case 11: /* greyscale, RLE */
212 for (y = 0;y < image_height;y++, pixbufi += row_inci)
214 for (x = 0;x < image_width;)
217 break; /* error - truncated file */
221 /* RLE - all pixels the same color */
223 if (fin + pix_inc > enddata)
224 break; /* error - truncated file */
225 if (x + runlen > image_width)
226 break; /* error - line exceeds width */
227 bgra.i = palettei[*fin++];
233 /* uncompressed - all pixels different color */
235 if (fin + pix_inc * runlen > enddata)
236 break; /* error - truncated file */
237 if (x + runlen > image_width)
238 break; /* error - line exceeds width */
240 *pixbufi++ = palettei[*fin++];
244 if (x != image_width)
246 /* pixbufi is useless now */
247 printf("LoadTGA: corrupt file\n");
253 /* BGR or BGRA, RLE */
254 if (targa_header.pixel_size == 32 && alphabits)
256 for (y = 0;y < image_height;y++, pixbufi += row_inci)
258 for (x = 0;x < image_width;)
261 break; /* error - truncated file */
265 /* RLE - all pixels the same color */
267 if (fin + pix_inc > enddata)
268 break; /* error - truncated file */
269 if (x + runlen > image_width)
270 break; /* error - line exceeds width */
281 /* uncompressed - all pixels different color */
283 if (fin + pix_inc * runlen > enddata)
284 break; /* error - truncated file */
285 if (x + runlen > image_width)
286 break; /* error - line exceeds width */
299 if (x != image_width)
301 /* pixbufi is useless now */
302 printf("LoadTGA: corrupt file\n");
309 for (y = 0;y < image_height;y++, pixbufi += row_inci)
311 for (x = 0;x < image_width;)
314 break; /* error - truncated file */
318 /* RLE - all pixels the same color */
320 if (fin + pix_inc > enddata)
321 break; /* error - truncated file */
322 if (x + runlen > image_width)
323 break; /* error - line exceeds width */
334 /* uncompressed - all pixels different color */
336 if (fin + pix_inc * runlen > enddata)
337 break; /* error - truncated file */
338 if (x + runlen > image_width)
339 break; /* error - line exceeds width */
352 if (x != image_width)
354 /* pixbufi is useless now */
355 printf("LoadTGA: corrupt file\n");
362 /* unknown image_type */
369 // in can be the same as out
370 void Image_MipReduce32(const unsigned char *in, unsigned char *out, int *width, int *height, int destwidth, int destheight)
372 const unsigned char *inrow;
374 // note: if given odd width/height this discards the last row/column of
375 // pixels, rather than doing a proper box-filter scale down
377 nextrow = *width * 4;
378 if (*width > destwidth)
381 if (*height > destheight)
385 for (y = 0;y < *height;y++, inrow += nextrow * 2)
387 for (in = inrow, x = 0;x < *width;x++)
389 out[0] = (unsigned char) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
390 out[1] = (unsigned char) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
391 out[2] = (unsigned char) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
392 out[3] = (unsigned char) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
401 for (y = 0;y < *height;y++, inrow += nextrow)
403 for (in = inrow, x = 0;x < *width;x++)
405 out[0] = (unsigned char) ((in[0] + in[4]) >> 1);
406 out[1] = (unsigned char) ((in[1] + in[5]) >> 1);
407 out[2] = (unsigned char) ((in[2] + in[6]) >> 1);
408 out[3] = (unsigned char) ((in[3] + in[7]) >> 1);
417 if (*height > destheight)
421 for (y = 0;y < *height;y++, inrow += nextrow * 2)
423 for (in = inrow, x = 0;x < *width;x++)
425 out[0] = (unsigned char) ((in[0] + in[nextrow ]) >> 1);
426 out[1] = (unsigned char) ((in[1] + in[nextrow+1]) >> 1);
427 out[2] = (unsigned char) ((in[2] + in[nextrow+2]) >> 1);
428 out[3] = (unsigned char) ((in[3] + in[nextrow+3]) >> 1);
436 unsigned char *FS_LoadFile(const char *fn, int *len)
438 unsigned char *buf = NULL;
440 FILE *f = fn ? fopen(fn, "rb") : stdin;
446 buf = (unsigned char *) realloc(buf, *len + 65536);
455 n = fread(buf + *len, 1, 65536, f);
472 /* end of darkplaces stuff */
474 uint32_t LittleLong(uint32_t w)
489 int usage(const char *me)
491 fprintf(stderr, "usage:\n"
494 " [-o outfile.dds]\n"
495 " [-t {DXT1|DXT3|DXT5}]\n"
496 " [-r randomcount]\n"
497 " [-c {RGB|YUV|SRGB|SRGB_MIXED|LAB|AVG|WAVG|NORMALMAP}]\n",
502 int main(int argc, char **argv)
504 unsigned char *pic, *picdata;
508 GLenum dxt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
509 const char *infile = NULL, *outfile = NULL;
514 while((opt = getopt(argc, argv, "i:o:t:r:c:")) != -1)
525 if(!strcasecmp(optarg, "DXT1"))
526 dxt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
527 else if(!strcasecmp(optarg, "DXT3"))
528 dxt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
529 else if(!strcasecmp(optarg, "DXT5"))
530 dxt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
532 return usage(argv[0]);
535 snprintf(buf, sizeof(buf), "S2TC_RANDOM_COLORS=%d", atoi(optarg));
536 buf[sizeof(buf)-1] = 0;
540 snprintf(buf, sizeof(buf), "S2TC_COLORDIST_MODE=%s", optarg);
541 buf[sizeof(buf)-1] = 0;
545 return usage(argv[0]);
550 outfh = outfile ? fopen(outfile, "wb") : stdout;
553 printf("opening output failed\n");
557 picdata = FS_LoadFile(infile, &piclen);
560 printf("FS_LoadFile failed\n");
563 pic = LoadTGA_BGRA(picdata, piclen);
566 while(image_width >= (1 << mipcount) || image_height >= (1 << mipcount))
568 // now, (1 << mipcount) >= width, height
572 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
576 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
581 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
588 uint32_t picsize = LittleLong(((image_width+3)/4) * ((image_height+3)/4) * blocksize);
589 uint32_t ddssize = LittleLong(0x7c);
590 uint32_t dds_flags = LittleLong(0xa1007);
591 uint32_t one = LittleLong(1);
592 uint32_t zero = LittleLong(0);
593 uint32_t dds_format_flags = LittleLong(0x04);
594 uint32_t dds_caps1 = LittleLong(0x401008);
595 uint32_t dds_caps2 = LittleLong(0);
596 uint32_t dds_format_size = LittleLong(32);
597 uint32_t dds_mipcount = LittleLong(mipcount);
600 fwrite("DDS ", 4, 1, outfh);
601 fwrite(&ddssize, 4, 1, outfh);
602 fwrite(&dds_flags, 4, 1, outfh);
603 fwrite(&image_height, 4, 1, outfh);
604 fwrite(&image_width, 4, 1, outfh);
605 fwrite(&picsize, 4, 1, outfh);
606 fwrite(&one, 4, 1, outfh);
607 fwrite(&dds_mipcount, 4, 1, outfh);
610 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(&zero, 4, 1, outfh);
615 fwrite(&zero, 4, 1, outfh);
616 fwrite(&zero, 4, 1, outfh);
617 fwrite(&zero, 4, 1, outfh);
620 fwrite(&zero, 4, 1, outfh);
621 fwrite(&zero, 4, 1, outfh);
622 fwrite(&zero, 4, 1, outfh);
623 fwrite(&dds_format_size, 4, 1, outfh);
624 fwrite(&dds_format_flags, 4, 1, outfh);
625 fwrite(fourcc, 4, 1, outfh);
626 fwrite("\x18\x00\x00\x00", 4, 1, outfh);
627 fwrite("\x00\x00\xff\x00", 4, 1, outfh);
630 fwrite("\x00\xff\x00\x00", 4, 1, outfh);
631 fwrite("\xff\x00\x00\x00", 4, 1, outfh);
632 fwrite(&zero, 4, 1, outfh);
633 fwrite(&dds_caps1, 4, 1, outfh);
634 fwrite(&dds_caps2, 4, 1, outfh);
635 fwrite(&zero, 4, 1, outfh);
636 fwrite(&zero, 4, 1, outfh);
637 fwrite(&zero, 4, 1, outfh);
642 int blocks_w = (image_width + 3) / 4;
643 int blocks_h = (image_height + 3) / 4;
644 GLubyte *obuf = (GLubyte *) malloc(blocksize * blocks_w * blocks_h);
645 tx_compress_dxtn(4, image_width, image_height, pic, dxt, obuf, blocks_w * blocksize);
646 fwrite(obuf, blocksize * blocks_w * blocks_h, 1, outfh);
648 if(image_width == 1 && image_height == 1)
650 Image_MipReduce32(pic, pic, &image_width, &image_height, 1, 1);