namespace
{
+ template<class T> struct color_type_info
+ {
+ };
+ template<> struct color_type_info<unsigned char>
+ {
+ static const unsigned char min_value = 0;
+ static const unsigned char max_value = 255;
+ };
+
struct color_t
{
signed char r, g, b;
-
- inline color_t(): r(0), g(0), b(0)
+ };
+ inline color_t make_color_t()
+ {
+ return (color_t) {0, 0, 0};
+ }
+ inline color_t make_color_t(signed char r_, signed char g_, signed char b_)
+ {
+ return (color_t) {r_, g_, b_};
+ }
+ inline color_t make_color_t(int i)
+ {
+ return (color_t) {i >> 3, i >> 2, i >> 3};
+ }
+ inline bool operator==(const color_t &a, const color_t &b)
+ {
+ return a.r == b.r && a.g == b.g && a.b == b.b;
+ }
+ inline bool operator<(const color_t &a, const color_t &b)
+ {
+ signed char d;
+ d = a.r - b.r;
+ if(d)
+ return d < 0;
+ d = a.g - b.g;
+ if(d)
+ return d < 0;
+ d = a.b - b.b;
+ return d < 0;
+ }
+ inline color_t &operator--(color_t &c)
+ {
+ if(c.b > 0)
{
+ --c.b;
}
-
- inline color_t(signed char r_, signed char g_, signed char b_): r(r_), g(g_), b(b_)
+ else if(c.g > 0)
{
+ c.b = 31;
+ --c.g;
}
-
- inline color_t(int i): r(i >> 3), g(i >> 2), b(i >> 3)
+ else if(c.r > 0)
{
+ c.b = 31;
+ c.g = 63;
+ --c.r;
}
-
- inline bool operator<(const color_t &c)
+ else
{
- signed char d;
- d = r - c.r;
- if(d)
- return d < 0;
- d = g - c.g;
- if(d)
- return d < 0;
- d = b - c.b;
- return d < 0;
+ c.b = 31;
+ c.g = 63;
+ c.r = 31;
+ }
+ return c;
+ }
+ inline color_t &operator++(color_t &c)
+ {
+ if(c.b < 31)
+ {
+ ++c.b;
+ }
+ else if(c.g < 63)
+ {
+ c.b = 0;
+ ++c.g;
+ }
+ else if(c.r < 31)
+ {
+ c.b = 0;
+ c.g = 0;
+ ++c.r;
}
+ else
+ {
+ c.b = 0;
+ c.g = 0;
+ c.r = 0;
+ }
+ return c;
+ }
+ template<> struct color_type_info<color_t>
+ {
+ static const color_t min_value;
+ static const color_t max_value;
};
+ const color_t color_type_info<color_t>::min_value = { 0, 0, 0 };
+ const color_t color_type_info<color_t>::max_value = { 31, 63, 31 };
struct bigcolor_t
{
std::ostream &operator<<(std::ostream &ost, const color_t &c)
{
- return ost << "color_t(" << int(c.r) << ", " << int(c.g) << ", " << int(c.b) << ")";
+ return ost << "make_color_t(" << int(c.r) << ", " << int(c.g) << ", " << int(c.b) << ")";
}
std::ostream &operator<<(std::ostream &ost, const bigcolor_t &c)
}
if(have_0_255)
{
- int dist_0 = ColorDist(color, 0);
+ int dist_0 = ColorDist(color, color_type_info<T>::min_value);
if(dist_0 <= bestdist)
{
bestdist = dist_0;
score += bestdist;
continue;
}
- int dist_255 = ColorDist(color, 255);
+ int dist_255 = ColorDist(color, color_type_info<T>::max_value);
if(dist_255 <= bestdist)
{
bestdist = dist_255;
break;
out2.clear();
}
+
+ if(a1 == a0)
+ {
+ if(a0 == 255)
+ --a1;
+ else
+ ++a1;
+ for(int i = 0; i < 16; ++i) switch(out.get(i))
+ {
+ case 1:
+ out.set(i, 0);
+ break;
+ }
+ }
+
if(a1 < a0)
{
std::swap(a0, a1);
s2tc_try_encode_block<unsigned char, int, 3, false, true, 6>(out, r2, alpha_dist, in, iw, w, h, ramp);
r2.evaluate(a0, a1);
+ if(a1 == a0)
+ {
+ if(a0 == 255)
+ --a1;
+ else
+ ++a1;
+ for(int i = 0; i < 16; ++i) switch(out.get(i))
+ {
+ case 1:
+ out.set(i, 0);
+ break;
+ }
+ }
+
if(a1 < a0)
{
std::swap(a0, a1);
break;
out2.clear();
}
+
+ if(c0 == c1)
+ {
+ if(c0 == color_type_info<color_t>::max_value)
+ --c1;
+ else
+ ++c1;
+ for(int i = 0; i < 16; ++i)
+ if(!(out.get(i) == 1))
+ out.set(i, 0);
+ }
+
if(have_trans ? c1 < c0 : c0 < c1)
{
std::swap(c0, c1);
s2tc_evaluate_colors_result_t<color_t, bigcolor_t, 1> r2;
s2tc_try_encode_block<color_t, bigcolor_t, 2, have_trans, false, 2>(out, r2, ColorDist, in, iw, w, h, ramp);
r2.evaluate(c0, c1);
+
+ if(c0 == c1)
+ {
+ if(c0 == color_type_info<color_t>::max_value)
+ --c1;
+ else
+ ++c1;
+ for(int i = 0; i < 16; ++i)
+ if(!(out.get(i) == 1))
+ out.set(i, 0);
+ }
+
if(have_trans ? c1 < c0 : c0 < c1)
{
std::swap(c0, c1);
{
color_t c[16 + (nrandom >= 0 ? nrandom : 0)];
unsigned char ca[16 + (nrandom >= 0 ? nrandom : 0)];
- int n = 0, m = 0;
int x, y;
if(mode == MODE_FAST)
{
// FAST: trick from libtxc_dxtn: just get brightest and darkest colors, and encode using these
- color_t c0(0);
+ color_t c0 = make_color_t(0, 0, 0);
// dummy values because we don't know whether the first pixel willw rite
c[0].r = 31;
}
}
}
-
- // if ALL pixels were transparent, this won't stop us
-
- m = n = 2;
}
else
{
+ int n = 0, m = 0;
+
for(x = 0; x < w; ++x)
for(y = 0; y < h; ++y)
{
maxa = max(maxa, ca[x]);
}
}
- color_t len(maxs.r - mins.r + 1, maxs.g - mins.g + 1, maxs.b - mins.b + 1);
+ color_t len = make_color_t(maxs.r - mins.r + 1, maxs.g - mins.g + 1, maxs.b - mins.b + 1);
int lena = (dxt == DXT5) ? (maxa - (int) mina + 1) : 0;
for(x = 0; x < nrandom; ++x)
{
reduce_colors_inplace_2fixpoints(ca, n, m, alpha_dist, (unsigned char) 0, (unsigned char) 255);
}
+ // equal colors are BAD
+ if(c[0] == c[1])
+ {
+ if(c[0] == color_type_info<color_t>::max_value)
+ --c[1];
+ else
+ ++c[1];
+ }
+
+ if(dxt == DXT5)
+ {
+ if(ca[0] == ca[1])
+ {
+ if(ca[0] == 255)
+ --ca[1];
+ else
+ ++ca[1];
+ }
+ }
+
switch(dxt)
{
case DXT1:
{
case 3:
rgb565_image<3>(out, rgba, w, h, alphabits, dither);
+ break;
case 4:
default:
rgb565_image<4>(out, rgba, w, h, alphabits, dither);
+ break;
}
}