srecord noeq MinimalRecognizer(BufferedImage inputImage) { replace Channel with int. IIntegralImage mainImage; abstract class IIntegralImage { // width and height of image int w, h; double integralValue(int x, int y, Channel channel); BufferedImage render() { int w = getWidth(), h = getHeight(); int[] pixels = new[w*h]; int i = 0; for y to h: for x to w: pixels[i++] = rgbPixel(x, y, x+1, y+1) | fullAlphaMask(); ret intArrayToBufferedImage(pixels, w, h); } double[] rectSum(int x1, int y1, int x2, int y2, int channel) { double bottomLeft = integralValue(x1-1, y2-1, channel); double bottomRight = integralValue(x2-1, y2-1, channel); double topLeft = integralValue(x1-1, y1-1, channel); double topRight = integralValue(x2-1, y1-1, channel); ret bottomRight+topLeft-topRight-bottomLeft; } double getPixel(int x1, int y1, int x2, int y2, int channel) { ret doubleRatio(rectSum(x1, y1, x2, y2, channel), (x2-x1)*(y2-y1)); } int rgbPixel(int x1, int y1, int x2, int y2) { int r = iround(getPixel(x1, y1, x2, y2, 0)); int g = iround(getPixel(x1, y1, x2, y2, 1)); int b = iround(getPixel(x1, y1, x2, y2, 2)); ret rgbInt(r, g, b); } } class IntegralImage extends IIntegralImage { int[] data; *(BufferedImage img) { w = img.getWidth(); h = img.getHeight(); if (longMul(w, h) > 8000000) fail("Image too big: " + w + "*" + h); int[] pixels = pixelsOfBufferedImage(img); data = new int[w*h*3]; 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; } } } public double integralValue(int x, int y, Channel channel) { ret x < 0 || y < 0 ? 0 : data[(min(y, h-1)*w+min(x, w-1))*3+channel]; } } run { mainImage = new IntegralImage(inputImage); inputImage = null; // save space } }