Interesting question!
Here's how to implement a blur brush using:
- an offscreen canvas
- a blur-effect algorithm
- compositing to "clip" an image to fit in the user's brush-strokes
- compositing to "draw-behind" the clear image behind the blurred brushstroke image.
A Demo: http://jsfiddle.net/m1erickson/baDLp/
- create an offscreen canvas
- let the user draw on the onscreen canvas with a brush
- simultaneously draw the same brush-strokes on the offscreen canvas
- after the user is finished brushing...
- set the offscreen canvas compositing to "source-in" (any new drawing is only on the existing brushstrokes.
- drawImage the image on the offscreen canvas (the image will be drawn only on the brushstrokes)
- use a blur algorithm to blur the offscreen canvas (at this point the offscreen canvas contains a blurred image only on the brushstrokes)
- clear the onscreen canvas
- use drawImage to copy the blurred brush-image from the offscreen canvas to the onscreen canvas.
- set the onscreen canvas compositing to "destination-over" (new drawings are drawn behind the existing blurred brush-image
- drawImage the source image to the onscreen canvas (the blurred brush-image remains and the source image is drawn behind that brush-image)
Here's how that looks in code:
(The blur effect is done using quasimondo's nice blurring algorithm: http://jsfiddle.net/m1erickson/baDLp/)
// At this point, the temp canvas contains
// only the users brush strokes
// draw the image "clipped" into those brush strokes
// using compositing == "source-in"
tempCtx.save();
tempCtx.globalCompositeOperation="source-in";
tempCtx.drawImage(img,0,0);
tempCtx.restore();
// blur the brush-image on the temp canvas
boxBlurCanvasRGBA("tempCanvas",0,0,tempCanvas.width,tempCanvas.height,4,0);
// clear the onscreen canvas
ctx.save();
ctx.clearRect(0,0,canvas.width,canvas.height);
// draw the brush-image from the temp canvas to the onscreen canvas
ctx.drawImage(tempCanvas,0,0);
// use compositing == "destination-over"
// to draw the source image *behind* the blurred brush-image
ctx.globalCompositeOperation="destination-over";
ctx.drawImage(img,0,0);
ctx.restore();
Source Image:
Offscreen canvas after drawing the image only on the stroked area and then blurring:
The onscreen canvas with the blurred area merged into the source image: