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! :-)