// drawing the resulting image on img1 gives img2 srecord noeq ImageDifferenceAsTransparentOverlay(BufferedImage img1, BufferedImage img2) { int w, h; int[] pixels; int x1, y1, x2, y2; // changed area (inclusive) GrabbableIntPixels gp1, gp2; run { if (pixels != null) ret; int w = this.w = img1.getWidth(), h = this.h = img1.getHeight(); assertSameSize(img1, img2); int[] pixels = this.pixels = new int[w*h]; gp1 = grabbableIntPixels_fastOrSlow(img1); gp2 = grabbableIntPixels_fastOrSlow(img2); int iPixels1 = gp1.offset, iPixels2 = gp2.offset; int[] pixels1 = gp1.data, pixels2 = gp2.data; int iPixels = 0; x1 = w; y1 = h; x2 = 0; y2 = 0; for y to h: { for x to w: { int pix; if ((pixels1[iPixels1+x] & 0xFFFFFF) != (pix = pixels2[iPixels2+x] & 0xFFFFFF)) { pixels[iPixels] = pix | 0xFF000000; if (x < x1) x1 = x; if (x > x2) x2 = x; if (y < y1) y1 = y; if (y > y2) y2 = y; } iPixels++; } iPixels1 += gp1.scanlineStride; iPixels2 += gp2.scanlineStride; } } BufferedImage get() { run(); ret newBufferedImageWithAlpha(w, h, pixels); } Rect changedBounds() { run(); ret rectFromPointsInclusive(x1, y1, x2, y2); } }