#include "length.h" #include "grid.h" #include #include #include #include #define OUT_MAXVAL 15 // distance to the first contour between "here" and there", as [0..OUT_MAXVAL] int contour_between(int here, int there, int interval) { // each contour is one half-step above each multiple of interval interval = 2 * interval; here = 2 * here + interval - 1; there = 2 * there + interval - 1; if (here < there) { int out = OUT_MAXVAL * (interval - here % interval) / (there - here); return std::min(OUT_MAXVAL, out); } else if (here > there) { int out = OUT_MAXVAL * (here % interval) / (here - there); return std::min(OUT_MAXVAL, out); } else { return OUT_MAXVAL; } } int contour_pixel(grid const& image, int x, int y, int interval) { int p = 0; if (x > 0) p += OUT_MAXVAL - contour_between(image[x][y], image[x-1][y], interval); if (x < xsize(image) - 1) p += OUT_MAXVAL - contour_between(image[x][y], image[x+1][y], interval); if (y > 0) p += OUT_MAXVAL - contour_between(image[x][y], image[x][y-1], interval); if (y < ysize(image) - 1) p += OUT_MAXVAL - contour_between(image[x][y], image[x][y+1], interval); return std::min(OUT_MAXVAL, p); } void contour_image(grid const& image, int interval, grid* out) { for (int x = 0; x < xsize(image); ++x) { for (int y = 0; y < ysize(image); ++y) { (*out)[x][y] = contour_pixel(image, x, y, interval); } } } int main(int argc, char** argv) { if (argc != 3) { fprintf(stderr, "usage: %s interval input.pgm > output.pgm\n", argv[0]); return 2; } int interval = parse_length(argv[1]); if (interval <= 0) { fprintf(stderr, "invalid interval: %s\n", argv[1]); return 1; } grid image, out; read_pgm(argv[2], &image); resize(xsize(image), ysize(image), &out); contour_image(image, interval, &out); write_pgm(out, NULL, OUT_MAXVAL + 1); return 0; }