all tasks

This commit is contained in:
Ingy döt Net 2013-04-11 01:07:29 -07:00
parent b83f433714
commit 68f8f3e56b
14735 changed files with 178959 additions and 0 deletions

View file

@ -0,0 +1,103 @@
import std.math, std.algorithm, grayscale_image;
/// Plots anti-aliased line by Xiaolin Wu's line algorithm.
void aaLine(Color)(ref Image!Color img, double x1, double y1,
double x2, double y2,
in Color color)
/*pure*/ nothrow {
// Straight translation of Wikipedia pseudocode.
static double round(in double x) /*pure*/ nothrow {
return floor(x + 0.5); // Not pure.
}
static double fpart(in double x) /*pure*/ nothrow {
return x - floor(x);
}
static double rfpart(in double x) /*pure*/ nothrow {
return 1 - fpart(x);
}
auto dx = x2 - x1;
auto dy = y2 - y1;
immutable ax = abs(dx);
immutable ay = abs(dy);
static Color mixColors(in Color c1, in Color c2, in double p)
pure nothrow {
static if (is(Color == RGB))
return Color(cast(ubyte)(c1.r * p + c2.r * (1 - p)),
cast(ubyte)(c1.g * p + c2.g * (1 - p)),
cast(ubyte)(c1.b * p + c2.b * (1 - p)));
else
// This doesn't work for every kind of Color.
return Color(cast(ubyte)(c1 * p + c2 * (1 - p)));
}
// Plot function set here to handle the two cases of slope.
void delegate(in int, in int, in double) nothrow plot;
if (ax < ay) {
swap(x1, y1);
swap(x2, y2);
swap(dx, dy);
plot = (x, y, p) {
assert(p >= 0.0 && p <= 1.0);
img[y, x] = mixColors(color, img[y, x], p);
};
} else {
plot = (x, y, p) {
assert(p >= 0.0 && p <= 1.0);
img[x, y] = mixColors(color, img[x, y], p);
};
}
if (x2 < x1) {
swap(x1, x2);
swap(y1, y2);
}
immutable gradient = dy / dx;
// Handle first endpoint.
auto xEnd = round(x1);
auto yEnd = y1 + gradient * (xEnd - x1);
auto xGap = rfpart(x1 + 0.5);
// This will be used in the main loop.
immutable xpxl1 = cast(int)xEnd;
immutable ypxl1 = cast(int)floor(yEnd);
plot(xpxl1, ypxl1, rfpart(yEnd) * xGap);
plot(xpxl1, ypxl1 + 1, fpart(yEnd) * xGap);
// First y-intersection for the main loop.
auto yInter = yEnd + gradient;
// Handle second endpoint.
xEnd = round(x2);
yEnd = y2 + gradient * (xEnd - x2);
xGap = fpart(x2 + 0.5);
// This will be used in the main loop.
immutable xpxl2 = cast(int)xEnd;
immutable ypxl2 = cast(int)floor(yEnd);
plot(xpxl2, ypxl2, rfpart(yEnd) * xGap);
plot(xpxl2, ypxl2 + 1, fpart(yEnd) * xGap);
// Main loop.
foreach (immutable x; xpxl1 + 1 .. xpxl2) {
plot(x, cast(int)floor(yInter), rfpart(yInter));
plot(x, cast(int)floor(yInter) + 1, fpart(yInter));
yInter += gradient;
}
}
void main() {
auto im1 = new Image!Gray(400, 300);
im1.clear(Gray.white);
im1.aaLine(7.4, 12.3, 307, 122.5, Gray.black);
im1.aaLine(177.4, 12.3, 127, 222.5, Gray.black);
im1.savePGM("xiaolin_lines1.pgm");
auto im2 = new Image!RGB(400, 300);
im2.clear(RGB(0, 255, 0));
immutable red = RGB(255, 0, 0);
im2.aaLine(7.4, 12.3, 307, 122.5, red);
im2.aaLine(177.4, 12.3, 127, 222.5, red);
im2.savePPM6("xiaolin_lines2.ppm");
}