// same brightness level count for each channel for now sclass PosterizeBufferedImage is PixelPreservingImageOpResult { BufferedImage img; BufferedImage result; IPosterizer posterizer; CachedPosterizer cachedPosterizer; *(int brightnessLevels, BufferedImage *img) { if (brightnessLevels >= 256 || img == null) posterizer = new DummyPosterizer; posterizer = SinglePixelPosterizer(brightnessLevels); } *(IPosterizer *posterizer, BufferedImage *img) {} run { if (img == null) ret; if (posterizer cast DummyPosterizer) ret with result = img; GrabbableIntPixels gp = grabbableIntPixels_fastOrSlow(img); int w = img.getWidth(), h = img.getHeight(), n = w*h; int[] pixels = gp.data; int[] pixels2 = new[n]; cachePosterizer(); var cachedPosterizer = this.cachedPosterizer; int iOut = 0, iIn = gp.offset; for y to h: { for x to w: { int rgb = pixels[iIn+x]; pixels2[iOut++] = rgbInt( cachedPosterizer.get(rgbRed(rgb)), cachedPosterizer.get(rgbGreen(rgb)), cachedPosterizer.get(rgbBlue(rgb))); } iIn += gp.scanlineStride; } result = bufferedImageWithoutAlpha(w, h, pixels2); } public BufferedImage pixelPreservingSrcImage() { ret img; } BufferedImage get() { if (result == null) run(); ret result; } private void cachePosterizer { if (cachedPosterizer == null) cachedPosterizer = main cachePosterizer(posterizer); } }