mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
405 lines
10 KiB
C++
405 lines
10 KiB
C++
#include <Draw/Draw.h>
|
|
|
|
using namespace Upp;
|
|
|
|
int sqr(int x)
|
|
{
|
|
return x * x;
|
|
}
|
|
|
|
RGBA Blend(RGBA a, RGBA b)
|
|
{
|
|
RGBA r;
|
|
r.a = ((int)a.a + b.a) >> 1;
|
|
r.r = ((int)a.r + b.r) >> 1;
|
|
r.g = ((int)a.g + b.g) >> 1;
|
|
r.b = ((int)a.b + b.b) >> 1;
|
|
return r;
|
|
}
|
|
|
|
RGBA Get(const Image& img, int x, int y)
|
|
{
|
|
return Rect(img.GetSize()).Contains(x, y) ? img[y][x] : White();
|
|
}
|
|
|
|
int SqrDistance(RGBA a, RGBA b)
|
|
{
|
|
return sqr(77 * ((int)a.r - b.r)) + sqr(151 * ((int)a.g - b.g)) + sqr(28 * ((int)a.b - b.b));
|
|
}
|
|
|
|
bool IsSimilar(RGBA a, RGBA b, int max)
|
|
{
|
|
return SqrDistance(a, b) <= sqr(max);
|
|
}
|
|
|
|
int GetColorIndex(Vector<RGBA>& colors, Color c, int max_distance)
|
|
{
|
|
for(int i = 0; i < colors.GetCount(); i++)
|
|
if(IsSimilar(colors[i], c, max_distance))
|
|
return i;
|
|
colors.Add(c);
|
|
return colors.GetCount() - 1;
|
|
}
|
|
|
|
struct Colors : Vector<RGBA> {
|
|
const Image& m;
|
|
int x, y;
|
|
|
|
int DX(int r) {
|
|
r &= 7;
|
|
return findarg(r, 0, 7, 6) >= 0 ? -1 : findarg(r, 2, 3, 4) >= 0 ? 1 : 0;
|
|
}
|
|
|
|
int DY(int r) {
|
|
r &= 7;
|
|
return findarg(r, 0, 1, 2) >= 0 ? -1 : findarg(r, 4, 5, 6) >= 0 ? 1 : 0;
|
|
}
|
|
|
|
RGBA Get(int dx, int dy) {
|
|
return ::Get(m, x + dx, y + dy);
|
|
}
|
|
|
|
RGBA Get(int r) {
|
|
return ::Get(m, x + DX(r), y + DY(r));
|
|
}
|
|
|
|
int GetCI(Color c)
|
|
{
|
|
return GetColorIndex(*this, c, 500);
|
|
}
|
|
|
|
int GetCI(int r) {
|
|
return GetCI(Get(r));
|
|
}
|
|
|
|
int GetCI(int dx, int dy) {
|
|
return GetColorIndex(*this, Get(dx, dy), 500);
|
|
}
|
|
|
|
Colors(const Image& m, int x, int y) : m(m), x(x), y(y) {}
|
|
};
|
|
|
|
Image Upscale(const Image& simg)
|
|
{
|
|
Size isz = simg.GetSize();
|
|
|
|
Image lan = RescaleFilter(simg, 2 * isz, FILTER_BILINEAR);
|
|
|
|
ImageBuffer ib(2 * isz);
|
|
|
|
Fill(~ib, RGBAZero(), ib.GetLength());
|
|
|
|
for(int x = 0; x < isz.cx; x++)
|
|
for(int y = 0; y < isz.cy; y++) {
|
|
DLOG("---------- " << x << ", " << y);
|
|
RGBA c = simg[y][x];
|
|
int p[16];
|
|
// 0 1 2
|
|
// 7 c 3
|
|
// 6 5 4
|
|
Colors colors(simg, x, y);
|
|
for(int i = 0; i < 8; i++) {
|
|
p[i] = p[i + 8] = colors.GetCI(i);
|
|
DLOG(i << ": " << p[i]);
|
|
}
|
|
int ci = colors.GetCI(c);
|
|
DDUMP(colors);
|
|
// 0 1
|
|
// 3 2
|
|
int *pp = p;
|
|
/* Index<int> in;
|
|
in.FindAdd(p[1]);
|
|
in.FindAdd(p[3]);
|
|
in.FindAdd(p[5]);
|
|
in.FindAdd(p[7]);
|
|
DDUMP(in.GetCount()); */
|
|
bool cq = (x ^ y) & 1;
|
|
|
|
for(int r = 0; r < 4; r++) {
|
|
int ix = 2 * x + (r == 1 || r == 2);
|
|
int iy = 2 * y + (r >= 2);
|
|
RGBA& t = ib[iy][ix];
|
|
t = c;
|
|
bool mrule = ci == pp[4] && ci == pp[3] && ci == pp[5] && ci != pp[0];
|
|
if(pp[1] == pp[7] && pp[0] == pp[1] &&
|
|
(!mrule || (Grayscale(colors.Get(2 * r + 0)) > Grayscale(c)))
|
|
// && pp[1] != pp[3] && pp[1] != pp[4] && pp[1] != pp[5]
|
|
// && !(pp[0] == pp[7] && pp[0] == pp[6] && pp[0] == pp[1] && pp[0] == pp[2]) // Box rule
|
|
// && ((cq/* && (r == 0 || r == 2)*/) || (pp[1] != pp[0]))
|
|
) {
|
|
t = Blend(colors.Get(2 * r + 7), colors.Get(2 * r + 1));
|
|
}
|
|
pp += 2;
|
|
}
|
|
}
|
|
|
|
return ib;
|
|
}
|
|
|
|
bool TryAA(int m, int d, RGBA a, RGBA b, RGBA c)
|
|
{
|
|
DDUMP(m);
|
|
DDUMP(d);
|
|
DDUMP(abs(m * (c.r - a.r) / d + a.r - b.r));
|
|
DDUMP(abs(m * (c.g - a.g) / d + a.g - b.g));
|
|
DDUMP(abs(m * (c.b - a.b) / d + a.b - b.b));
|
|
if(abs(m) > abs(d) || m * d < 0 || abs(m) < 10)
|
|
return false;
|
|
return (abs(m * (b.r - a.r) / d + a.r - b.r) < 4 &&
|
|
abs(m * (c.g - a.g) / d + a.g - b.g) < 4 &&
|
|
abs(m * (c.b - a.b) / d + a.b - b.b) < 4);
|
|
}
|
|
|
|
int AADetected(RGBA a, RGBA b, RGBA c)
|
|
{
|
|
DLOG("AADetect " << a << ", " << b << ", " << c);
|
|
|
|
if(IsSimilar(a, c, 500) || IsSimilar(b, c, 500) || IsSimilar(a, b, 500))
|
|
return false;
|
|
|
|
return TryAA(b.g - a.g, c.g - a.g, a, b, c) ||
|
|
TryAA(b.r - a.r, c.r - a.r, a, b, c) ||
|
|
TryAA(b.g - a.g, c.g - a.g, a, b, c);
|
|
}
|
|
|
|
Image UpscaleA(const Image& simg)
|
|
{
|
|
Size isz = simg.GetSize();
|
|
|
|
ImageBuffer ib(2 * isz);
|
|
|
|
Fill(~ib, RGBAZero(), ib.GetLength());
|
|
|
|
for(int x = 0; x < isz.cx; x++)
|
|
for(int y = 0; y < isz.cy; y++) {
|
|
DLOG("---------- " << x << ", " << y);
|
|
RGBA c = simg[y][x];
|
|
int p[16];
|
|
// 0 1 2
|
|
// 7 c 3
|
|
// 6 5 4
|
|
Colors m(simg, x, y);
|
|
for(int i = 0; i < 8; i++) {
|
|
p[i] = p[i + 8] = m.GetCI(i);
|
|
DLOG(i << ": " << p[i]);
|
|
}
|
|
int ci = m.GetCI(c);
|
|
|
|
RGBA t[4];
|
|
t[0] = t[1] = t[2] = t[3] = c;
|
|
bool hl = p[0] == p[1] && p[1] == p[2] ||
|
|
p[6] == p[5] && p[5] == p[4];
|
|
bool vl = p[0] == p[7] && p[7] == p[6] ||
|
|
p[2] == p[3] && p[3] == p[4];
|
|
bool dia = !hl && !vl;
|
|
dia = true;
|
|
int horz = AADetected(m.Get(7), c, m.Get(3)) * 1;
|
|
int vert = AADetected(m.Get(1), c, m.Get(5)) * 1;
|
|
int dia1 = AADetected(m.Get(0), c, m.Get(4)) * 1 * dia;
|
|
int dia2 = AADetected(m.Get(2), c, m.Get(6)) * 1 * dia;
|
|
const int *pp = p;
|
|
if(horz || vert || dia1 || dia2) {
|
|
if(horz && !vert)
|
|
t[1] = t[3] = m.Get(3);
|
|
else
|
|
if(vert && !horz)
|
|
t[2] = t[3] = m.Get(5);
|
|
else
|
|
const int *pp = p;
|
|
for(int i = 0; i < 4; i++) {
|
|
if(pp[0] == pp[1] && pp[1] == pp[7])
|
|
t[decode(i, 2, 3, 3, 2, i)] = m.Get(i * 2);
|
|
pp += 2;
|
|
}
|
|
}
|
|
|
|
ib[2 * y + 0][2 * x + 0] = t[0];
|
|
ib[2 * y + 0][2 * x + 1] = t[1];
|
|
ib[2 * y + 1][2 * x + 0] = t[2];
|
|
ib[2 * y + 1][2 * x + 1] = t[3];
|
|
}
|
|
|
|
return ib;
|
|
}
|
|
|
|
Image UpscaleA2(const Image& simg)
|
|
{
|
|
Size isz = simg.GetSize();
|
|
|
|
ImageBuffer ib(2 * isz);
|
|
|
|
Fill(~ib, RGBAZero(), ib.GetLength());
|
|
|
|
for(int y = 0; y < isz.cy; y++)
|
|
for(int x = 0; x < isz.cx; x++) {
|
|
DLOG("---------- " << x << ", " << y);
|
|
RGBA c = simg[y][x];
|
|
int p[16];
|
|
// 0 1 2
|
|
// 7 c 3
|
|
// 6 5 4
|
|
Colors m(simg, x, y);
|
|
for(int i = 0; i < 8; i++) {
|
|
p[i] = p[i + 8] = m.GetCI(i);
|
|
DLOG(i << ": " << p[i]);
|
|
}
|
|
int ci = m.GetCI(c);
|
|
|
|
RGBA t[4];
|
|
t[0] = t[1] = t[2] = t[3] = c;
|
|
bool h = AADetected(m.Get(7), c, m.Get(3));
|
|
bool v = AADetected(m.Get(1), c, m.Get(5));
|
|
if(h && v) {
|
|
const int *pp = p;
|
|
for(int i = 0; i < 4; i++) {
|
|
if(pp[0] == pp[1] && pp[1] == pp[7])
|
|
t[decode(i, 2, 3, 3, 2, i)] = m.Get(i * 2);
|
|
pp += 2;
|
|
}
|
|
}
|
|
else
|
|
if(h)
|
|
t[1] = t[3] = m.Get(3);
|
|
else
|
|
if(v)
|
|
t[2] = t[3] = m.Get(5);
|
|
|
|
ib[2 * y + 0][2 * x + 0] = t[0];
|
|
ib[2 * y + 0][2 * x + 1] = t[1];
|
|
ib[2 * y + 1][2 * x + 0] = t[2];
|
|
ib[2 * y + 1][2 * x + 1] = t[3];
|
|
}
|
|
|
|
return ib;
|
|
}
|
|
/* int best = max(horz, vert, dia1, dia2);
|
|
if(best == horz) t[1] = t[3] = m.Get(3);
|
|
else
|
|
if(best == vert) t[2] = t[3] = m.Get(5);
|
|
else
|
|
if(best == dia1) t[3] = m.Get(4);
|
|
else
|
|
if(best == dia2) t[2] = m.Get(6);*/
|
|
|
|
static inline int GetResult(uint32 A, uint32 B, uint32 C, uint32 D)
|
|
{
|
|
int x = 0;
|
|
int y = 0;
|
|
int r = 0;
|
|
if (A == C) x++; else if (B == C) y++;
|
|
if (A == D) x++; else if (B == D) y++;
|
|
if (x <= 1) r++;
|
|
if (y <= 1) r--;
|
|
return r;
|
|
}
|
|
|
|
RGBA Blend(RGBA a, RGBA b, RGBA c, RGBA d)
|
|
{
|
|
return Blend(Blend(a, b), Blend(c, d));
|
|
}
|
|
|
|
Image Upscale2(const Image& simg) // Super SAI
|
|
{
|
|
Size isz = simg.GetSize();
|
|
|
|
ImageBuffer ib(2 * isz);
|
|
|
|
Fill(~ib, RGBAZero(), ib.GetLength());
|
|
|
|
for(int x = 0; x < isz.cx; x++)
|
|
for(int y = 0; y < isz.cy; y++) {
|
|
DLOG("---------- " << x << ", " << y);
|
|
|
|
Colors m(simg, x, y);
|
|
|
|
int colorB0 = m.GetCI(-1, -1);
|
|
int colorB1 = m.GetCI(0, -1);
|
|
int colorB2 = m.GetCI(1, -1);
|
|
int colorB3 = m.GetCI(2, -1);
|
|
|
|
int color4 = m.GetCI(-1, 0);
|
|
int color5 = m.GetCI(0, 0);
|
|
int color6 = m.GetCI(1, 0);
|
|
int colorS2 = m.GetCI(2, 0);
|
|
|
|
int color1 = m.GetCI(-1, 1);
|
|
int color2 = m.GetCI(0, 1);
|
|
int color3 = m.GetCI(1, 1);
|
|
int colorS1 = m.GetCI(2, 1);
|
|
|
|
int colorA0 = m.GetCI(-1, 2);
|
|
int colorA1 = m.GetCI(0, 2);
|
|
int colorA2 = m.GetCI(1, 2);
|
|
int colorA3 = m.GetCI(2, 2);
|
|
|
|
RGBA product1a, product1b, product2a, product2b;
|
|
|
|
RGBA c2 = m.Get(0, 1);
|
|
RGBA c3 = m.Get(1, 1);
|
|
RGBA c5 = m.Get(0, 0);
|
|
RGBA c6 = m.Get(1, 0);
|
|
|
|
if(color2 == color6 && color5 != color3)
|
|
product2b = product1b = c2;
|
|
else
|
|
if(color5 == color3 && color2 != color6)
|
|
product2b = product1b = c5;
|
|
else
|
|
if(color5 == color3 && color2 == color6) {
|
|
int r = 0;
|
|
|
|
r += GetResult (color6, color5, color1, colorA1);
|
|
r += GetResult (color6, color5, color4, colorB1);
|
|
r += GetResult (color6, color5, colorA2, colorS1);
|
|
r += GetResult (color6, color5, colorB2, colorS2);
|
|
|
|
if(r > 0)
|
|
product2b = product1b = c6;
|
|
else
|
|
if(r < 0)
|
|
product2b = product1b = c5;
|
|
else
|
|
product2b = product1b = Blend(c5, c6);
|
|
}
|
|
else {
|
|
if(color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0)
|
|
product2b = Blend(c3, c3, c3, c2);
|
|
else
|
|
if(color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3)
|
|
product2b = Blend(c2, c2, c2, c3);
|
|
else
|
|
product2b = Blend(c2, c3);
|
|
|
|
if(color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0)
|
|
product1b = Blend(c6, c6, c6, c5);
|
|
else
|
|
if(color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3)
|
|
product1b = Blend(c6, c5, c5, c5);
|
|
else
|
|
product1b = Blend(c5, c6);
|
|
}
|
|
|
|
if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2)
|
|
product2a = Blend(c2, c5);
|
|
else
|
|
if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0)
|
|
product2a = Blend(c2, c5);
|
|
else
|
|
product2a = c2;
|
|
|
|
if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2)
|
|
product1a = Blend(c2, c5);
|
|
else
|
|
if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0)
|
|
product1a = Blend(c2, c5);
|
|
else
|
|
product1a = c5;
|
|
|
|
ib[2 * y][2 * x] = product1a;
|
|
ib[2 * y][2 * x + 1] = product1b;
|
|
ib[2 * y + 1][2 * x] = product2a;
|
|
ib[2 * y + 1][2 * x + 1] = product2b;
|
|
}
|
|
|
|
return ib;
|
|
}
|