/** Adjust scrollbars to reprocess image.
Click buttons to select new source image.
Right-click mouse to display original image for comparison.

Ortonizer
Dave Bollinger, Feb 2006
http://www.davebollinger.com
For Processing 0109 Beta
(recompiled with 0124 while contemplating 0125 blend modes, Jan 2007)

An implementation of a technique named after photographer Michael Orton.
For example see the Orton Pool on Flickr.
An image is brightened, then blurred then blended with itself
to achieve a soft diffusion highlight, almost an airbrushed effect.
(Orton's original technique involved overlaying two separate negatives that
were overexposed by controlled amounts, one sharp focused, one soft focused.)

*/ PImage source, ortonized; void setup() { size(400, 340); UIInit(); } void draw() { UIUpdate(); image((mousePressed && mouseButton==RIGHT) ? source : ortonized, 0, 0); UIDraw(); } //=========================== // IMAGE PROCESSING ROUTINES //=========================== PImage Ortonize(PImage img, int briteness, float blurradius) { // a screen overlay is also commonly used, though i think plain old brightness more often looks better PImage brightened = Brightness(img, briteness); PImage blurred = Blur(brightened, blurradius); return Multiply(brightened, blurred); } int peg(int n) { return (n < 0) ? 0 : ((n > 255) ? 255 : n); } // TODO: use ImageAdjuster lib or 0125's screen blend mode PImage Brightness(PImage imgA, int amount) { PImage imgC = new PImage(imgA.width, imgA.height); int [] pixA = imgA.pixels; int [] pixC = imgC.pixels; int n = imgA.width * imgA.height; for (int i=0; i> 16) + amount; int gg = ((a & GREEN_MASK) >> 8) + amount; int bb = ((a & BLUE_MASK)) + amount; pixC[i] = 0xFF000000 | (peg(rr)<<16) | (peg(gg)<<8) | (peg(bb)); } return imgC; } PImage Blur(PImage in, float radius) { PImage out = in.get(); out.filter(BLUR, radius); return out; } // TODO: use 0125's multiply blend mode PImage Multiply(PImage imgA, PImage imgB) { PImage imgC = new PImage(imgA.width, imgA.height); int [] pixA = imgA.pixels; int [] pixB = imgB.pixels; int [] pixC = imgC.pixels; int n = imgA.width * imgA.height; for (int i=0; i> 16) * ((b & RED_MASK) >> 16)) >> 8; int gg = (((a & GREEN_MASK) >> 8) * ((b & GREEN_MASK) >> 8)) >> 8; int bb = (((a & BLUE_MASK)) * ((b & BLUE_MASK))) >> 8; pixC[i] = 0xFF000000 | (peg(rr)<<16) | (peg(gg)<<8) | (peg(bb)); } return imgC; }