-
-
Save Reputeless/d953e503a144f4a8e072 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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