persistable sclass HexagonalIntegralImage { final int w, h; // 3 ints per pixel. data[0] is the sharp edge, data[1] the blunt edge final int[2][] data; // the column sums in three directions // north, north west, north east final int[][] columnSums = new int[3][]; *(BufferedImage img) { this(RGBImage img); } *(RGBImage img) { w = img.w(); h = img.h(); data1 = new int[w*h*3]; int i = 0; for y to h: { int sumR = 0, sumG = 0, sumB = 0; int shift = iround(y*sqrtAThird()); for x to w: { // grab pixels int rgb = img.getInt(x, y); sumR += (rgb >> 16) & 0xFF; sumG += (rgb >> 8) & 0xFF; sumB += rgb & 0xFF; // calc wedges data[0][i] = sumR; data[0][i+1] = sumG; data[0][i+2] = sumB; if (y != 0) { if (x >= shift) { data[0][i] += data[0][i-(w+shift)*3]; data[0][i+1] += data[0][i-(w+shift)*3+1]; data[0][i+2] += data[0][i-(w+shift)*3+2]; } if (x+shift < w) { data[1][i] += data[1][i-(w-shift)*3]; data[1][i+1] += data[1][i-(w-shift)*3+1]; data[1][i+2] += data[1][i-(w-shift)*3+2]; } } i += 3; } } columnSums[0] = new int[h]; for y to h: for x to w: { c for i over columnSums: columnSums[i] = new int[max(w, h)*2]; // TODO: find actual upper bound int i = 0, j = 0, sumR = 0, sumG = 0, sumB = 0; for x to w: { int rgb = pixels[j++]; data[i++] = (sumR += (rgb >> 16) & 0xFF); data[i++] = (sumG += (rgb >> 8) & 0xFF); data[i++] = (sumB += rgb & 0xFF); } for (int y = 1; y < h; y++) { sumR = sumG = sumB = 0; for x to w: { int rgb = pixels[j++]; sumR += (rgb >> 16) & 0xFF; sumG += (rgb >> 8) & 0xFF; sumB += rgb & 0xFF; data[i] = sumR + data[i-w*3]; data[i+1] = sumG + data[i-w*3+1]; data[i+2] = sumB + data[i-w*3+2]; i += 3; } } } // gets the integral value at x/y for given RGB channel int get(int x, int y, int channel) { ret x < 0 || y < 0 || x >= w || y >= h ? 0 : data[(y*w+x)*3+channel]; } // gets sum of the 3 channels int get(int x, int y) { if (x < 0 || y < 0 || x >= w || y >= h) ret 0; int i = (y*w+x)*3; ret data[i]+data[i+1]+data[i+2]; } double averageBrightness() { ret doubleRatio(get(w-1, h-1), w*h*3*255.0); } toString { ret "HexagonalIntegralImage " + w + "*" + h + ", brightness: " + averageBrightness(); } public int getWidth() { ret w; } public int getHeight() { ret h; } int w() { ret w; } int h() { ret h; } }