2 * Copyright (C) 2011 Rudolf Polzer All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * RUDOLF POLZER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 #define S2TC_LICENSE_IDENTIFIER s2tc_algorithm_license
22 #include "s2tc_license.h"
32 #include "s2tc_algorithm.h"
33 #include "s2tc_common.h"
41 inline color_t(): r(0), g(0), b(0)
45 inline color_t(signed char r_, signed char g_, signed char b_): r(r_), g(g_), b(b_)
49 inline color_t(int i): r(i >> 3), g(i >> 2), b(i >> 3)
53 inline bool operator<(const color_t &c)
71 inline bigcolor_t(): r(0), g(0), b(0)
75 inline bigcolor_t &operator+=(const color_t &c)
83 inline bigcolor_t &operator+=(int v)
91 inline bigcolor_t operator+(int v)
93 bigcolor_t out = *this;
98 inline bigcolor_t &operator/=(int v)
106 inline bigcolor_t operator/(int v)
108 bigcolor_t out = *this;
113 inline bigcolor_t &operator<<=(int v)
121 inline bigcolor_t operator<<(int v)
123 bigcolor_t out = *this;
128 inline operator color_t()
138 std::ostream &operator<<(std::ostream &ost, const color_t &c)
140 return ost << "color_t(" << int(c.r) << ", " << int(c.g) << ", " << int(c.b) << ")";
143 std::ostream &operator<<(std::ostream &ost, const bigcolor_t &c)
145 return ost << "bigcolor_t(" << c.r << ", " << c.g << ", " << c.b << ")";
148 // 16 differences must fit in int
149 // i.e. a difference must be lower than 2^27
151 // shift right, rounded
152 #define SHRR(a,n) (((a) + (1 << ((n)-1))) >> (n))
154 inline int color_dist_avg(const color_t &a, const color_t &b)
156 int dr = a.r - b.r; // multiplier: 31 (-1..1)
157 int dg = a.g - b.g; // multiplier: 63 (-1..1)
158 int db = a.b - b.b; // multiplier: 31 (-1..1)
159 return ((dr*dr) << 2) + dg*dg + ((db*db) << 2);
162 inline int color_dist_wavg(const color_t &a, const color_t &b)
164 int dr = a.r - b.r; // multiplier: 31 (-1..1)
165 int dg = a.g - b.g; // multiplier: 63 (-1..1)
166 int db = a.b - b.b; // multiplier: 31 (-1..1)
167 return ((dr*dr) << 2) + ((dg*dg) << 2) + (db*db);
171 inline int color_dist_yuv(const color_t &a, const color_t &b)
173 int dr = a.r - b.r; // multiplier: 31 (-1..1)
174 int dg = a.g - b.g; // multiplier: 63 (-1..1)
175 int db = a.b - b.b; // multiplier: 31 (-1..1)
176 int y = dr * 30*2 + dg * 59 + db * 11*2; // multiplier: 6259
177 int u = dr * 202 - y; // * 0.5 / (1 - 0.30)
178 int v = db * 202 - y; // * 0.5 / (1 - 0.11)
179 return ((y*y) << 1) + SHRR(u*u, 3) + SHRR(v*v, 4);
180 // weight for u: sqrt(2^-4) / (0.5 / (1 - 0.30)) = 0.350
181 // weight for v: sqrt(2^-5) / (0.5 / (1 - 0.11)) = 0.315
184 inline int color_dist_rgb(const color_t &a, const color_t &b)
186 int dr = a.r - b.r; // multiplier: 31 (-1..1)
187 int dg = a.g - b.g; // multiplier: 63 (-1..1)
188 int db = a.b - b.b; // multiplier: 31 (-1..1)
189 int y = dr * 21*2 + dg * 72 + db * 7*2; // multiplier: 6272
190 int u = dr * 202 - y; // * 0.5 / (1 - 0.21)
191 int v = db * 202 - y; // * 0.5 / (1 - 0.07)
192 return ((y*y) << 1) + SHRR(u*u, 3) + SHRR(v*v, 4);
193 // weight for u: sqrt(2^-4) / (0.5 / (1 - 0.21)) = 0.395
194 // weight for v: sqrt(2^-5) / (0.5 / (1 - 0.07)) = 0.328
197 inline int color_dist_srgb(const color_t &a, const color_t &b)
199 int dr = a.r * (int) a.r - b.r * (int) b.r; // multiplier: 31*31
200 int dg = a.g * (int) a.g - b.g * (int) b.g; // multiplier: 63*63
201 int db = a.b * (int) a.b - b.b * (int) b.b; // multiplier: 31*31
202 int y = dr * 21*2*2 + dg * 72 + db * 7*2*2; // multiplier: 393400
203 int u = dr * 409 - y; // * 0.5 / (1 - 0.30)
204 int v = db * 409 - y; // * 0.5 / (1 - 0.11)
205 int sy = SHRR(y, 3) * SHRR(y, 4);
206 int su = SHRR(u, 3) * SHRR(u, 4);
207 int sv = SHRR(v, 3) * SHRR(v, 4);
208 return SHRR(sy, 4) + SHRR(su, 8) + SHRR(sv, 9);
209 // weight for u: sqrt(2^-4) / (0.5 / (1 - 0.30)) = 0.350
210 // weight for v: sqrt(2^-5) / (0.5 / (1 - 0.11)) = 0.315
213 inline int srgb_get_y(const color_t &a)
216 int r = a.r * (int) a.r;
217 int g = a.g * (int) a.g;
218 int b = a.b * (int) a.b;
220 int y = 37 * (r * 21*2*2 + g * 72 + b * 7*2*2); // multiplier: 14555800
221 // square root it (!)
222 y = sqrtf(y) + 0.5f; // now in range 0 to 3815
226 inline int color_dist_srgb_mixed(const color_t &a, const color_t &b)
229 int ay = srgb_get_y(a);
230 int by = srgb_get_y(b);
232 int au = a.r * 191 - ay;
233 int av = a.b * 191 - ay;
234 int bu = b.r * 191 - by;
235 int bv = b.b * 191 - by;
240 return ((y*y) << 3) + SHRR(u*u, 1) + SHRR(v*v, 2);
245 inline int color_dist_normalmap(const color_t &a, const color_t &b)
247 float ca[3], cb[3], n;
248 ca[0] = a.r / 31.0f * 2 - 1;
249 ca[1] = a.g / 63.0f * 2 - 1;
250 ca[2] = a.b / 31.0f * 2 - 1;
251 cb[0] = b.r / 31.0f * 2 - 1;
252 cb[1] = b.g / 63.0f * 2 - 1;
253 cb[2] = b.b / 31.0f * 2 - 1;
254 n = ca[0] * ca[0] + ca[1] * ca[1] + ca[2] * ca[2];
262 n = cb[0] * cb[0] + cb[1] * cb[1] + cb[2] * cb[2];
274 (cb[0] - ca[0]) * (cb[0] - ca[0])
276 (cb[1] - ca[1]) * (cb[1] - ca[1])
278 (cb[2] - ca[2]) * (cb[2] - ca[2])
281 // max value: 1000 * (4 + 4 + 4) = 6000
284 typedef int ColorDistFunc(const color_t &a, const color_t &b);
286 inline int alpha_dist(unsigned char a, unsigned char b)
288 return (a - (int) b) * (a - (int) b);
291 template <class T, class F>
293 // m: total color count (including non-counted inputs)
295 inline void reduce_colors_inplace(T *c, int n, int m, F dist)
303 for(i = 0; i < n; ++i)
306 for(j = i+1; j < n; ++j)
308 int d = dist(c[i], c[j]);
309 dists[i][j] = dists[j][i] = d;
315 for(j = 0; j < n; ++j)
317 int d = dist(c[i], c[j]);
321 for(i = 0; i < m; ++i)
322 for(j = i+1; j < m; ++j)
325 for(k = 0; k < n; ++k)
327 int di = dists[i][k];
328 int dj = dists[j][k];
332 if(bestsum < 0 || sum < bestsum)
344 template <class T, class F>
345 inline void reduce_colors_inplace_2fixpoints(T *c, int n, int m, F dist, const T &fix0, const T &fix1)
347 // TODO fix this for ramp encoding!
354 for(i = 0; i < n; ++i)
357 for(j = i+1; j < n; ++j)
359 int d = dist(c[i], c[j]);
360 dists[i][j] = dists[j][i] = d;
366 for(j = 0; j < n; ++j)
368 int d = dist(c[i], c[j]);
372 // then the two extra rows
373 for(j = 0; j < n; ++j)
375 int d = dist(fix0, c[j]);
378 for(j = 0; j < n; ++j)
380 int d = dist(fix1, c[j]);
383 for(i = 0; i < m; ++i)
384 for(j = i+1; j < m; ++j)
387 for(k = 0; k < n; ++k)
389 int di = dists[i][k];
390 int dj = dists[j][k];
391 int d0 = dists[m][k];
392 int d1 = dists[m+1][k];
393 int m = min(min(di, dj), min(d0, d1));
396 if(bestsum < 0 || sum < bestsum)
415 template<ColorDistFunc ColorDist> inline int refine_component_encode(int comp)
419 template<> inline int refine_component_encode<color_dist_srgb>(int comp)
423 template<> inline int refine_component_encode<color_dist_srgb_mixed>(int comp)
428 template<ColorDistFunc ColorDist> inline int refine_component_decode(int comp)
432 template<> inline int refine_component_decode<color_dist_srgb>(int comp)
434 return sqrtf(comp) + 0.5f;
436 template<> inline int refine_component_decode<color_dist_srgb_mixed>(int comp)
438 return sqrtf(comp) + 0.5f;
441 template <class T, class Big, int scale_l>
442 struct s2tc_evaluate_colors_result_t;
444 template <class T, class Big>
445 struct s2tc_evaluate_colors_result_t<T, Big, 1>
454 inline s2tc_evaluate_colors_result_t():
455 n0(), n1(), S0(), S1()
458 inline void add(int l, T a)
471 inline bool evaluate(T &a, T &b)
476 a = ((S0 << 1) + n0) / (n0 << 1);
478 b = ((S1 << 1) + n1) / (n1 << 1);
483 template <class T, class Big, int scale_l>
484 struct s2tc_evaluate_colors_result_t
486 // a possible implementation of inferred color/alpha values
487 // refining would go here
491 struct s2tc_evaluate_colors_result_null_t
493 inline void add(int l, T a)
498 template<class T> T get(const unsigned char *buf)
506 template<> unsigned char get<unsigned char>(const unsigned char *buf)
508 return buf[3]; // extract alpha
511 template<class T, class Big, int bpp, bool have_trans, bool have_0_255, int n_input, class Dist, class Eval, class Arr>
512 inline unsigned int s2tc_try_encode_block(
516 const unsigned char *in, int iw, int w, int h,
517 const T colors_ref[])
519 unsigned int score = 0;
520 for(int x = 0; x < w; ++x) for(int y = 0; y < h; ++y)
523 const unsigned char *pix = &in[(y * iw + x) * 4];
529 out.do_or(i, (1 << bpp) - 1);
534 T color(get<T>(pix));
536 int bestdist = ColorDist(color, colors_ref[0]);
537 for(int k = 1; k < n_input; ++k)
539 int dist = ColorDist(color, colors_ref[k]);
548 int dist_0 = ColorDist(color, 0);
549 if(dist_0 <= bestdist)
552 out.do_or(i, (1 << bpp) - 2);
556 int dist_255 = ColorDist(color, 255);
557 if(dist_255 <= bestdist)
560 out.do_or(i, (1 << bpp) - 1);
567 res.add(best, color);
574 // REFINE_LOOP: refine, take result over only if score improved, loop until it did not
575 inline void s2tc_dxt5_encode_alpha_refine_loop(bitarray<uint64_t, 16, 3> &out, const unsigned char *in, int iw, int w, int h, unsigned char &a0, unsigned char &a1)
577 bitarray<uint64_t, 16, 3> out2;
578 unsigned char a0next = a0, a1next = a1;
579 unsigned int s = 0x7FFFFFFF;
582 unsigned char ramp[2] = {
586 s2tc_evaluate_colors_result_t<unsigned char, int, 1> r2;
587 unsigned int s2 = s2tc_try_encode_block<unsigned char, int, 3, false, true, 2>(out2, r2, alpha_dist, in, iw, w, h, ramp);
594 if(!r2.evaluate(a0next, a1next))
604 for(int i = 0; i < 16; ++i) switch(out.get(i))
616 out.set(i, 7 - out.get(i));
622 // REFINE_ALWAYS: refine, do not check
623 inline void s2tc_dxt5_encode_alpha_refine_always(bitarray<uint64_t, 16, 3> &out, const unsigned char *in, int iw, int w, int h, unsigned char &a0, unsigned char &a1)
625 unsigned char ramp[2] = {
629 s2tc_evaluate_colors_result_t<unsigned char, int, 1> r2;
630 s2tc_try_encode_block<unsigned char, int, 3, false, true, 6>(out, r2, alpha_dist, in, iw, w, h, ramp);
636 for(int i = 0; i < 16; ++i) switch(out.get(i))
648 out.set(i, 7 - out.get(i));
654 // REFINE_NEVER: do not refine
655 inline void s2tc_dxt5_encode_alpha_refine_never(bitarray<uint64_t, 16, 3> &out, const unsigned char *in, int iw, int w, int h, unsigned char &a0, unsigned char &a1)
659 unsigned char ramp[6] = {
663 s2tc_evaluate_colors_result_null_t<unsigned char> r2;
664 s2tc_try_encode_block<unsigned char, int, 3, false, true, 6>(out, r2, alpha_dist, in, iw, w, h, ramp);
667 // REFINE_LOOP: refine, take result over only if score improved, loop until it did not
668 template<ColorDistFunc ColorDist, bool have_trans>
669 inline void s2tc_dxt1_encode_color_refine_loop(bitarray<uint32_t, 16, 2> &out, const unsigned char *in, int iw, int w, int h, color_t &c0, color_t &c1)
671 bitarray<uint32_t, 16, 2> out2;
672 color_t c0next = c0, c1next = c1;
673 unsigned int s = 0x7FFFFFFF;
680 s2tc_evaluate_colors_result_t<color_t, bigcolor_t, 1> r2;
681 unsigned int s2 = s2tc_try_encode_block<color_t, bigcolor_t, 2, have_trans, false, 2>(out2, r2, ColorDist, in, iw, w, h, ramp);
688 if(!r2.evaluate(c0next, c1next))
695 if(have_trans ? c1 < c0 : c0 < c1)
698 for(int i = 0; i < 16; ++i)
699 if(!(out.get(i) & 2))
704 // REFINE_ALWAYS: refine, do not check
705 template<ColorDistFunc ColorDist, bool have_trans>
706 inline void s2tc_dxt1_encode_color_refine_always(bitarray<uint32_t, 16, 2> &out, const unsigned char *in, int iw, int w, int h, color_t &c0, color_t &c1)
712 s2tc_evaluate_colors_result_t<color_t, bigcolor_t, 1> r2;
713 s2tc_try_encode_block<color_t, bigcolor_t, 2, have_trans, false, 2>(out, r2, ColorDist, in, iw, w, h, ramp);
715 if(have_trans ? c1 < c0 : c0 < c1)
718 for(int i = 0; i < 16; ++i)
719 if(!(out.get(i) & 2))
724 // REFINE_NEVER: do not refine
725 template<ColorDistFunc ColorDist, bool have_trans>
726 inline void s2tc_dxt1_encode_color_refine_never(bitarray<uint32_t, 16, 2> &out, const unsigned char *in, int iw, int w, int h, color_t &c0, color_t &c1)
728 if(have_trans ? c1 < c0 : c0 < c1)
734 s2tc_evaluate_colors_result_null_t<color_t> r2;
735 s2tc_try_encode_block<color_t, bigcolor_t, 2, have_trans, false, 2>(out, r2, ColorDist, in, iw, w, h, ramp);
738 inline void s2tc_dxt3_encode_alpha(bitarray<uint64_t, 16, 4> &out, const unsigned char *in, int iw, int w, int h)
740 for(int x = 0; x < w; ++x) for(int y = 0; y < h; ++y)
743 const unsigned char *pix = &in[(y * iw + x) * 4];
744 out.do_or(i, pix[3]);
748 template<DxtMode dxt, ColorDistFunc ColorDist, CompressionMode mode, RefinementMode refine>
749 inline void s2tc_encode_block(unsigned char *out, const unsigned char *rgba, int iw, int w, int h, int nrandom)
751 color_t c[16 + (nrandom >= 0 ? nrandom : 0)];
752 unsigned char ca[16 + (nrandom >= 0 ? nrandom : 0)];
756 if(mode == MODE_FAST)
758 // FAST: trick from libtxc_dxtn: just get brightest and darkest colors, and encode using these
762 // dummy values because we don't know whether the first pixel willw rite
769 int dmin = 0x7FFFFFFF;
777 for(x = 0; x < w; ++x)
778 for(y = 0; y < h; ++y)
780 c[2].r = rgba[(x + y * iw) * 4 + 0];
781 c[2].g = rgba[(x + y * iw) * 4 + 1];
782 c[2].b = rgba[(x + y * iw) * 4 + 2];
783 ca[2] = rgba[(x + y * iw) * 4 + 3];
784 // MODE_FAST doesn't work for normalmaps, so this works
788 int d = ColorDist(c[2], c0);
812 // if ALL pixels were transparent, this won't stop us
818 for(x = 0; x < w; ++x)
819 for(y = 0; y < h; ++y)
821 c[n].r = rgba[(x + y * iw) * 4 + 0];
822 c[n].g = rgba[(x + y * iw) * 4 + 1];
823 c[n].b = rgba[(x + y * iw) * 4 + 2];
824 ca[n] = rgba[(x + y * iw) * 4 + 3];
841 unsigned char mina = (dxt == DXT5) ? ca[0] : 0;
842 unsigned char maxa = (dxt == DXT5) ? ca[0] : 0;
843 for(x = 1; x < n; ++x)
845 mins.r = min(mins.r, c[x].r);
846 mins.g = min(mins.g, c[x].g);
847 mins.b = min(mins.b, c[x].b);
848 maxs.r = max(maxs.r, c[x].r);
849 maxs.g = max(maxs.g, c[x].g);
850 maxs.b = max(maxs.b, c[x].b);
853 mina = min(mina, ca[x]);
854 maxa = max(maxa, ca[x]);
857 color_t len(maxs.r - mins.r + 1, maxs.g - mins.g + 1, maxs.b - mins.b + 1);
858 int lena = (dxt == DXT5) ? (maxa - (int) mina + 1) : 0;
859 for(x = 0; x < nrandom; ++x)
861 c[m].r = mins.r + rand() % len.r;
862 c[m].g = mins.g + rand() % len.g;
863 c[m].b = mins.b + rand() % len.b;
865 ca[m] = mina + rand() % lena;
871 // hack for last miplevel
879 reduce_colors_inplace(c, n, m, ColorDist);
881 reduce_colors_inplace_2fixpoints(ca, n, m, alpha_dist, (unsigned char) 0, (unsigned char) 255);
888 bitarray<uint32_t, 16, 2> colorblock;
892 s2tc_dxt1_encode_color_refine_never<ColorDist, true>(colorblock, rgba, iw, w, h, c[0], c[1]);
895 s2tc_dxt1_encode_color_refine_always<ColorDist, true>(colorblock, rgba, iw, w, h, c[0], c[1]);
898 s2tc_dxt1_encode_color_refine_loop<ColorDist, true>(colorblock, rgba, iw, w, h, c[0], c[1]);
901 out[0] = ((c[0].g & 0x07) << 5) | c[0].b;
902 out[1] = (c[0].r << 3) | (c[0].g >> 3);
903 out[2] = ((c[1].g & 0x07) << 5) | c[1].b;
904 out[3] = (c[1].r << 3) | (c[1].g >> 3);
905 colorblock.tobytes(&out[4]);
910 bitarray<uint32_t, 16, 2> colorblock;
911 bitarray<uint64_t, 16, 4> alphablock;
915 s2tc_dxt1_encode_color_refine_never<ColorDist, false>(colorblock, rgba, iw, w, h, c[0], c[1]);
918 s2tc_dxt1_encode_color_refine_always<ColorDist, false>(colorblock, rgba, iw, w, h, c[0], c[1]);
921 s2tc_dxt1_encode_color_refine_loop<ColorDist, false>(colorblock, rgba, iw, w, h, c[0], c[1]);
924 s2tc_dxt3_encode_alpha(alphablock, rgba, iw, w, h);
925 alphablock.tobytes(&out[0]);
926 out[8] = ((c[0].g & 0x07) << 5) | c[0].b;
927 out[9] = (c[0].r << 3) | (c[0].g >> 3);
928 out[10] = ((c[1].g & 0x07) << 5) | c[1].b;
929 out[11] = (c[1].r << 3) | (c[1].g >> 3);
930 colorblock.tobytes(&out[12]);
935 bitarray<uint32_t, 16, 2> colorblock;
936 bitarray<uint64_t, 16, 3> alphablock;
940 s2tc_dxt1_encode_color_refine_never<ColorDist, false>(colorblock, rgba, iw, w, h, c[0], c[1]);
941 s2tc_dxt5_encode_alpha_refine_never(alphablock, rgba, iw, w, h, ca[0], ca[1]);
944 s2tc_dxt1_encode_color_refine_always<ColorDist, false>(colorblock, rgba, iw, w, h, c[0], c[1]);
945 s2tc_dxt5_encode_alpha_refine_always(alphablock, rgba, iw, w, h, ca[0], ca[1]);
948 s2tc_dxt1_encode_color_refine_loop<ColorDist, false>(colorblock, rgba, iw, w, h, c[0], c[1]);
949 s2tc_dxt5_encode_alpha_refine_loop(alphablock, rgba, iw, w, h, ca[0], ca[1]);
954 alphablock.tobytes(&out[2]);
955 out[8] = ((c[0].g & 0x07) << 5) | c[0].b;
956 out[9] = (c[0].r << 3) | (c[0].g >> 3);
957 out[10] = ((c[1].g & 0x07) << 5) | c[1].b;
958 out[11] = (c[1].r << 3) | (c[1].g >> 3);
959 colorblock.tobytes(&out[12]);
965 // compile time dispatch magic
966 template<DxtMode dxt, ColorDistFunc ColorDist, CompressionMode mode>
967 inline s2tc_encode_block_func_t s2tc_encode_block_func(RefinementMode refine)
972 return s2tc_encode_block<dxt, ColorDist, mode, REFINE_NEVER>;
974 return s2tc_encode_block<dxt, ColorDist, mode, REFINE_LOOP>;
977 return s2tc_encode_block<dxt, ColorDist, mode, REFINE_ALWAYS>;
981 // these color dist functions do not need the refinement check, as they always improve the situation
982 template<ColorDistFunc ColorDist> struct supports_fast
984 static const bool value = true;
986 template<> struct supports_fast<color_dist_normalmap>
988 static const bool value = false;
991 template<DxtMode dxt, ColorDistFunc ColorDist>
992 inline s2tc_encode_block_func_t s2tc_encode_block_func(int nrandom, RefinementMode refine)
994 if(!supports_fast<ColorDist>::value || nrandom >= 0)
995 return s2tc_encode_block_func<dxt, ColorDist, MODE_NORMAL>(refine);
997 return s2tc_encode_block_func<dxt, ColorDist, MODE_FAST>(refine);
1000 template<ColorDistFunc ColorDist>
1001 inline s2tc_encode_block_func_t s2tc_encode_block_func(DxtMode dxt, int nrandom, RefinementMode refine)
1006 return s2tc_encode_block_func<DXT1, ColorDist>(nrandom, refine);
1009 return s2tc_encode_block_func<DXT3, ColorDist>(nrandom, refine);
1013 return s2tc_encode_block_func<DXT5, ColorDist>(nrandom, refine);
1019 s2tc_encode_block_func_t s2tc_encode_block_func(DxtMode dxt, ColorDistMode cd, int nrandom, RefinementMode refine)
1024 return s2tc_encode_block_func<color_dist_rgb>(dxt, nrandom, refine);
1027 return s2tc_encode_block_func<color_dist_yuv>(dxt, nrandom, refine);
1030 return s2tc_encode_block_func<color_dist_srgb>(dxt, nrandom, refine);
1033 return s2tc_encode_block_func<color_dist_srgb_mixed>(dxt, nrandom, refine);
1036 return s2tc_encode_block_func<color_dist_avg>(dxt, nrandom, refine);
1040 return s2tc_encode_block_func<color_dist_wavg>(dxt, nrandom, refine);
1043 return s2tc_encode_block_func<color_dist_normalmap>(dxt, nrandom, refine);
1050 inline int diffuse(int *diff, int src, int shift)
1052 const int maxval = (1 << (8 - shift)) - 1;
1054 int ret = max(0, min(src >> shift, maxval));
1055 // simulate decoding ("loop filter")
1056 int loop = (ret << shift) | (ret >> (8 - 2 * shift));
1060 inline int diffuse1(int *diff, int src)
1063 int ret = (src >= 128);
1064 // simulate decoding ("loop filter")
1065 int loop = ret ? 255 : 0;
1070 inline int floyd(int *thisrow, int *downrow, int src, int shift)
1072 const int maxval = (1 << (8 - shift)) - 1;
1073 src = (src << 4) | (src >> 4);
1075 int ret = max(0, min(src >> (shift + 4), maxval));
1076 // simulate decoding ("loop filter")
1077 int loop = (ret * 4095 / maxval);
1078 int err = src - loop;
1079 int e7 = (err * 7 + 8) / 16;
1081 int e3 = (err * 3 + 4) / 9;
1083 int e5 = (err * 5 + 3) / 6;
1093 inline int floyd1(int *thisrow, int *downrow, int src)
1095 src = (src << 4) | (src >> 4);
1097 int ret = (src >= 2048);
1098 // simulate decoding ("loop filter")
1099 int loop = ret ? 4095 : 0;
1100 int err = src - loop;
1101 int e7 = (err * 7 + 8) / 16;
1103 int e3 = (err * 3 + 4) / 9;
1105 int e5 = (err * 5 + 3) / 6;
1115 template<int srccomps, int alphabits, DitherMode dither>
1116 inline void rgb565_image(unsigned char *out, const unsigned char *rgba, int w, int h)
1123 for(y = 0; y < h; ++y)
1124 for(x = 0; x < w; ++x)
1126 out[(x + y * w) * 4 + 0] = rgba[(x + y * w) * srccomps + 0] >> 3;
1127 out[(x + y * w) * 4 + 1] = rgba[(x + y * w) * srccomps + 1] >> 2;
1128 out[(x + y * w) * 4 + 2] = rgba[(x + y * w) * srccomps + 2] >> 3;
1134 for(y = 0; y < h; ++y)
1135 for(x = 0; x < w; ++x)
1136 out[(x + y * w) * 4 + 3] = rgba[(x + y * w) * srccomps + 3] >> 7;
1138 else if(alphabits == 8)
1140 for(y = 0; y < h; ++y)
1141 for(x = 0; x < w; ++x)
1142 out[(x + y * w) * 4 + 3] = rgba[(x + y * w) * srccomps + 3]; // no conversion
1146 int alphadiffuse = 8 - alphabits;
1147 for(y = 0; y < h; ++y)
1148 for(x = 0; x < w; ++x)
1149 out[(x + y * w) * 4 + 3] = rgba[(x + y * w) * srccomps + 3] >> (8 - alphabits);
1154 for(y = 0; y < h; ++y)
1155 for(x = 0; x < w; ++x)
1156 out[(x + y * w) * 4 + 3] = (1 << alphabits) - 1;
1167 for(y = 0; y < h; ++y)
1168 for(x = 0; x < w; ++x)
1170 out[(x + y * w) * 4 + 0] = diffuse(&diffuse_r, rgba[(x + y * w) * srccomps + 0], 3);
1171 out[(x + y * w) * 4 + 1] = diffuse(&diffuse_g, rgba[(x + y * w) * srccomps + 1], 2);
1172 out[(x + y * w) * 4 + 2] = diffuse(&diffuse_b, rgba[(x + y * w) * srccomps + 2], 3);
1178 for(y = 0; y < h; ++y)
1179 for(x = 0; x < w; ++x)
1180 out[(x + y * w) * 4 + 3] = diffuse1(&diffuse_a, rgba[(x + y * w) * srccomps + 3]);
1182 else if(alphabits == 8)
1184 for(y = 0; y < h; ++y)
1185 for(x = 0; x < w; ++x)
1186 out[(x + y * w) * 4 + 3] = rgba[(x + y * w) * srccomps + 3]; // no conversion
1190 for(y = 0; y < h; ++y)
1191 for(x = 0; x < w; ++x)
1192 out[(x + y * w) * 4 + 3] = diffuse(&diffuse_a, rgba[(x + y * w) * srccomps + 3], 8 - alphabits);
1197 for(y = 0; y < h; ++y)
1198 for(x = 0; x < w; ++x)
1199 out[(x + y * w) * 4 + 3] = (1 << alphabits) - 1;
1203 case DITHER_FLOYDSTEINBERG:
1208 memset(downrow, 0, sizeof(downrow));
1209 int *thisrow_r, *thisrow_g, *thisrow_b, *thisrow_a;
1210 int *downrow_r, *downrow_g, *downrow_b, *downrow_a;
1211 for(y = 0; y < h; ++y)
1213 thisrow_r = downrow + ((y&1)?3:0) * pw;
1214 downrow_r = downrow + ((y&1)?0:3) * pw;
1215 memset(downrow_r, 0, sizeof(*downrow_r) * (3*pw));
1216 thisrow_g = thisrow_r + pw;
1217 thisrow_b = thisrow_g + pw;
1218 downrow_g = downrow_r + pw;
1219 downrow_b = downrow_g + pw;
1220 for(x = 0; x < w; ++x)
1222 out[(x + y * w) * 4 + 0] = floyd(&thisrow_r[x], &downrow_r[x], rgba[(x + y * w) * srccomps + 0], 3);
1223 out[(x + y * w) * 4 + 1] = floyd(&thisrow_g[x], &downrow_g[x], rgba[(x + y * w) * srccomps + 1], 2);
1224 out[(x + y * w) * 4 + 2] = floyd(&thisrow_b[x], &downrow_b[x], rgba[(x + y * w) * srccomps + 2], 3);
1231 for(y = 0; y < h; ++y)
1233 thisrow_a = downrow + (y&1) * pw;
1234 downrow_a = downrow + !(y&1) * pw;
1235 memset(downrow_a, 0, sizeof(*downrow_a) * pw);
1236 for(x = 0; x < w; ++x)
1237 out[(x + y * w) * 4 + 3] = floyd1(&thisrow_a[x], &downrow_a[x], rgba[(x + y * w) * srccomps + 3]);
1240 else if(alphabits == 8)
1242 for(y = 0; y < h; ++y)
1243 for(x = 0; x < w; ++x)
1244 out[(x + y * w) * 4 + 3] = rgba[(x + y * w) * srccomps + 3]; // no conversion
1248 for(y = 0; y < h; ++y)
1250 thisrow_a = downrow + (y&1) * pw;
1251 downrow_a = downrow + !(y&1) * pw;
1252 memset(downrow_a, 0, sizeof(*downrow_a) * pw);
1253 for(x = 0; x < w; ++x)
1254 out[(x + y * w) * 4 + 3] = floyd(&thisrow_a[x], &downrow_a[x], rgba[(x + y * w) * srccomps + 3], 8 - alphabits);
1260 for(y = 0; y < h; ++y)
1261 for(x = 0; x < w; ++x)
1262 out[(x + y * w) * 4 + 3] = (1 << alphabits) - 1;
1269 template<int srccomps, int alphabits>
1270 inline void rgb565_image(unsigned char *out, const unsigned char *rgba, int w, int h, DitherMode dither)
1275 rgb565_image<srccomps, alphabits, DITHER_NONE>(out, rgba, w, h);
1279 rgb565_image<srccomps, alphabits, DITHER_SIMPLE>(out, rgba, w, h);
1281 case DITHER_FLOYDSTEINBERG:
1282 rgb565_image<srccomps, alphabits, DITHER_FLOYDSTEINBERG>(out, rgba, w, h);
1287 template<int srccomps>
1288 inline void rgb565_image(unsigned char *out, const unsigned char *rgba, int w, int h, int alphabits, DitherMode dither)
1293 rgb565_image<srccomps, 1>(out, rgba, w, h, dither);
1296 rgb565_image<srccomps, 4>(out, rgba, w, h, dither);
1300 rgb565_image<srccomps, 8>(out, rgba, w, h, dither);
1306 void rgb565_image(unsigned char *out, const unsigned char *rgba, int w, int h, int srccomps, int alphabits, DitherMode dither)
1311 rgb565_image<3>(out, rgba, w, h, alphabits, dither);
1314 rgb565_image<4>(out, rgba, w, h, alphabits, dither);