Skip to content

Instantly share code, notes, and snippets.

@Reputeless
Created Oct 4, 2014
Embed
What would you like to do?
# include <Siv3D.hpp>
//
// 参考
// 『詳解 画像処理プログラミング』
// http://www.sbcr.jp/products/4797344370.html
//
int Solve2(double a, double b, double c, double& x1, double& x2)
{
if (a == 0.0)
{
if (c == 0.0)
{
return false;
}
x1 = -b / c;
x2 = -b / c;
return true;
}
double dd = b*b - 4.0*a*c;
x1 = 0.0;
x2 = 0.0;
if (dd < 0.0)
{
return false;
}
x1 = (-b + sqrt(dd)) / (2.0*a);
x2 = (-b - sqrt(dd)) / (2.0*a);
return true;
}
void Solve(
double a, double b, double c, double d,
double e, double f, double g, double h,
double& xa, double& ya, double& xb, double& yb
)
{
double p1 = a*h - f*c;
double p2 = d*f - c*g + b*h - a*e;
double p3 = d*g - b*e;
if (p1 == 0.0)
{
xa = d / b;
ya = (b*e - d*g) / (b*h + d*f);
xb = -1000;
yb = -1000;
return;
}
if (!Solve2(p1, p2, p3, ya, yb))
{
xa = -1000;
xb = -1000;
return;
}
double tm = a* ya + b;
if (tm)
{
xa = (d - c * ya) / tm;
}
else
{
xa = -1000;
}
tm = a* yb + b;
if (tm)
{
xb = (d - c * yb) / tm;
}
else
{
xb = -1000.0;
}
}
void Transform(const Image& src, Image& dst, const double(&px)[4], const double(&py)[4])
{
const int rx1 = 0;
const int ry1 = 0;
const int rx2 = src.height - 1;
const int ry2 = src.width - 1;
double aa = px[2] - px[3] - px[1] + px[0];
double bb = px[1] - px[0];
double cc = px[3] - px[0];
double ff = py[2] - py[3] - py[1] + py[0];
double gg = py[1] - py[0];
double hh = py[3] - py[0];
if (!aa) aa = 0.001;
if (!ff) ff = 0.001;
for (int y = 0; y < dst.height; ++y)
{
for (int x = 0; x < dst.width; ++x)
{
const double xx = x + 0.5;
const double yy = y + 0.5;
if (!Quad(px[0], py[0], px[3], py[3], px[2], py[2], px[1], py[1]).intersects(Vec2(xx,yy)))
{
continue;
}
double s1, t1, s2, t2, tx, ty;
const double dd = xx - px[0];
const double ee = yy - py[0];
Solve(aa, bb, cc, dd, ee, ff, gg, hh, s1, t1, s2, t2);
if (s1 >= 0 && t1 >= 0 && s1 <= 1.0 && t1 <= 1.0)
{
tx = s1*(rx2 - rx1) + rx1;
ty = t1*(ry2 - ry1) + ry1;
}
else
{
tx = s2*(rx2 - rx1) + rx1;
ty = t2*(ry2 - ry1) + ry1;
}
if (tx < 0 || ty < 0)
{
continue;
}
dst[y][x] = src.sample(tx-0.5, ty-0.5);
}
}
}
void Transform(const Image& src, Image& dst, const Quad& to)
{
if (&src == &dst)
{
return;
}
const double xs[4] = { to.tl.x, to.bl.x, to.br.x, to.tr.x };
const double ys[4] = { to.tl.y, to.bl.y, to.br.y, to.tr.y };
Transform(src, dst, xs, ys);
}
void Main()
{
Image image(L"Example/Windmill.png");
Image canvas(640, 480, Color(0, 0));
Quad quad({ 0, 0 }, { image.width, 0 }, { image.width, image.height }, { 0, image.height });
Transform(image, canvas, quad);
DynamicTexture texture(canvas);
optional<int> grabbed;
while (System::Update())
{
if (Input::MouseL.released)
{
grabbed = none;
canvas.fill(Color(0, 0));
Transform(image, canvas, quad);
texture.fill(canvas);
}
if (grabbed)
{
quad.p[grabbed.get()].moveBy(Mouse::Delta());
}
if (Input::MouseL.clicked)
{
for (int i = 0; i < 4; ++i)
{
if (Circle(quad.p[i], 12).leftClicked)
{
grabbed = i;
break;
}
}
}
texture.draw();
for (const auto& pt : quad.p)
{
Circle(pt, 12).drawFrame(4, 0, Palette::Orange);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment