8 #include "s2tc_compressor.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"
497 " [-r randomcount]\n"
498 " [-c {RGB|YUV|SRGB|SRGB_MIXED|LAB|AVG|NORMALMAP}]\n",
503 int main(int argc, char **argv)
506 unsigned char *pic, *picdata;
509 int blocksize, alpharange;
511 ColorDistMode cd = RGB;
513 const char *infile = NULL, *outfile = NULL;
517 while((opt = getopt(argc, argv, "i:o:t:r:c:")) != -1)
528 if(!strcasecmp(optarg, "DXT1"))
530 else if(!strcasecmp(optarg, "DXT3"))
532 else if(!strcasecmp(optarg, "DXT5"))
535 return usage(argv[0]);
538 nrandom = atoi(optarg);
541 if(!strcasecmp(optarg, "RGB"))
543 else if(!strcasecmp(optarg, "YUV"))
545 else if(!strcasecmp(optarg, "SRGB"))
547 else if(!strcasecmp(optarg, "SRGB_MIXED"))
549 else if(!strcasecmp(optarg, "LAB"))
551 else if(!strcasecmp(optarg, "AVG"))
553 else if(!strcasecmp(optarg, "NORMALMAP"))
556 return usage(argv[0]);
559 return usage(argv[0]);
564 outfh = outfile ? fopen(outfile, "wb") : stdout;
567 printf("opening output failed\n");
571 picdata = FS_LoadFile(infile, &piclen);
574 printf("FS_LoadFile failed\n");
577 pic = LoadTGA_BGRA(picdata, piclen);
580 while(image_width >= (1 << mipcount) || image_height >= (1 << mipcount))
582 // now, (1 << mipcount) >= width, height
605 uint32_t picsize = LittleLong(((image_width+3)/4) * ((image_height+3)/4) * blocksize);
606 uint32_t ddssize = LittleLong(0x7c);
607 uint32_t dds_flags = LittleLong(0xa1007);
608 uint32_t one = LittleLong(1);
609 uint32_t zero = LittleLong(0);
610 uint32_t dds_format_flags = LittleLong(0x04);
611 uint32_t dds_caps1 = LittleLong(0x401008);
612 uint32_t dds_caps2 = LittleLong(0);
613 uint32_t dds_format_size = LittleLong(32);
614 uint32_t dds_mipcount = LittleLong(mipcount);
617 fwrite("DDS ", 4, 1, outfh);
618 fwrite(&ddssize, 4, 1, outfh);
619 fwrite(&dds_flags, 4, 1, outfh);
620 fwrite(&image_height, 4, 1, outfh);
621 fwrite(&image_width, 4, 1, outfh);
622 fwrite(&picsize, 4, 1, outfh);
623 fwrite(&one, 4, 1, outfh);
624 fwrite(&dds_mipcount, 4, 1, outfh);
627 fwrite(&zero, 4, 1, outfh);
628 fwrite(&zero, 4, 1, outfh);
629 fwrite(&zero, 4, 1, outfh);
630 fwrite(&zero, 4, 1, outfh);
631 fwrite(&zero, 4, 1, outfh);
632 fwrite(&zero, 4, 1, outfh);
633 fwrite(&zero, 4, 1, outfh);
634 fwrite(&zero, 4, 1, outfh);
637 fwrite(&zero, 4, 1, outfh);
638 fwrite(&zero, 4, 1, outfh);
639 fwrite(&zero, 4, 1, outfh);
640 fwrite(&dds_format_size, 4, 1, outfh);
641 fwrite(&dds_format_flags, 4, 1, outfh);
642 fwrite(fourcc, 4, 1, outfh);
643 fwrite("\x18\x00\x00\x00", 4, 1, outfh);
644 fwrite("\x00\x00\xff\x00", 4, 1, outfh);
647 fwrite("\x00\xff\x00\x00", 4, 1, outfh);
648 fwrite("\xff\x00\x00\x00", 4, 1, outfh);
649 fwrite(&zero, 4, 1, outfh);
650 fwrite(&dds_caps1, 4, 1, outfh);
651 fwrite(&dds_caps2, 4, 1, outfh);
652 fwrite(&zero, 4, 1, outfh);
653 fwrite(&zero, 4, 1, outfh);
654 fwrite(&zero, 4, 1, outfh);
657 unsigned char *opic = (unsigned char *) malloc(image_width * image_height * 4);
660 rgb565_image(opic, pic, image_width, image_height, 4, 1, alpharange);
661 for(y = 0; y < image_height; y += 4)
662 for(x = 0; x < image_width; x += 4)
664 unsigned char block[16];
665 s2tc_encode_block(block, opic + (x + y * image_width) * 4, image_width, min(4, image_width - x), min(4, image_height - y), dxt, cd, nrandom);
666 fwrite(block, blocksize, 1, outfh);
668 if(image_width == 1 && image_height == 1)
670 Image_MipReduce32(pic, pic, &image_width, &image_height, 1, 1);