import imageadjuster.*; /** Illustrates extending the base ImageAdjuster class to support a posterize operation.
(as opposed to manually creating the corresponding lookup table with code as shown in demo 8)
Use this technique to implement "recipes" or other frequently-used operations not directly supported in the base class.
*/ class ImageAdjusterWithPosterize extends ImageAdjuster { // you need a constructor like this: ImageAdjusterWithPosterize(PApplet applet) { super(applet); } // then for each operation you intend to implement you should specify three methods as follows: // // 1) the "low-level" portion of the interface that actually builds the lookup table public void posterize(int levels) { int levels_minus_one = levels - 1; for (int i=0; i<256; i++) flut[i] = (float)((((int)flut[i] * levels) >> 8) * 255 / levels_minus_one); // buildILUT() is an internal routine that keeps the integer version of the // lookup table (ilut[]) in sync with the floating point version (flut[]). // required whenever flut[] changes: buildILUT(); } // 2) the "high-level" full-image portion of the interface public void posterize(PImage img, int levels) { // checkImage() is an internal error-checking routine, required: checkImage(img); // continue by calling your method 3) below (or duplicate code here) posterize(img, 0, 0, img.width, img.height, levels); } // 3) the "high-level" partial-image portion of the interface public void posterize(PImage img, int x, int y, int w, int h, int levels) { // checkImage() is an internal error-checking routine, required: checkImage(img); // reset() is an internal routine that resets the lookup table to unity values. // required by "high-level" interface methods: reset(); // build the posterize lookup table, using your method 1) above posterize(levels); // apply the lookup table to the image apply(img, x, y, w, h); } } // congratulations, your image adjuster class now supports posterize()! :-) // THE DEMO: size(200,200); background(loadImage("milan_rubbish.jpg")); ImageAdjusterWithPosterize adjust = new ImageAdjusterWithPosterize(this); // high-level tests: adjust.posterize(g, 0, 0, 50, 200, 2); adjust.posterize(g, 50, 0, 50, 200, 3); adjust.posterize(g, 100, 0, 50, 200, 4); // low-level accumulation test: adjust.reset(); adjust.brightness(0.25f); adjust.contrast(0.75f); adjust.posterize(4); // apply posterize() to values that have ALREADY been brightness/contrast adjusted adjust.apply(g, 150, 0, 50, 200); // but do it all with only a single pass through the pixels! :-)