6 #include "s2tc_compressor.h"
7 #include "s2tc_common.h"
17 inline bool operator<(const color_t &a, const color_t &b)
29 // 16 differences must fit in int
30 // i.e. a difference must be lower than 2^27
32 // shift right, rounded
33 #define SHRR(a,n) (((a) + (1 << ((n)-1))) >> (n))
35 inline int color_dist_avg(const color_t &a, const color_t &b)
37 int dr = a.r - b.r; // multiplier: 31 (-1..1)
38 int dg = a.g - b.g; // multiplier: 63 (-1..1)
39 int db = a.b - b.b; // multiplier: 31 (-1..1)
40 return ((dr*dr) << 2) + dg*dg + ((db*db) << 2);
43 inline int color_dist_wavg(const color_t &a, const color_t &b)
45 int dr = a.r - b.r; // multiplier: 31 (-1..1)
46 int dg = a.g - b.g; // multiplier: 63 (-1..1)
47 int db = a.b - b.b; // multiplier: 31 (-1..1)
48 return ((dr*dr) << 2) + ((dg*dg) << 2) + (db*db);
52 inline int color_dist_yuv(const color_t &a, const color_t &b)
54 int dr = a.r - b.r; // multiplier: 31 (-1..1)
55 int dg = a.g - b.g; // multiplier: 63 (-1..1)
56 int db = a.b - b.b; // multiplier: 31 (-1..1)
57 int y = dr * 30*2 + dg * 59 + db * 11*2; // multiplier: 6259
58 int u = dr * 202 - y; // * 0.5 / (1 - 0.30)
59 int v = db * 202 - y; // * 0.5 / (1 - 0.11)
60 return ((y*y) << 1) + SHRR(u*u, 3) + SHRR(v*v, 4);
61 // weight for u: sqrt(2^-4) / (0.5 / (1 - 0.30)) = 0.350
62 // weight for v: sqrt(2^-5) / (0.5 / (1 - 0.11)) = 0.315
65 inline int color_dist_rgb(const color_t &a, const color_t &b)
67 int dr = a.r - b.r; // multiplier: 31 (-1..1)
68 int dg = a.g - b.g; // multiplier: 63 (-1..1)
69 int db = a.b - b.b; // multiplier: 31 (-1..1)
70 int y = dr * 21*2 + dg * 72 + db * 7*2; // multiplier: 6272
71 int u = dr * 202 - y; // * 0.5 / (1 - 0.21)
72 int v = db * 202 - y; // * 0.5 / (1 - 0.07)
73 return ((y*y) << 1) + SHRR(u*u, 3) + SHRR(v*v, 4);
74 // weight for u: sqrt(2^-4) / (0.5 / (1 - 0.21)) = 0.395
75 // weight for v: sqrt(2^-5) / (0.5 / (1 - 0.07)) = 0.328
78 inline int color_dist_srgb(const color_t &a, const color_t &b)
80 int dr = a.r * (int) a.r - b.r * (int) b.r; // multiplier: 31*31
81 int dg = a.g * (int) a.g - b.g * (int) b.g; // multiplier: 63*63
82 int db = a.b * (int) a.b - b.b * (int) b.b; // multiplier: 31*31
83 int y = dr * 21*2*2 + dg * 72 + db * 7*2*2; // multiplier: 393400
84 int u = dr * 409 - y; // * 0.5 / (1 - 0.30)
85 int v = db * 409 - y; // * 0.5 / (1 - 0.11)
86 int sy = SHRR(y, 3) * SHRR(y, 4);
87 int su = SHRR(u, 3) * SHRR(u, 4);
88 int sv = SHRR(v, 3) * SHRR(v, 4);
89 return SHRR(sy, 4) + SHRR(su, 8) + SHRR(sv, 9);
90 // weight for u: sqrt(2^-4) / (0.5 / (1 - 0.30)) = 0.350
91 // weight for v: sqrt(2^-5) / (0.5 / (1 - 0.11)) = 0.315
94 inline int srgb_get_y(const color_t &a)
97 int r = a.r * (int) a.r;
98 int g = a.g * (int) a.g;
99 int b = a.b * (int) a.b;
101 int y = 37 * (r * 21*2*2 + g * 72 + b * 7*2*2); // multiplier: 14555800
102 // square root it (!)
103 y = sqrtf(y) + 0.5f; // now in range 0 to 3815
107 inline int color_dist_srgb_mixed(const color_t &a, const color_t &b)
110 int ay = srgb_get_y(a);
111 int by = srgb_get_y(b);
113 int au = a.r * 191 - ay;
114 int av = a.b * 191 - ay;
115 int bu = b.r * 191 - by;
116 int bv = b.b * 191 - by;
121 return ((y*y) << 3) + SHRR(u*u, 1) + SHRR(v*v, 2);
126 // FIXME this is likely broken
127 inline int color_dist_lab_srgb(const color_t &a, const color_t &b)
130 float ar = powf(a.r / 31.0f, 2.4f);
131 float ag = powf(a.g / 63.0f, 2.4f);
132 float ab = powf(a.b / 31.0f, 2.4f);
133 float br = powf(b.r / 31.0f, 2.4f);
134 float bg = powf(b.g / 63.0f, 2.4f);
135 float bb = powf(b.b / 31.0f, 2.4f);
136 // convert to CIE XYZ
137 float aX = 0.4124f * ar + 0.3576f * ag + 0.1805f * ab;
138 float aY = 0.2126f * ar + 0.7152f * ag + 0.0722f * ab;
139 float aZ = 0.0193f * ar + 0.1192f * ag + 0.9505f * ab;
140 float bX = 0.4124f * br + 0.3576f * bg + 0.1805f * bb;
141 float bY = 0.2126f * br + 0.7152f * bg + 0.0722f * bb;
142 float bZ = 0.0193f * br + 0.1192f * bg + 0.9505f * bb;
143 // convert to CIE Lab
147 float aL = 116 * cbrtf(aY / Yn) - 16;
148 float aA = 500 * (cbrtf(aX / Xn) - cbrtf(aY / Yn));
149 float aB = 200 * (cbrtf(aY / Yn) - cbrtf(aZ / Zn));
150 float bL = 116 * cbrtf(bY / Yn) - 16;
151 float bA = 500 * (cbrtf(bX / Xn) - cbrtf(bY / Yn));
152 float bB = 200 * (cbrtf(bY / Yn) - cbrtf(bZ / Zn));
153 // euclidean distance, but moving weight away from A and B
154 return 1000 * ((aL - bL) * (aL - bL) + (aA - bA) * (aA - bA) + (aB - bB) * (aB - bB));
157 inline int color_dist_normalmap(const color_t &a, const color_t &b)
159 float ca[3], cb[3], n;
160 ca[0] = a.r / 31.0f * 2 - 1;
161 ca[1] = a.g / 63.0f * 2 - 1;
162 ca[2] = a.b / 31.0f * 2 - 1;
163 cb[0] = b.r / 31.0f * 2 - 1;
164 cb[1] = b.g / 63.0f * 2 - 1;
165 cb[2] = b.b / 31.0f * 2 - 1;
166 n = ca[0] * ca[0] + ca[1] * ca[1] + ca[2] * ca[2];
174 n = cb[0] * cb[0] + cb[1] * cb[1] + cb[2] * cb[2];
186 (cb[0] - ca[0]) * (cb[0] - ca[0])
188 (cb[1] - ca[1]) * (cb[1] - ca[1])
190 (cb[2] - ca[2]) * (cb[2] - ca[2])
193 // max value: 1000 * (4 + 4 + 4) = 6000
196 typedef int ColorDistFunc(const color_t &a, const color_t &b);
198 inline int alpha_dist(unsigned char a, unsigned char b)
200 return (a - (int) b) * (a - (int) b);
203 template <class T, class F>
205 // m: total color count (including non-counted inputs)
207 inline void reduce_colors_inplace(T *c, int n, int m, F dist)
215 for(i = 0; i < n; ++i)
218 for(j = i+1; j < n; ++j)
220 int d = dist(c[i], c[j]);
221 dists[i][j] = dists[j][i] = d;
227 for(j = 0; j < n; ++j)
229 int d = dist(c[i], c[j]);
233 for(i = 0; i < m; ++i)
234 for(j = i+1; j < m; ++j)
237 for(k = 0; k < n; ++k)
239 int di = dists[i][k];
240 int dj = dists[j][k];
244 if(bestsum < 0 || sum < bestsum)
256 template <class T, class F>
257 inline void reduce_colors_inplace_2fixpoints(T *c, int n, int m, F dist, const T &fix0, const T &fix1)
265 for(i = 0; i < n; ++i)
268 for(j = i+1; j < n; ++j)
270 int d = dist(c[i], c[j]);
271 dists[i][j] = dists[j][i] = d;
277 for(j = 0; j < n; ++j)
279 int d = dist(c[i], c[j]);
283 // then the two extra rows
284 for(j = 0; j < n; ++j)
286 int d = dist(fix0, c[j]);
289 for(j = 0; j < n; ++j)
291 int d = dist(fix1, c[j]);
294 for(i = 0; i < m; ++i)
295 for(j = i+1; j < m; ++j)
298 for(k = 0; k < n; ++k)
300 int di = dists[i][k];
301 int dj = dists[j][k];
302 int d0 = dists[m][k];
303 int d1 = dists[m+1][k];
304 int m = min(min(di, dj), min(d0, d1));
307 if(bestsum < 0 || sum < bestsum)
327 template<ColorDistFunc ColorDist> inline int refine_component_encode(int comp)
331 template<> inline int refine_component_encode<color_dist_srgb>(int comp)
335 template<> inline int refine_component_encode<color_dist_srgb_mixed>(int comp)
339 template<> inline int refine_component_encode<color_dist_lab_srgb>(int comp)
344 template<ColorDistFunc ColorDist> inline int refine_component_decode(int comp)
348 template<> inline int refine_component_decode<color_dist_srgb>(int comp)
350 return sqrtf(comp) + 0.5f;
352 template<> inline int refine_component_decode<color_dist_srgb_mixed>(int comp)
354 return sqrtf(comp) + 0.5f;
356 template<> inline int refine_component_decode<color_dist_lab_srgb>(int comp)
358 return sqrtf(comp) + 0.5f;
361 // these color dist functions ignore color values at alpha 0
362 template<ColorDistFunc ColorDist> struct alpha_0_is_unimportant
364 static bool const value = true;
366 template<> struct alpha_0_is_unimportant<color_dist_normalmap>
368 static bool const value = false;
371 template<DxtMode dxt, ColorDistFunc ColorDist, CompressionMode mode, RefinementMode refine>
372 inline void s2tc_encode_block(unsigned char *out, const unsigned char *rgba, int iw, int w, int h, int nrandom)
374 color_t c[16 + (mode == MODE_RANDOM ? nrandom : 0)];
375 unsigned char ca[16 + (mode == MODE_RANDOM ? nrandom : 0)];
379 if(mode == MODE_FAST)
381 // FAST: trick from libtxc_dxtn: just get brightest and darkest colors, and encode using these
383 color_t c0 = {0, 0, 0};
385 // dummy values because we don't know whether the first pixel willw rite
392 int dmin = 0x7FFFFFFF;
400 for(x = 0; x < w; ++x)
401 for(y = 0; y < h; ++y)
403 c[2].r = rgba[(x + y * iw) * 4 + 2];
404 c[2].g = rgba[(x + y * iw) * 4 + 1];
405 c[2].b = rgba[(x + y * iw) * 4 + 0];
406 ca[2] = rgba[(x + y * iw) * 4 + 3];
407 // MODE_FAST doesn't work for normalmaps, so this works
411 int d = ColorDist(c[2], c0);
435 // if ALL pixels were transparent, this won't stop us
441 for(x = 0; x < w; ++x)
442 for(y = 0; y < h; ++y)
444 ca[n] = rgba[(x + y * iw) * 4 + 3];
445 if(alpha_0_is_unimportant<ColorDist>::value)
448 c[n].r = rgba[(x + y * iw) * 4 + 2];
449 c[n].g = rgba[(x + y * iw) * 4 + 1];
450 c[n].b = rgba[(x + y * iw) * 4 + 0];
463 if(mode == MODE_RANDOM)
467 unsigned char mina = (dxt == DXT5) ? ca[0] : 0;
468 unsigned char maxa = (dxt == DXT5) ? ca[0] : 0;
469 for(x = 1; x < n; ++x)
471 mins.r = min(mins.r, c[x].r);
472 mins.g = min(mins.g, c[x].g);
473 mins.b = min(mins.b, c[x].b);
474 maxs.r = max(maxs.r, c[x].r);
475 maxs.g = max(maxs.g, c[x].g);
476 maxs.b = max(maxs.b, c[x].b);
479 mina = min(mina, ca[x]);
480 maxa = max(maxa, ca[x]);
483 color_t len = { maxs.r - mins.r + 1, maxs.g - mins.g + 1, maxs.b - mins.b + 1 };
484 int lena = (dxt == DXT5) ? (maxa - (int) mina + 1) : 0;
485 for(x = 0; x < nrandom; ++x)
487 c[m].r = mins.r + rand() % len.r;
488 c[m].g = mins.g + rand() % len.g;
489 c[m].b = mins.b + rand() % len.b;
491 ca[m] = mina + rand() % lena;
497 // hack for last miplevel
505 reduce_colors_inplace(c, n, m, ColorDist);
507 reduce_colors_inplace_2fixpoints(ca, n, m, alpha_dist, (unsigned char) 0, (unsigned char) 255);
510 if(refine == REFINE_NEVER)
516 // select mode with 6 = 0, 7 = 255
522 if((dxt == DXT1) ? (c[1] < c[0]) : (c[0] < c[1]))
523 // DXT1: select mode with 3 = transparent
524 // other: don't select this mode
535 int nc0 = 0, na0 = 0, sc0r = 0, sc0g = 0, sc0b = 0, sa0 = 0;
536 int nc1 = 0, na1 = 0, sc1r = 0, sc1g = 0, sc1b = 0, sa1 = 0;
537 if(refine == REFINE_LOOP)
540 memset(out, 0, (dxt == DXT1) ? 8 : 16);
541 for(x = 0; x < w; ++x)
542 for(y = 0; y < h; ++y)
544 int pindex = (x+y*4);
545 c[2].r = rgba[(x + y * iw) * 4 + 2];
546 c[2].g = rgba[(x + y * iw) * 4 + 1];
547 c[2].b = rgba[(x + y * iw) * 4 + 0];
548 ca[2] = rgba[(x + y * iw) * 4 + 3];
555 int bitindex = pindex * 3;
556 da[0] = alpha_dist(ca[0], ca[2]);
557 da[1] = alpha_dist(ca[1], ca[2]);
558 da[2] = alpha_dist(0, ca[2]);
559 da[3] = alpha_dist(255, ca[2]);
560 if(da[2] <= da[0] && da[2] <= da[1] && da[2] <= da[3])
564 setbit(&out[2], bitindex);
566 setbit(&out[2], bitindex);
567 if(alpha_0_is_unimportant<ColorDist>::value)
570 else if(da[3] <= da[0] && da[3] <= da[1])
573 setbit(&out[2], bitindex);
575 setbit(&out[2], bitindex);
577 setbit(&out[2], bitindex);
579 else if(da[0] <= da[1])
582 if(refine != REFINE_NEVER)
591 setbit(&out[2], bitindex);
592 if(refine != REFINE_NEVER)
598 if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
600 int bitindex = pindex * 2;
601 setbit(&out[12], bitindex);
602 if(refine != REFINE_NEVER)
604 if(!alpha_0_is_unimportant<ColorDist>::value || visible)
607 sc1r += refine_component_encode<ColorDist>(c[2].r);
608 sc1g += refine_component_encode<ColorDist>(c[2].g);
609 sc1b += refine_component_encode<ColorDist>(c[2].b);
615 if(refine != REFINE_NEVER)
617 if(!alpha_0_is_unimportant<ColorDist>::value || visible)
620 sc0r += refine_component_encode<ColorDist>(c[2].r);
621 sc0g += refine_component_encode<ColorDist>(c[2].g);
622 sc0b += refine_component_encode<ColorDist>(c[2].b);
630 int bitindex = pindex * 4;
631 setbit(&out[0], bitindex, ca[2]);
633 if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
635 int bitindex = pindex * 2;
636 setbit(&out[12], bitindex);
637 if(refine != REFINE_NEVER)
639 if(!alpha_0_is_unimportant<ColorDist>::value || ca[2])
642 sc1r += refine_component_encode<ColorDist>(c[2].r);
643 sc1g += refine_component_encode<ColorDist>(c[2].g);
644 sc1b += refine_component_encode<ColorDist>(c[2].b);
650 if(refine != REFINE_NEVER)
652 if(!alpha_0_is_unimportant<ColorDist>::value || ca[2])
655 sc0r += refine_component_encode<ColorDist>(c[2].r);
656 sc0g += refine_component_encode<ColorDist>(c[2].g);
657 sc0b += refine_component_encode<ColorDist>(c[2].b);
664 // the normalmap-uses-alpha-0 hack cannot be used here
665 int bitindex = pindex * 2;
667 setbit(&out[4], bitindex, 3);
668 else if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
670 setbit(&out[4], bitindex);
671 if(refine != REFINE_NEVER)
674 sc1r += refine_component_encode<ColorDist>(c[2].r);
675 sc1g += refine_component_encode<ColorDist>(c[2].g);
676 sc1b += refine_component_encode<ColorDist>(c[2].b);
681 if(refine != REFINE_NEVER)
684 sc0r += refine_component_encode<ColorDist>(c[2].r);
685 sc0g += refine_component_encode<ColorDist>(c[2].g);
686 sc0b += refine_component_encode<ColorDist>(c[2].b);
693 if(refine != REFINE_NEVER)
695 // REFINEMENT: trick from libtxc_dxtn: reassign the colors to an average of the colors encoded with that value
700 ca[0] = (2 * sa0 + na0) / (2 * na0);
702 ca[1] = (2 * sa1 + na1) / (2 * na1);
704 if(refine == REFINE_CHECK || refine == REFINE_LOOP)
711 c[0].r = refine_component_decode<ColorDist>((2 * sc0r + nc0) / (2 * nc0));
712 c[0].g = refine_component_decode<ColorDist>((2 * sc0g + nc0) / (2 * nc0));
713 c[0].b = refine_component_decode<ColorDist>((2 * sc0b + nc0) / (2 * nc0));
717 c[1].r = refine_component_decode<ColorDist>((2 * sc1r + nc1) / (2 * nc1));
718 c[1].g = refine_component_decode<ColorDist>((2 * sc1g + nc1) / (2 * nc1));
719 c[1].b = refine_component_decode<ColorDist>((2 * sc1b + nc1) / (2 * nc1));
722 if(refine == REFINE_CHECK || refine == REFINE_LOOP)
726 for(x = 0; x < w; ++x)
727 for(y = 0; y < h; ++y)
729 int pindex = (x+y*4);
730 c[4].r = rgba[(x + y * iw) * 4 + 2];
731 c[4].g = rgba[(x + y * iw) * 4 + 1];
732 c[4].b = rgba[(x + y * iw) * 4 + 0];
733 if(!alpha_0_is_unimportant<ColorDist>::value)
737 // check ENCODED alpha
738 int bitindex_0 = pindex * 3;
739 int bitindex_1 = bitindex_0 + 2;
740 if(!testbit(&out[2], bitindex_0))
741 if(testbit(&out[2], bitindex_1))
746 // check ORIGINAL alpha (DXT1 and DXT3 preserve it)
747 ca[4] = rgba[(x + y * iw) * 4 + 3];
752 int bitindex = pindex * 2;
753 if(refine == REFINE_CHECK)
755 if(testbit(&out[(dxt == DXT1 ? 4 : 12)], bitindex))
758 score_01 += ColorDist(c[1], c[4]);
759 score_23 += ColorDist(c[3], c[4]);
764 score_01 += ColorDist(c[0], c[4]);
765 score_23 += ColorDist(c[2], c[4]);
768 else if(refine == REFINE_LOOP)
770 if(testbit(&out[(dxt == DXT1 ? 4 : 12)], bitindex))
773 score_23 += ColorDist(c[3], c[4]);
778 score_23 += ColorDist(c[2], c[4]);
780 // we WILL run another loop iteration, if score_01 wins
781 score_01 += min(ColorDist(c[0], c[4]), ColorDist(c[1], c[4]));
785 if(score_23 <= score_01)
787 // refinement was BAD
791 else if(refine == REFINE_LOOP)
794 // alpha refinement is always good and doesn't
795 // need to be checked because alpha is linear
797 // when looping, though, checking the
798 // alpha COULD help, but we usually
799 // loop twice anyway as refinement
804 while(refine == REFINE_LOOP && refined);
806 if(refine != REFINE_NEVER)
816 for(int pindex = 0; pindex < 16; ++pindex)
818 int bitindex_set = pindex * 3;
819 int bitindex_test = bitindex_set + 2;
820 if(!testbit(&out[2], bitindex_test))
821 xorbit(&out[2], bitindex_set);
825 if((dxt == DXT1) ? (c[1] < c[0]) : (c[0] < c[1]))
826 // DXT1: select mode with 3 = transparent
827 // other: don't select this mode
835 out[4] ^= 0x55 & ~(out[4] >> 1);
836 out[5] ^= 0x55 & ~(out[5] >> 1);
837 out[6] ^= 0x55 & ~(out[6] >> 1);
838 out[7] ^= 0x55 & ~(out[7] >> 1);
842 out[12] ^= 0x55 & ~(out[12] >> 1);
843 out[13] ^= 0x55 & ~(out[13] >> 1);
844 out[14] ^= 0x55 & ~(out[14] >> 1);
845 out[15] ^= 0x55 & ~(out[15] >> 1);
856 out[8] = ((c[0].g & 0x07) << 5) | c[0].b;
857 out[9] = (c[0].r << 3) | (c[0].g >> 3);
858 out[10] = ((c[1].g & 0x07) << 5) | c[1].b;
859 out[11] = (c[1].r << 3) | (c[1].g >> 3);
862 out[0] = ((c[0].g & 0x07) << 5) | c[0].b;
863 out[1] = (c[0].r << 3) | (c[0].g >> 3);
864 out[2] = ((c[1].g & 0x07) << 5) | c[1].b;
865 out[3] = (c[1].r << 3) | (c[1].g >> 3);
870 // these color dist functions do not need the refinement check, as they always improve the situation
871 template<ColorDistFunc ColorDist> struct need_refine_check
873 static const bool value = true;
875 template<> struct need_refine_check<color_dist_avg>
877 static const bool value = false;
879 template<> struct need_refine_check<color_dist_wavg>
881 static const bool value = false;
884 // compile time dispatch magic
885 template<DxtMode dxt, ColorDistFunc ColorDist, CompressionMode mode>
886 inline s2tc_encode_block_func_t s2tc_encode_block_func(RefinementMode refine)
891 return s2tc_encode_block<dxt, ColorDist, mode, REFINE_NEVER>;
893 return s2tc_encode_block<dxt, ColorDist, mode, REFINE_LOOP>;
895 if(need_refine_check<ColorDist>::value)
896 return s2tc_encode_block<dxt, ColorDist, mode, REFINE_CHECK>;
899 return s2tc_encode_block<dxt, ColorDist, mode, REFINE_ALWAYS>;
903 // these color dist functions do not need the refinement check, as they always improve the situation
904 template<ColorDistFunc ColorDist> struct supports_fast
906 static const bool value = true;
908 template<> struct need_refine_check<color_dist_normalmap>
910 static const bool value = false;
913 template<DxtMode dxt, ColorDistFunc ColorDist>
914 inline s2tc_encode_block_func_t s2tc_encode_block_func(int nrandom, RefinementMode refine)
917 return s2tc_encode_block_func<dxt, ColorDist, MODE_RANDOM>(refine);
918 else if(!supports_fast<ColorDist>::value || nrandom == 0) // MODE_FAST not supported for normalmaps, sorry
919 return s2tc_encode_block_func<dxt, ColorDist, MODE_NORMAL>(refine);
921 return s2tc_encode_block_func<dxt, ColorDist, MODE_FAST>(refine);
924 template<ColorDistFunc ColorDist>
925 inline s2tc_encode_block_func_t s2tc_encode_block_func(DxtMode dxt, int nrandom, RefinementMode refine)
930 return s2tc_encode_block_func<DXT1, ColorDist>(nrandom, refine);
933 return s2tc_encode_block_func<DXT3, ColorDist>(nrandom, refine);
937 return s2tc_encode_block_func<DXT5, ColorDist>(nrandom, refine);
943 s2tc_encode_block_func_t s2tc_encode_block_func(DxtMode dxt, ColorDistMode cd, int nrandom, RefinementMode refine)
948 return s2tc_encode_block_func<color_dist_rgb>(dxt, nrandom, refine);
951 return s2tc_encode_block_func<color_dist_yuv>(dxt, nrandom, refine);
954 return s2tc_encode_block_func<color_dist_srgb>(dxt, nrandom, refine);
957 return s2tc_encode_block_func<color_dist_srgb_mixed>(dxt, nrandom, refine);
960 return s2tc_encode_block_func<color_dist_lab_srgb>(dxt, nrandom, refine);
963 return s2tc_encode_block_func<color_dist_avg>(dxt, nrandom, refine);
967 return s2tc_encode_block_func<color_dist_wavg>(dxt, nrandom, refine);
970 return s2tc_encode_block_func<color_dist_normalmap>(dxt, nrandom, refine);
977 inline int diffuse(int *diff, int src, int shift)
979 int maxval = (1 << (8 - shift)) - 1;
981 int ret = max(0, min(src >> shift, maxval));
982 // simulate decoding ("loop filter")
983 int loop = (ret << shift) | (ret >> (8 - 2 * shift));
987 inline int diffuse1(int *diff, int src)
990 int ret = (src >= 128);
991 int loop = ret ? 255 : 0;
997 void rgb565_image(unsigned char *out, const unsigned char *rgba, int w, int h, int srccomps, int bgr, int alphabits)
1006 for(y = 0; y < h; ++y)
1007 for(x = 0; x < w; ++x)
1009 out[(x + y * w) * 4 + 2] = diffuse(&diffuse_r, rgba[(x + y * w) * srccomps + 2], 3);
1010 out[(x + y * w) * 4 + 1] = diffuse(&diffuse_g, rgba[(x + y * w) * srccomps + 1], 2);
1011 out[(x + y * w) * 4 + 0] = diffuse(&diffuse_b, rgba[(x + y * w) * srccomps + 0], 3);
1016 for(y = 0; y < h; ++y)
1017 for(x = 0; x < w; ++x)
1019 out[(x + y * w) * 4 + 2] = diffuse(&diffuse_r, rgba[(x + y * w) * srccomps + 0], 3);
1020 out[(x + y * w) * 4 + 1] = diffuse(&diffuse_g, rgba[(x + y * w) * srccomps + 1], 2);
1021 out[(x + y * w) * 4 + 0] = diffuse(&diffuse_b, rgba[(x + y * w) * srccomps + 2], 3);
1028 for(y = 0; y < h; ++y)
1029 for(x = 0; x < w; ++x)
1030 out[(x + y * w) * 4 + 3] = diffuse1(&diffuse_a, rgba[(x + y * w) * srccomps + 3]);
1032 else if(alphabits == 8)
1034 for(y = 0; y < h; ++y)
1035 for(x = 0; x < w; ++x)
1036 out[(x + y * w) * 4 + 3] = rgba[(x + y * w) * srccomps + 3]; // no conversion
1040 int alphadiffuse = 8 - alphabits;
1041 for(y = 0; y < h; ++y)
1042 for(x = 0; x < w; ++x)
1043 out[(x + y * w) * 4 + 3] = diffuse(&diffuse_a, rgba[(x + y * w) * srccomps + 3], alphadiffuse);
1048 int alpharange = (1 << alphabits) - 1;
1049 for(y = 0; y < h; ++y)
1050 for(x = 0; x < w; ++x)
1051 out[(x + y * w) * 4 + 3] = alpharange;