sclass IIVerticalSplit extends Meta implements IIntegralImage { // y coordinate of split point int splitPoint; // a and b must have same width // [0; splitPoint) RegisteredReference a = new(this); // [splitPoint; height) RegisteredReference b = new(this); *() {} *(IIntegralImage img, int splitPoint) { init(img, splitPoint); } void init(IIntegralImage img, int splitPoint) { this.splitPoint = splitPoint; int w = img.getWidth(), h = img.getHeight(); a.set(img.clip(0, 0, w, splitPoint)); b.set(img.clip(0, splitPoint, w, h-splitPoint)); } *(IIntegralImage img) { int h = img.getHeight(); if (h < 2) fail("Can't split image vertically - too small"); init(img, h/2); } *(IIntegralImage img1, IIntegralImage img2) { a.set(img1); b.set(img2); splitPoint = img1.getHeight(); } public int getWidth() { ret a->getWidth(); } public simplyCached int getHeight() { ret a->getHeight()+b->getHeight(); } public double getIntegralValue(int x, int y, int channel) { if (y < splitPoint) ret a->getIntegralValue(x, y, channel); else ret a->getIntegralValue(x, splitPoint, channel) + b->getIntegralValue(x, y-splitPoint, channel); } public double getIntegralValue(int x, int y) { if (y < splitPoint) ret a->getIntegralValue(x, y); else ret a->getIntegralValue(x, splitPoint) + b->getIntegralValue(x, y-splitPoint); } public BufferedImage getBufferedImage() { BufferedImage img = newBufferedImage(getWidth(), getHeight()); var g = graphics(img); a->drawAt(g, 0, 0); b->drawAt(g, 0, splitPoint); ret img; } }