// Need external definition of: scaleX, scaleY // Up to scaleX-1 pixel columns and scaleY pixel rows may be discarded // (those not fitting in a scaleX*scaleY block). The discarded pixels are // along the right and bottom border of the image, respectively. // Benchmark on screenshot for 1 MP: 2.6ms or less (twice as fast as scaleImage!) int w, h, w2, h2; int[] finalPixels; void scaleDown(BufferedImage img) { // TODO: remove the slow part scaleDown(main grabbableIntPixels_fastOrSlow(img)); } void scaleDown(GrabbableIntPixels gp) { w = gp.w; int h = this.h = gp.h; int w2 = this.w2 = w/scaleX, h2 = this.h2 = h/scaleY; int stride = gp.scanlineStride; int scaleArea = scaleX*scaleY; int[] newPixels = finalPixels = new int[w2*h2]; int iRow = gp.offset, iOut = 0; int[] pixels = gp.data; for y to h2: { int iIn = iRow; for x to w2: { // making one pixel of output image inside this block int r = 0, g = 0, b = 0; int iSub = iIn; for subY to scaleY: { for subX to scaleX: { int rgb = pixels[iSub+subX]; r += (rgb >> 16) & 0xFF; g += (rgb >> 8) & 0xFF; b += rgb & 0xFF; } iSub += stride; } iIn += scaleX; // advance input scaleX pixels to the right newPixels[iOut++] = rgbIntFullAlpha(r/scaleArea, g/scaleArea, b/scaleArea); } iRow += stride*scaleY; } // for y } BufferedImage get(BufferedImage img) { scaleDown(img); ret get(); } BufferedImage get() { ret bufferedImage(w2, h2, finalPixels); } GrabbableIntPixels grabbableIntPixels() { ret GrabbableIntPixels(finalPixels, w2, h2, 0, w2); }