8 template <class T> inline T min(const T &a, const T &b)
15 template <class T> inline T max(const T &a, const T &b)
22 /* START stuff that originates from image.c in DarkPlaces */
23 int image_width, image_height;
25 typedef struct _TargaHeader
27 unsigned char id_length, colormap_type, image_type;
28 unsigned short colormap_index, colormap_length;
29 unsigned char colormap_size;
30 unsigned short x_origin, y_origin, width, height;
31 unsigned char pixel_size, attributes;
35 unsigned char *LoadTGA_BGRA (const unsigned char *f, int filesize)
37 int x, y, pix_inc, row_inci, runlen, alphabits;
38 unsigned char *image_buffer;
39 unsigned int *pixbufi;
40 const unsigned char *fin, *enddata;
41 TargaHeader targa_header;
42 unsigned int palettei[256];
53 enddata = f + filesize;
55 targa_header.id_length = f[0];
56 targa_header.colormap_type = f[1];
57 targa_header.image_type = f[2];
59 targa_header.colormap_index = f[3] + f[4] * 256;
60 targa_header.colormap_length = f[5] + f[6] * 256;
61 targa_header.colormap_size = f[7];
62 targa_header.x_origin = f[8] + f[9] * 256;
63 targa_header.y_origin = f[10] + f[11] * 256;
64 targa_header.width = image_width = f[12] + f[13] * 256;
65 targa_header.height = image_height = f[14] + f[15] * 256;
66 targa_header.pixel_size = f[16];
67 targa_header.attributes = f[17];
69 if (image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0)
71 printf("LoadTGA: invalid size\n");
75 /* advance to end of header */
78 /* skip TARGA image comment (usually 0 bytes) */
79 fin += targa_header.id_length;
81 /* read/skip the colormap if present (note: according to the TARGA spec it */
82 /* can be present even on 1color or greyscale images, just not used by */
84 if (targa_header.colormap_type)
86 if (targa_header.colormap_length > 256)
88 printf("LoadTGA: only up to 256 colormap_length supported\n");
91 if (targa_header.colormap_index)
93 printf("LoadTGA: colormap_index not supported\n");
96 if (targa_header.colormap_size == 24)
98 for (x = 0;x < targa_header.colormap_length;x++)
104 palettei[x] = bgra.i;
107 else if (targa_header.colormap_size == 32)
109 memcpy(palettei, fin, targa_header.colormap_length*4);
110 fin += targa_header.colormap_length * 4;
114 printf("LoadTGA: Only 32 and 24 bit colormap_size supported\n");
119 /* check our pixel_size restrictions according to image_type */
120 switch (targa_header.image_type & ~8)
123 if (targa_header.pixel_size != 24 && targa_header.pixel_size != 32)
125 printf("LoadTGA: only 24bit and 32bit pixel sizes supported for type 2 and type 10 images\n");
130 /* set up a palette to make the loader easier */
131 for (x = 0;x < 256;x++)
133 bgra.b[0] = bgra.b[1] = bgra.b[2] = x;
135 palettei[x] = bgra.i;
137 /* fall through to colormap case */
139 if (targa_header.pixel_size != 8)
141 printf("LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n");
146 printf("LoadTGA: Only type 1, 2, 3, 9, 10, and 11 targa RGB images supported, image_type = %i\n", targa_header.image_type);
150 if (targa_header.attributes & 0x10)
152 printf("LoadTGA: origin must be in top left or bottom left, top right and bottom right are not supported\n");
156 /* number of attribute bits per pixel, we only support 0 or 8 */
157 alphabits = targa_header.attributes & 0x0F;
158 if (alphabits != 8 && alphabits != 0)
160 printf("LoadTGA: only 0 or 8 attribute (alpha) bits supported\n");
164 image_buffer = (unsigned char *)malloc(image_width * image_height * 4);
167 printf("LoadTGA: not enough memory for %i by %i image\n", image_width, image_height);
171 /* If bit 5 of attributes isn't set, the image has been stored from bottom to top */
172 if ((targa_header.attributes & 0x20) == 0)
174 pixbufi = (unsigned int*)image_buffer + (image_height - 1)*image_width;
175 row_inci = -image_width*2;
179 pixbufi = (unsigned int*)image_buffer;
186 if ((targa_header.image_type & ~8) == 2)
187 pix_inc = (targa_header.pixel_size + 7) / 8;
188 switch (targa_header.image_type)
190 case 1: /* colormapped, uncompressed */
191 case 3: /* greyscale, uncompressed */
192 if (fin + image_width * image_height * pix_inc > enddata)
194 for (y = 0;y < image_height;y++, pixbufi += row_inci)
195 for (x = 0;x < image_width;x++)
196 *pixbufi++ = palettei[*fin++];
199 /* BGR or BGRA, uncompressed */
200 if (fin + image_width * image_height * pix_inc > enddata)
202 if (targa_header.pixel_size == 32 && alphabits)
204 for (y = 0;y < image_height;y++)
205 memcpy(pixbufi + y * (image_width + row_inci), fin + y * image_width * pix_inc, image_width*4);
209 for (y = 0;y < image_height;y++, pixbufi += row_inci)
211 for (x = 0;x < image_width;x++, fin += pix_inc)
222 case 9: /* colormapped, RLE */
223 case 11: /* greyscale, RLE */
224 for (y = 0;y < image_height;y++, pixbufi += row_inci)
226 for (x = 0;x < image_width;)
229 break; /* error - truncated file */
233 /* RLE - all pixels the same color */
235 if (fin + pix_inc > enddata)
236 break; /* error - truncated file */
237 if (x + runlen > image_width)
238 break; /* error - line exceeds width */
239 bgra.i = palettei[*fin++];
245 /* uncompressed - all pixels different color */
247 if (fin + pix_inc * runlen > enddata)
248 break; /* error - truncated file */
249 if (x + runlen > image_width)
250 break; /* error - line exceeds width */
252 *pixbufi++ = palettei[*fin++];
256 if (x != image_width)
258 /* pixbufi is useless now */
259 printf("LoadTGA: corrupt file\n");
265 /* BGR or BGRA, RLE */
266 if (targa_header.pixel_size == 32 && alphabits)
268 for (y = 0;y < image_height;y++, pixbufi += row_inci)
270 for (x = 0;x < image_width;)
273 break; /* error - truncated file */
277 /* RLE - all pixels the same color */
279 if (fin + pix_inc > enddata)
280 break; /* error - truncated file */
281 if (x + runlen > image_width)
282 break; /* error - line exceeds width */
293 /* uncompressed - all pixels different color */
295 if (fin + pix_inc * runlen > enddata)
296 break; /* error - truncated file */
297 if (x + runlen > image_width)
298 break; /* error - line exceeds width */
311 if (x != image_width)
313 /* pixbufi is useless now */
314 printf("LoadTGA: corrupt file\n");
321 for (y = 0;y < image_height;y++, pixbufi += row_inci)
323 for (x = 0;x < image_width;)
326 break; /* error - truncated file */
330 /* RLE - all pixels the same color */
332 if (fin + pix_inc > enddata)
333 break; /* error - truncated file */
334 if (x + runlen > image_width)
335 break; /* error - line exceeds width */
346 /* uncompressed - all pixels different color */
348 if (fin + pix_inc * runlen > enddata)
349 break; /* error - truncated file */
350 if (x + runlen > image_width)
351 break; /* error - line exceeds width */
364 if (x != image_width)
366 /* pixbufi is useless now */
367 printf("LoadTGA: corrupt file\n");
374 /* unknown image_type */
381 // in can be the same as out
382 void Image_MipReduce32(const unsigned char *in, unsigned char *out, int *width, int *height, int destwidth, int destheight)
384 const unsigned char *inrow;
386 // note: if given odd width/height this discards the last row/column of
387 // pixels, rather than doing a proper box-filter scale down
389 nextrow = *width * 4;
390 if (*width > destwidth)
393 if (*height > destheight)
397 for (y = 0;y < *height;y++, inrow += nextrow * 2)
399 for (in = inrow, x = 0;x < *width;x++)
401 out[0] = (unsigned char) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
402 out[1] = (unsigned char) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
403 out[2] = (unsigned char) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
404 out[3] = (unsigned char) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
413 for (y = 0;y < *height;y++, inrow += nextrow)
415 for (in = inrow, x = 0;x < *width;x++)
417 out[0] = (unsigned char) ((in[0] + in[4]) >> 1);
418 out[1] = (unsigned char) ((in[1] + in[5]) >> 1);
419 out[2] = (unsigned char) ((in[2] + in[6]) >> 1);
420 out[3] = (unsigned char) ((in[3] + in[7]) >> 1);
429 if (*height > destheight)
433 for (y = 0;y < *height;y++, inrow += nextrow * 2)
435 for (in = inrow, x = 0;x < *width;x++)
437 out[0] = (unsigned char) ((in[0] + in[nextrow ]) >> 1);
438 out[1] = (unsigned char) ((in[1] + in[nextrow+1]) >> 1);
439 out[2] = (unsigned char) ((in[2] + in[nextrow+2]) >> 1);
440 out[3] = (unsigned char) ((in[3] + in[nextrow+3]) >> 1);
448 unsigned char *FS_LoadFile(const char *fn, int *len)
450 unsigned char *buf = NULL;
452 FILE *f = fn ? fopen(fn, "rb") : stdin;
458 buf = (unsigned char *) realloc(buf, *len + 65536);
467 n = fread(buf + *len, 1, 65536, f);
484 /* end of darkplaces stuff */
494 inline bool operator<(const color_t &a, const color_t &b)
507 // 16 differences must fit in int
508 // i.e. a difference must be lower than 2^27
510 // shift right, rounded
511 #define SHRR(a,n) (((a) + (1 << ((n)-1))) >> (n))
513 inline int color_dist_avg(const color_t &a, const color_t &b)
515 int dr = a.r - b.r; // multiplier: 31 (-1..1)
516 int dg = a.g - b.g; // multiplier: 63 (-1..1)
517 int db = a.b - b.b; // multiplier: 31 (-1..1)
518 return ((dr*dr) << 2) + dg*dg + ((db*db) << 2);
521 inline int color_dist_yuv(const color_t &a, const color_t &b)
523 int dr = a.r - b.r; // multiplier: 31 (-1..1)
524 int dg = a.g - b.g; // multiplier: 63 (-1..1)
525 int db = a.b - b.b; // multiplier: 31 (-1..1)
526 int y = dr * 30*2 + dg * 59 + db * 11*2; // multiplier: 6259
527 int u = dr * 202 - y; // * 0.5 / (1 - 0.30)
528 int v = db * 202 - y; // * 0.5 / (1 - 0.11)
529 return ((y*y) << 1) + SHRR(u*u, 3) + SHRR(v*v, 4);
530 // weight for u: sqrt(2^-4) / (0.5 / (1 - 0.30)) = 0.350
531 // weight for v: sqrt(2^-5) / (0.5 / (1 - 0.11)) = 0.315
534 inline int color_dist_rgb(const color_t &a, const color_t &b)
536 int dr = a.r - b.r; // multiplier: 31 (-1..1)
537 int dg = a.g - b.g; // multiplier: 63 (-1..1)
538 int db = a.b - b.b; // multiplier: 31 (-1..1)
539 int y = dr * 21*2 + dg * 72 + db * 7*2; // multiplier: 6272
540 int u = dr * 202 - y; // * 0.5 / (1 - 0.21)
541 int v = db * 202 - y; // * 0.5 / (1 - 0.07)
542 return ((y*y) << 1) + SHRR(u*u, 3) + SHRR(v*v, 4);
543 // weight for u: sqrt(2^-4) / (0.5 / (1 - 0.21)) = 0.395
544 // weight for v: sqrt(2^-5) / (0.5 / (1 - 0.07)) = 0.328
547 inline int color_dist_srgb(const color_t &a, const color_t &b)
549 int dr = a.r * (int) a.r - b.r * (int) b.r; // multiplier: 31*31
550 int dg = a.g * (int) a.g - b.g * (int) b.g; // multiplier: 63*63
551 int db = a.b * (int) a.b - b.b * (int) b.b; // multiplier: 31*31
552 int y = dr * 21*2*2 + dg * 72 + db * 7*2*2; // multiplier: 393400
553 int u = dr * 409 - y; // * 0.5 / (1 - 0.30)
554 int v = db * 409 - y; // * 0.5 / (1 - 0.11)
555 int sy = SHRR(y, 3) * SHRR(y, 4);
556 int su = SHRR(u, 3) * SHRR(u, 4);
557 int sv = SHRR(v, 3) * SHRR(v, 4);
558 return SHRR(sy, 4) + SHRR(su, 8) + SHRR(sv, 9);
559 // weight for u: sqrt(2^-4) / (0.5 / (1 - 0.30)) = 0.350
560 // weight for v: sqrt(2^-5) / (0.5 / (1 - 0.11)) = 0.315
563 inline int srgb_get_y(const color_t &a)
566 int r = a.r * (int) a.r;
567 int g = a.g * (int) a.g;
568 int b = a.b * (int) a.b;
570 int y = 37 * (r * 21*2*2 + g * 72 + b * 7*2*2); // multiplier: 14555800
571 // square root it (!)
572 y = sqrt(y); // now in range 0 to 3815
576 inline int color_dist_srgb_mixed(const color_t &a, const color_t &b)
579 int ay = srgb_get_y(a);
580 int by = srgb_get_y(b);
582 int au = a.r * 191 - ay;
583 int av = a.b * 191 - ay;
584 int bu = b.r * 191 - by;
585 int bv = b.b * 191 - by;
590 return ((y*y) << 3) + SHRR(u*u, 1) + SHRR(v*v, 2);
595 // FIXME this is likely broken
596 inline int color_dist_lab_srgb(const color_t &a, const color_t &b)
599 float ar = powf(a.r / 31.0f, 2.4f);
600 float ag = powf(a.g / 63.0f, 2.4f);
601 float ab = powf(a.b / 31.0f, 2.4f);
602 float br = powf(b.r / 31.0f, 2.4f);
603 float bg = powf(b.g / 63.0f, 2.4f);
604 float bb = powf(b.b / 31.0f, 2.4f);
605 // convert to CIE XYZ
606 float aX = 0.4124f * ar + 0.3576f * ag + 0.1805f * ab;
607 float aY = 0.2126f * ar + 0.7152f * ag + 0.0722f * ab;
608 float aZ = 0.0193f * ar + 0.1192f * ag + 0.9505f * ab;
609 float bX = 0.4124f * br + 0.3576f * bg + 0.1805f * bb;
610 float bY = 0.2126f * br + 0.7152f * bg + 0.0722f * bb;
611 float bZ = 0.0193f * br + 0.1192f * bg + 0.9505f * bb;
612 // convert to CIE Lab
616 float aL = 116 * cbrtf(aY / Yn) - 16;
617 float aA = 500 * (cbrtf(aX / Xn) - cbrtf(aY / Yn));
618 float aB = 200 * (cbrtf(aY / Yn) - cbrtf(aZ / Zn));
619 float bL = 116 * cbrtf(bY / Yn) - 16;
620 float bA = 500 * (cbrtf(bX / Xn) - cbrtf(bY / Yn));
621 float bB = 200 * (cbrtf(bY / Yn) - cbrtf(bZ / Zn));
622 // euclidean distance, but moving weight away from A and B
623 return 1000 * ((aL - bL) * (aL - bL) + (aA - bA) * (aA - bA) + (aB - bB) * (aB - bB));
626 inline int color_dist_normalmap(const color_t &a, const color_t &b)
629 ca[0] = a.r / 31.0 * 2 - 1;
630 ca[1] = a.g / 63.0 * 2 - 1;
631 ca[2] = a.b / 31.0 * 2 - 1;
632 cb[0] = b.r / 31.0 * 2 - 1;
633 cb[1] = b.g / 63.0 * 2 - 1;
634 cb[2] = b.b / 31.0 * 2 - 1;
639 (cb[0] - ca[0]) * (cb[0] - ca[0])
641 (cb[1] - ca[1]) * (cb[1] - ca[1])
643 (cb[2] - ca[2]) * (cb[2] - ca[2])
646 // max value: 500 * (4 + 4 + 4) = 6000
649 typedef int ColorDistFunc(const color_t &a, const color_t &b);
651 inline int alpha_dist(unsigned char a, unsigned char b)
653 return (a - (int) b) * (a - (int) b);
656 template <class T, class F>
658 // m: total color count (including non-counted inputs)
660 void reduce_colors_inplace(T *c, int n, int m, F dist)
668 for(i = 0; i < n; ++i)
671 for(j = i+1; j < n; ++j)
673 int d = dist(c[i], c[j]);
674 dists[i][j] = dists[j][i] = d;
680 for(j = 0; j < n; ++j)
682 int d = dist(c[i], c[j]);
686 for(i = 0; i < m; ++i)
687 for(j = i+1; j < m; ++j)
690 for(k = 0; k < n; ++k)
692 int di = dists[i][k];
693 int dj = dists[j][k];
697 if(bestsum < 0 || sum < bestsum)
709 template <class T, class F>
710 void reduce_colors_inplace_2fixpoints(T *c, int n, int m, F dist, const T &fix0, const T &fix1)
718 for(i = 0; i < n; ++i)
721 for(j = i+1; j < n; ++j)
723 int d = dist(c[i], c[j]);
724 dists[i][j] = dists[j][i] = d;
730 for(j = 0; j < n; ++j)
732 int d = dist(c[i], c[j]);
736 // then the two extra rows
737 for(j = 0; j < n; ++j)
739 int d = dist(fix0, c[j]);
742 for(j = 0; j < n; ++j)
744 int d = dist(fix1, c[j]);
747 for(i = 0; i < m; ++i)
748 for(j = i+1; j < m; ++j)
751 for(k = 0; k < n; ++k)
753 int di = dists[i][k];
754 int dj = dists[j][k];
755 int d0 = dists[m][k];
756 int d1 = dists[m+1][k];
757 int m = min(min(di, dj), min(d0, d1));
760 if(bestsum < 0 || sum < bestsum)
773 inline int diffuse(float *diff, float src)
782 void rgb565_image(unsigned char *out, const unsigned char *rgba, int w, int h, int alpharange)
789 for(y = 0; y < h; ++y)
790 for(x = 0; x < w; ++x)
792 out[(x + y * w) * 4 + 2] = diffuse(&diffuse_r, rgba[(x + y * w) * 4 + 2] * 31.0 / 255.0);
793 out[(x + y * w) * 4 + 1] = diffuse(&diffuse_g, rgba[(x + y * w) * 4 + 1] * 63.0 / 255.0);
794 out[(x + y * w) * 4 + 0] = diffuse(&diffuse_b, rgba[(x + y * w) * 4 + 0] * 31.0 / 255.0);
795 out[(x + y * w) * 4 + 3] = diffuse(&diffuse_a, rgba[(x + y * w) * 4 + 3] * (alpharange / 255.0));
816 template<DxtMode dxt, ColorDistFunc ColorDist, bool userandom>
817 void s2tc_encode_block(unsigned char *out, const unsigned char *rgba, int iw, int w, int h, int nrandom)
819 color_t c[16 + (userandom ? nrandom : 0)];
821 unsigned char ca[16];
825 for(x = 0; x < w; ++x)
826 for(y = 0; y < h; ++y)
828 c[n].r = rgba[(x + y * iw) * 4 + 2];
829 c[n].g = rgba[(x + y * iw) * 4 + 1];
830 c[n].b = rgba[(x + y * iw) * 4 + 0];
832 ca[n] = rgba[(x + y * iw) * 4 + 3];
842 for(x = 1; x < n; ++x)
844 mins.r = min(mins.r, c[x].r);
845 mins.g = min(mins.g, c[x].g);
846 mins.b = min(mins.b, c[x].b);
847 maxs.r = max(maxs.r, c[x].r);
848 maxs.g = max(maxs.g, c[x].g);
849 maxs.b = max(maxs.b, c[x].b);
851 color_t len = { maxs.r - mins.r + 1, maxs.g - mins.g + 1, maxs.b - mins.b + 1 };
852 for(x = 0; x < nrandom; ++x)
854 c[m].r = mins.r + rand() % len.r;
855 c[m].g = mins.g + rand() % len.g;
856 c[m].b = mins.b + rand() % len.b;
861 reduce_colors_inplace(c, n, m, ColorDist);
864 reduce_colors_inplace_2fixpoints(ca, n, n, alpha_dist, (unsigned char) 0, (unsigned char) 255);
886 out[8] = ((c[0].g & 0x07) << 5) | c[0].b;
887 out[9] = (c[0].r << 3) | (c[0].g >> 3);
888 out[10] = ((c[1].g & 0x07) << 5) | c[1].b;
889 out[11] = (c[1].r << 3) | (c[1].g >> 3);
892 out[0] = ((c[0].g & 0x07) << 5) | c[0].b;
893 out[1] = (c[0].r << 3) | (c[0].g >> 3);
894 out[2] = ((c[1].g & 0x07) << 5) | c[1].b;
895 out[3] = (c[1].r << 3) | (c[1].g >> 3);
898 for(x = 0; x < w; ++x)
899 for(y = 0; y < h; ++y)
901 int pindex = (x+y*4);
902 c[2].r = rgba[(x + y * iw) * 4 + 2];
903 c[2].g = rgba[(x + y * iw) * 4 + 1];
904 c[2].b = rgba[(x + y * iw) * 4 + 0];
905 ca[2] = rgba[(x + y * iw) * 4 + 3];
911 int bitindex = pindex * 3;
912 da[0] = alpha_dist(ca[0], ca[2]);
913 da[1] = alpha_dist(ca[1], ca[2]);
914 da[2] = alpha_dist(0, ca[2]);
915 da[3] = alpha_dist(255, ca[2]);
916 if(da[2] <= da[0] && da[2] <= da[1] && da[2] <= da[3])
920 out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
922 out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
924 else if(da[3] <= da[0] && da[3] <= da[1])
927 out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
929 out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
931 out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
933 else if(da[0] <= da[1])
940 out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
943 if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
945 int bitindex = pindex * 2;
946 out[bitindex / 8 + 12] |= (1 << (bitindex % 8));
951 int bitindex = pindex * 4;
952 out[bitindex / 8 + 0] |= (ca[2] << (bitindex % 8));
954 if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
956 int bitindex = pindex * 2;
957 out[bitindex / 8 + 12] |= (1 << (bitindex % 8));
962 int bitindex = pindex * 2;
964 out[bitindex / 8 + 4] |= (3 << (bitindex % 8));
965 else if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
966 out[bitindex / 8 + 4] |= (1 << (bitindex % 8));
973 // compile time dispatch magic
974 template<DxtMode dxt, ColorDistFunc ColorDist>
975 void s2tc_encode_block(unsigned char *out, const unsigned char *rgba, int iw, int w, int h, int nrandom)
978 s2tc_encode_block<dxt, ColorDist, true>(out, rgba, iw, w, h, nrandom);
980 s2tc_encode_block<dxt, ColorDist, false>(out, rgba, iw, w, h, nrandom);
983 template<ColorDistFunc ColorDist>
984 void s2tc_encode_block(unsigned char *out, const unsigned char *rgba, int iw, int w, int h, DxtMode dxt, int nrandom)
989 s2tc_encode_block<DXT1, ColorDist>(out, rgba, iw, w, h, nrandom);
992 s2tc_encode_block<DXT3, ColorDist>(out, rgba, iw, w, h, nrandom);
996 s2tc_encode_block<DXT5, ColorDist>(out, rgba, iw, w, h, nrandom);
1001 void s2tc_encode_block(unsigned char *out, const unsigned char *rgba, int iw, int w, int h, DxtMode dxt, ColorDistMode cd, int nrandom)
1006 s2tc_encode_block<color_dist_rgb>(out, rgba, iw, w, h, dxt, nrandom);
1009 s2tc_encode_block<color_dist_yuv>(out, rgba, iw, w, h, dxt, nrandom);
1012 s2tc_encode_block<color_dist_srgb>(out, rgba, iw, w, h, dxt, nrandom);
1015 s2tc_encode_block<color_dist_srgb_mixed>(out, rgba, iw, w, h, dxt, nrandom);
1018 s2tc_encode_block<color_dist_lab_srgb>(out, rgba, iw, w, h, dxt, nrandom);
1021 s2tc_encode_block<color_dist_avg>(out, rgba, iw, w, h, dxt, nrandom);
1024 s2tc_encode_block<color_dist_normalmap>(out, rgba, iw, w, h, dxt, nrandom);
1029 uint32_t LittleLong(uint32_t w)
1044 int usage(const char *me)
1046 fprintf(stderr, "usage:\n"
1048 " [-i infile.tga]\n"
1049 " [-o outfile.dds]\n"
1050 " [-t {DXT1|DXT3|DXT5}]\n"
1051 " [-r randomcount]\n"
1052 " [-c {RGB|YUV|SRGB|SRGB_MIXED|LAB|AVG|NORMALMAP}]\n",
1057 int main(int argc, char **argv)
1060 unsigned char *pic, *picdata;
1063 int blocksize, alpharange;
1065 ColorDistMode cd = RGB;
1067 const char *infile = NULL, *outfile = NULL;
1071 while((opt = getopt(argc, argv, "i:o:t:r:c:")) != -1)
1082 if(!strcasecmp(optarg, "DXT1"))
1084 else if(!strcasecmp(optarg, "DXT3"))
1086 else if(!strcasecmp(optarg, "DXT5"))
1089 return usage(argv[0]);
1092 nrandom = atoi(optarg);
1095 if(!strcasecmp(optarg, "RGB"))
1097 else if(!strcasecmp(optarg, "YUV"))
1099 else if(!strcasecmp(optarg, "SRGB"))
1101 else if(!strcasecmp(optarg, "SRGB_MIXED"))
1103 else if(!strcasecmp(optarg, "LAB"))
1105 else if(!strcasecmp(optarg, "AVG"))
1107 else if(!strcasecmp(optarg, "NORMALMAP"))
1110 return usage(argv[0]);
1113 return usage(argv[0]);
1118 outfh = outfile ? fopen(outfile, "wb") : stdout;
1121 printf("opening output failed\n");
1125 picdata = FS_LoadFile(infile, &piclen);
1128 printf("FS_LoadFile failed\n");
1131 pic = LoadTGA_BGRA(picdata, piclen);
1134 while(image_width >= (1 << mipcount) || image_height >= (1 << mipcount))
1136 // now, (1 << mipcount) >= width, height
1159 uint32_t picsize = LittleLong(((image_width+3)/4) * ((image_height+3)/4) * blocksize);
1160 uint32_t ddssize = LittleLong(0x7c);
1161 uint32_t dds_flags = LittleLong(0xa1007);
1162 uint32_t one = LittleLong(1);
1163 uint32_t zero = LittleLong(0);
1164 uint32_t dds_format_flags = LittleLong(0x04);
1165 uint32_t dds_caps1 = LittleLong(0x401008);
1166 uint32_t dds_caps2 = LittleLong(0);
1167 uint32_t dds_format_size = LittleLong(32);
1168 uint32_t dds_mipcount = LittleLong(mipcount);
1171 fwrite("DDS ", 4, 1, outfh);
1172 fwrite(&ddssize, 4, 1, outfh);
1173 fwrite(&dds_flags, 4, 1, outfh);
1174 fwrite(&image_height, 4, 1, outfh);
1175 fwrite(&image_width, 4, 1, outfh);
1176 fwrite(&picsize, 4, 1, outfh);
1177 fwrite(&one, 4, 1, outfh);
1178 fwrite(&dds_mipcount, 4, 1, outfh);
1181 fwrite(&zero, 4, 1, outfh);
1182 fwrite(&zero, 4, 1, outfh);
1183 fwrite(&zero, 4, 1, outfh);
1184 fwrite(&zero, 4, 1, outfh);
1185 fwrite(&zero, 4, 1, outfh);
1186 fwrite(&zero, 4, 1, outfh);
1187 fwrite(&zero, 4, 1, outfh);
1188 fwrite(&zero, 4, 1, outfh);
1191 fwrite(&zero, 4, 1, outfh);
1192 fwrite(&zero, 4, 1, outfh);
1193 fwrite(&zero, 4, 1, outfh);
1194 fwrite(&dds_format_size, 4, 1, outfh);
1195 fwrite(&dds_format_flags, 4, 1, outfh);
1196 fwrite(fourcc, 4, 1, outfh);
1197 fwrite("\x18\x00\x00\x00", 4, 1, outfh);
1198 fwrite("\x00\x00\xff\x00", 4, 1, outfh);
1201 fwrite("\x00\xff\x00\x00", 4, 1, outfh);
1202 fwrite("\xff\x00\x00\x00", 4, 1, outfh);
1203 fwrite(&zero, 4, 1, outfh);
1204 fwrite(&dds_caps1, 4, 1, outfh);
1205 fwrite(&dds_caps2, 4, 1, outfh);
1206 fwrite(&zero, 4, 1, outfh);
1207 fwrite(&zero, 4, 1, outfh);
1208 fwrite(&zero, 4, 1, outfh);
1211 unsigned char *opic = (unsigned char *) malloc(image_width * image_height * 4);
1214 rgb565_image(opic, pic, image_width, image_height, alpharange);
1215 for(y = 0; y < image_height; y += 4)
1216 for(x = 0; x < image_width; x += 4)
1218 unsigned char block[16];
1219 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);
1220 fwrite(block, blocksize, 1, outfh);
1222 if(image_width == 1 && image_height == 1)
1224 Image_MipReduce32(pic, pic, &image_width, &image_height, 1, 1);