8 #include "s2tc_common.h"
15 /* START stuff that originates from image.c in DarkPlaces */
17 Thu Jul 14 21:58:02 CEST 2011
18 21:25:25 @divVerent | LordHavoc: http://paste.pocoo.org/show/438804/
19 21:25:31 @divVerent | can I have this code under a MIT-style license?
20 21:59:58 @LordHavoc | divVerent: yeah, have them under any license you want
21 22:00:11 @LordHavoc | divVerent: my attitude toward licenses is generally "WTFPL would be preferably if I could use it" :P
22 22:04:01 @divVerent | LordHavoc: okay, thanks
25 int image_width, image_height;
27 typedef struct _TargaHeader
29 unsigned char id_length, colormap_type, image_type;
30 unsigned short colormap_index, colormap_length;
31 unsigned char colormap_size;
32 unsigned short x_origin, y_origin, width, height;
33 unsigned char pixel_size, attributes;
37 unsigned char *LoadTGA_BGRA (const unsigned char *f, int filesize)
39 int x, y, pix_inc, row_inci, runlen, alphabits;
40 unsigned char *image_buffer;
41 unsigned int *pixbufi;
42 const unsigned char *fin, *enddata;
43 TargaHeader targa_header;
44 unsigned int palettei[256];
55 enddata = f + filesize;
57 targa_header.id_length = f[0];
58 targa_header.colormap_type = f[1];
59 targa_header.image_type = f[2];
61 targa_header.colormap_index = f[3] + f[4] * 256;
62 targa_header.colormap_length = f[5] + f[6] * 256;
63 targa_header.colormap_size = f[7];
64 targa_header.x_origin = f[8] + f[9] * 256;
65 targa_header.y_origin = f[10] + f[11] * 256;
66 targa_header.width = image_width = f[12] + f[13] * 256;
67 targa_header.height = image_height = f[14] + f[15] * 256;
68 targa_header.pixel_size = f[16];
69 targa_header.attributes = f[17];
71 if (image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0)
73 printf("LoadTGA: invalid size\n");
77 /* advance to end of header */
80 /* skip TARGA image comment (usually 0 bytes) */
81 fin += targa_header.id_length;
83 /* read/skip the colormap if present (note: according to the TARGA spec it */
84 /* can be present even on 1color or greyscale images, just not used by */
86 if (targa_header.colormap_type)
88 if (targa_header.colormap_length > 256)
90 printf("LoadTGA: only up to 256 colormap_length supported\n");
93 if (targa_header.colormap_index)
95 printf("LoadTGA: colormap_index not supported\n");
98 if (targa_header.colormap_size == 24)
100 for (x = 0;x < targa_header.colormap_length;x++)
106 palettei[x] = bgra.i;
109 else if (targa_header.colormap_size == 32)
111 memcpy(palettei, fin, targa_header.colormap_length*4);
112 fin += targa_header.colormap_length * 4;
116 printf("LoadTGA: Only 32 and 24 bit colormap_size supported\n");
121 /* check our pixel_size restrictions according to image_type */
122 switch (targa_header.image_type & ~8)
125 if (targa_header.pixel_size != 24 && targa_header.pixel_size != 32)
127 printf("LoadTGA: only 24bit and 32bit pixel sizes supported for type 2 and type 10 images\n");
132 /* set up a palette to make the loader easier */
133 for (x = 0;x < 256;x++)
135 bgra.b[0] = bgra.b[1] = bgra.b[2] = x;
137 palettei[x] = bgra.i;
139 /* fall through to colormap case */
141 if (targa_header.pixel_size != 8)
143 printf("LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n");
148 printf("LoadTGA: Only type 1, 2, 3, 9, 10, and 11 targa RGB images supported, image_type = %i\n", targa_header.image_type);
152 if (targa_header.attributes & 0x10)
154 printf("LoadTGA: origin must be in top left or bottom left, top right and bottom right are not supported\n");
158 /* number of attribute bits per pixel, we only support 0 or 8 */
159 alphabits = targa_header.attributes & 0x0F;
160 if (alphabits != 8 && alphabits != 0)
162 printf("LoadTGA: only 0 or 8 attribute (alpha) bits supported\n");
166 image_buffer = (unsigned char *)malloc(image_width * image_height * 4);
169 printf("LoadTGA: not enough memory for %i by %i image\n", image_width, image_height);
173 /* If bit 5 of attributes isn't set, the image has been stored from bottom to top */
174 if ((targa_header.attributes & 0x20) == 0)
176 pixbufi = (unsigned int*)image_buffer + (image_height - 1)*image_width;
177 row_inci = -image_width*2;
181 pixbufi = (unsigned int*)image_buffer;
188 if ((targa_header.image_type & ~8) == 2)
189 pix_inc = (targa_header.pixel_size + 7) / 8;
190 switch (targa_header.image_type)
192 case 1: /* colormapped, uncompressed */
193 case 3: /* greyscale, uncompressed */
194 if (fin + image_width * image_height * pix_inc > enddata)
196 for (y = 0;y < image_height;y++, pixbufi += row_inci)
197 for (x = 0;x < image_width;x++)
198 *pixbufi++ = palettei[*fin++];
201 /* BGR or BGRA, uncompressed */
202 if (fin + image_width * image_height * pix_inc > enddata)
204 if (targa_header.pixel_size == 32 && alphabits)
206 for (y = 0;y < image_height;y++)
207 memcpy(pixbufi + y * (image_width + row_inci), fin + y * image_width * pix_inc, image_width*4);
211 for (y = 0;y < image_height;y++, pixbufi += row_inci)
213 for (x = 0;x < image_width;x++, fin += pix_inc)
224 case 9: /* colormapped, RLE */
225 case 11: /* greyscale, RLE */
226 for (y = 0;y < image_height;y++, pixbufi += row_inci)
228 for (x = 0;x < image_width;)
231 break; /* error - truncated file */
235 /* RLE - all pixels the same color */
237 if (fin + pix_inc > enddata)
238 break; /* error - truncated file */
239 if (x + runlen > image_width)
240 break; /* error - line exceeds width */
241 bgra.i = palettei[*fin++];
247 /* uncompressed - all pixels different color */
249 if (fin + pix_inc * runlen > enddata)
250 break; /* error - truncated file */
251 if (x + runlen > image_width)
252 break; /* error - line exceeds width */
254 *pixbufi++ = palettei[*fin++];
258 if (x != image_width)
260 /* pixbufi is useless now */
261 printf("LoadTGA: corrupt file\n");
267 /* BGR or BGRA, RLE */
268 if (targa_header.pixel_size == 32 && alphabits)
270 for (y = 0;y < image_height;y++, pixbufi += row_inci)
272 for (x = 0;x < image_width;)
275 break; /* error - truncated file */
279 /* RLE - all pixels the same color */
281 if (fin + pix_inc > enddata)
282 break; /* error - truncated file */
283 if (x + runlen > image_width)
284 break; /* error - line exceeds width */
295 /* uncompressed - all pixels different color */
297 if (fin + pix_inc * runlen > enddata)
298 break; /* error - truncated file */
299 if (x + runlen > image_width)
300 break; /* error - line exceeds width */
313 if (x != image_width)
315 /* pixbufi is useless now */
316 printf("LoadTGA: corrupt file\n");
323 for (y = 0;y < image_height;y++, pixbufi += row_inci)
325 for (x = 0;x < image_width;)
328 break; /* error - truncated file */
332 /* RLE - all pixels the same color */
334 if (fin + pix_inc > enddata)
335 break; /* error - truncated file */
336 if (x + runlen > image_width)
337 break; /* error - line exceeds width */
348 /* uncompressed - all pixels different color */
350 if (fin + pix_inc * runlen > enddata)
351 break; /* error - truncated file */
352 if (x + runlen > image_width)
353 break; /* error - line exceeds width */
366 if (x != image_width)
368 /* pixbufi is useless now */
369 printf("LoadTGA: corrupt file\n");
376 /* unknown image_type */
383 // in can be the same as out
384 void Image_MipReduce32(const unsigned char *in, unsigned char *out, int *width, int *height, int destwidth, int destheight)
386 const unsigned char *inrow;
388 // note: if given odd width/height this discards the last row/column of
389 // pixels, rather than doing a proper box-filter scale down
391 nextrow = *width * 4;
392 if (*width > destwidth)
395 if (*height > destheight)
399 for (y = 0;y < *height;y++, inrow += nextrow * 2)
401 for (in = inrow, x = 0;x < *width;x++)
403 out[0] = (unsigned char) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
404 out[1] = (unsigned char) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
405 out[2] = (unsigned char) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
406 out[3] = (unsigned char) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
415 for (y = 0;y < *height;y++, inrow += nextrow)
417 for (in = inrow, x = 0;x < *width;x++)
419 out[0] = (unsigned char) ((in[0] + in[4]) >> 1);
420 out[1] = (unsigned char) ((in[1] + in[5]) >> 1);
421 out[2] = (unsigned char) ((in[2] + in[6]) >> 1);
422 out[3] = (unsigned char) ((in[3] + in[7]) >> 1);
431 if (*height > destheight)
435 for (y = 0;y < *height;y++, inrow += nextrow * 2)
437 for (in = inrow, x = 0;x < *width;x++)
439 out[0] = (unsigned char) ((in[0] + in[nextrow ]) >> 1);
440 out[1] = (unsigned char) ((in[1] + in[nextrow+1]) >> 1);
441 out[2] = (unsigned char) ((in[2] + in[nextrow+2]) >> 1);
442 out[3] = (unsigned char) ((in[3] + in[nextrow+3]) >> 1);
450 unsigned char *FS_LoadFile(const char *fn, int *len)
452 unsigned char *buf = NULL;
454 FILE *f = fn ? fopen(fn, "rb") : stdin;
460 buf = (unsigned char *) realloc(buf, *len + 65536);
469 n = fread(buf + *len, 1, 65536, f);
486 /* END of darkplaces stuff */
488 uint32_t LittleLong(uint32_t w)
503 int usage(const char *me)
505 fprintf(stderr, "usage:\n"
508 " [-o outfile.dds]\n"
509 " [-t {DXT1|DXT3|DXT5}]\n",
514 int main(int argc, char **argv)
516 unsigned char *pic, *picdata;
520 GLenum dxt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
521 const char *infile = NULL, *outfile = NULL;
525 while((opt = getopt(argc, argv, "i:o:t:r:c:")) != -1)
536 if(!strcasecmp(optarg, "DXT1"))
537 dxt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
538 else if(!strcasecmp(optarg, "DXT3"))
539 dxt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
540 else if(!strcasecmp(optarg, "DXT5"))
541 dxt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
543 return usage(argv[0]);
546 return usage(argv[0]);
551 outfh = outfile ? fopen(outfile, "wb") : stdout;
554 printf("opening output failed\n");
558 picdata = FS_LoadFile(infile, &piclen);
561 printf("FS_LoadFile failed\n");
564 pic = LoadTGA_BGRA(picdata, piclen);
566 for(int x = 0; x < image_width*image_height; ++x)
567 std::swap(pic[4*x], pic[4*x+2]);
570 while(image_width >= (1 << mipcount) || image_height >= (1 << mipcount))
572 // now, (1 << mipcount) >= width, height
576 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
580 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
585 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
592 uint32_t picsize = LittleLong(((image_width+3)/4) * ((image_height+3)/4) * blocksize);
593 uint32_t ddssize = LittleLong(0x7c);
594 uint32_t dds_flags = LittleLong(0xa1007);
595 uint32_t one = LittleLong(1);
596 uint32_t zero = LittleLong(0);
597 uint32_t dds_format_flags = LittleLong(0x04);
598 uint32_t dds_caps1 = LittleLong(0x401008);
599 uint32_t dds_caps2 = LittleLong(0);
600 uint32_t dds_format_size = LittleLong(32);
601 uint32_t dds_mipcount = LittleLong(mipcount);
604 fwrite("DDS ", 4, 1, outfh);
605 fwrite(&ddssize, 4, 1, outfh);
606 fwrite(&dds_flags, 4, 1, outfh);
607 fwrite(&image_height, 4, 1, outfh);
608 fwrite(&image_width, 4, 1, outfh);
609 fwrite(&picsize, 4, 1, outfh);
610 fwrite(&one, 4, 1, outfh);
611 fwrite(&dds_mipcount, 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);
618 fwrite(&zero, 4, 1, outfh);
619 fwrite(&zero, 4, 1, outfh);
620 fwrite(&zero, 4, 1, outfh);
621 fwrite(&zero, 4, 1, outfh);
624 fwrite(&zero, 4, 1, outfh);
625 fwrite(&zero, 4, 1, outfh);
626 fwrite(&zero, 4, 1, outfh);
627 fwrite(&dds_format_size, 4, 1, outfh);
628 fwrite(&dds_format_flags, 4, 1, outfh);
629 fwrite(fourcc, 4, 1, outfh);
630 fwrite("\x18\x00\x00\x00", 4, 1, outfh);
631 fwrite("\x00\x00\xff\x00", 4, 1, outfh);
634 fwrite("\x00\xff\x00\x00", 4, 1, outfh);
635 fwrite("\xff\x00\x00\x00", 4, 1, outfh);
636 fwrite(&zero, 4, 1, outfh);
637 fwrite(&dds_caps1, 4, 1, outfh);
638 fwrite(&dds_caps2, 4, 1, outfh);
639 fwrite(&zero, 4, 1, outfh);
640 fwrite(&zero, 4, 1, outfh);
641 fwrite(&zero, 4, 1, outfh);
646 int blocks_w = (image_width + 3) / 4;
647 int blocks_h = (image_height + 3) / 4;
648 GLubyte *obuf = (GLubyte *) malloc(blocksize * blocks_w * blocks_h);
649 tx_compress_dxtn(4, image_width, image_height, pic, dxt, obuf, blocks_w * blocksize);
650 fwrite(obuf, blocksize * blocks_w * blocks_h, 1, outfh);
652 if(image_width == 1 && image_height == 1)
654 Image_MipReduce32(pic, pic, &image_width, &image_height, 1, 1);