C++, Score: 1.42042 1.4204246766
EDIT: Using nonlinear brightness in neighborhood calculation improves the score slightly.
Compile with g++ joe.cpp -ojoe -std=c++11 -O3 -lcairo
. Requires cairo.
#include <cairo/cairo.h>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
using namespace std;
int main(int argc, const char* argv[]) {
auto* img = cairo_image_surface_create_from_png(argv[1]);
int width = cairo_image_surface_get_width(img),
height = cairo_image_surface_get_height(img),
stride = cairo_image_surface_get_stride(img);
unsigned char* data = cairo_image_surface_get_data(img);
double* brightness = new double[width * height];
double total_brightness = 0;
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
const unsigned char* p = data + stride * y + 4 * x;
total_brightness += brightness[y * width + x] = p[0] + p[1] + p[2];
}
}
const int r = argc > 2 ? stoi(argv[2]) : 64, R = 2 * r + 1;
double* weight = new double[R * R];
for (int y = -r; y <= r; ++y) {
for (int x = -r; x <= r; ++x)
weight[R * (y + r) + (x + r)] = 1.0 / (x*x + y*y + 1);
}
auto neighborhood = [&] (int x, int y) {
double b = 0;
int x1 = max(x - r, 0), x2 = min(x + r, width - 1);
int y1 = max(y - r, 0), y2 = min(y + r, height - 1);
for (int v = y1; v <= y2; ++v) {
const double *B = brightness + width * v + x1;
const double *W = weight + R * (v - (y - r)) + (x1 - (x - r));
for (int u = x1; u <= x2; ++u, ++B, ++W)
b += (*W) * *B;(*B) * (*B);
}
return b;
};
int n = (2 * width * height + 3) / 6;
int x = 0, y = 0;
double path_brightness = 0;
int O[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (int i = 0; i < n; ++i) {
if (i % 1000 == 0) cerr << (200 * i + n) / (2 * n) << "%\r";
path_brightness += brightness[width * y + x]; brightness[width * y + x] = 0;
unsigned char* p = data + stride * y + 4 * x;
p[0] = p[1] = 16 * i % 255; p[2] = 0;
auto O_end = partition(begin(O), end(O), [&] (const int* o) {
return x + o[0] >= 0 && x + o[0] < width &&
y + o[1] >= 0 && y + o[1] < height;
});
const int* o_max; double o_max_neighborhood = -1;
for (auto o = O; o != O_end; ++o) {
double o_neighborhood = neighborhood(x + (*o)[0], y + (*o)[1]);
if (o_neighborhood > o_max_neighborhood)
o_max = *o, o_max_neighborhood = o_neighborhood;
}
x += o_max[0]; y += o_max[1];
}
cout << (path_brightness * width * height) / (n * total_brightness) << endl;
cairo_surface_write_to_png(img, (string("out.") + argv[1]).c_str());
delete []brightness;
delete []weight;
cairo_surface_destroy(img);
}
Bridge 1.3686939945
Balls 1.6601677714
Scream 1.3532138349
Fractal 1.2701731727
Vortex 1.6052866493
Tornado 1.2650326366
-----------------
Average 1.4204246766