// fills transparent pixels in the image with // the color of the (roughly) closest non-transparent neighbor pixel sclass ImageInfiller { settable BufferedImage inputImage; int w, h; int[] pixels; PtBuffer queue; PtBuffer nextQueue; BufferedImage outputImage; gettable int rounds; gettable int filledPixels; run { prepare(); do oneRound(); while (!done()); } bool done() { ret nextQueue.isEmpty(); } BufferedImage get() { ret pixelsToBufferedImage(pixels, w); } void prepare { pixels = pixelsFromBufferedImage(inputImage); w = inputImage.getWidth(); h = inputImage.getHeight(); } void oneRound { ++rounds; queue = nextQueue; nextQueue = new PtBuffer; for (p : queue == null ? pixelsInImageIterator(inputImage) : queue) { int x = p.x, y = p.y; int rgba = pixels[y*w+x]; if (rgba >= 0) continue; // not transparent //new IntBuffer colors; // surrounding colors new MultiSet surroundingColors; for (int y2 = max(0, y-1); y2 < min(h, y+2); y2++) for (int x2 = max(0, x-1); x2 < min(w, x+2); x2++) { rgba = pixels[y2*w+x2]; if (rgba < 0) surroundingColors.add(rgba); } if (!surroundingColors.isEmpty()) { // Surrounding color found, fill pixel pixels[y*w+x] = surroundingColors.mostPopular(); // Schedule surrounding transparent pixels for (int y2 = max(0, y-1); y2 < min(h, y+2); y2++) for (int x2 = max(0, x-1); x2 < min(w, x+2); x2++) nextQueue.add(x2, y2); } else // No surrounding colors found, reschedule this pixel nextQueue.add(p); } print("Round " + rounds + " pixels filled: " + n2(filledPixels)); } }