summaryrefslogtreecommitdiff
path: root/smartblur.js
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2015-04-22 05:21:11 -0400
committerJules Laplace <jules@okfoc.us>2015-04-22 05:21:11 -0400
commitbef106de9fa827d983fa319cecdf688c2822efb9 (patch)
treed336ec726e97e5c19cb0dfee56d2bf4912d0db29 /smartblur.js
smartblur convolution experiment
Diffstat (limited to 'smartblur.js')
-rw-r--r--smartblur.js138
1 files changed, 138 insertions, 0 deletions
diff --git a/smartblur.js b/smartblur.js
new file mode 100644
index 0000000..181b1b4
--- /dev/null
+++ b/smartblur.js
@@ -0,0 +1,138 @@
+
+// http://asserttrue.blogspot.ca/2010/08/implementing-smart-blur-in-java.html
+SmartBlurFilter = function () {
+ var SENSITIVITY = 10
+ var REGION_SIZE = 5
+ var edge_zero_fill = true
+
+ var kx = -((REGION_SIZE/2)|0), ky = -((REGION_SIZE/2)|0), klen = REGION_SIZE*REGION_SIZE
+
+ var kernelArray = [
+ 1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1
+ ]
+
+ var kernel = new Kernel(9, 9, kernelArray)
+ kernel.normalize()
+
+ function lerp(a,b,amt) {
+ return a + amt * (b - a);
+ }
+
+ function rmsError(src, i, size) {
+ var ave = 0;
+
+ var len = size*size, data = src.data
+
+ var ix, iy
+ var r,g,b,a
+ var w = src.width, h = src.height
+ ix = i%w
+ iy = (i/w)|0
+ it = i * 4
+ r = g = b = a = 0
+ for (var j = 0; j < klen; j++) {
+ jx = ix + j%size + kx
+ jy = iy + ((j/size)|0) + ky
+ jt = 4 * (jx + jy*w)
+ if (0 > jx || jx > w || 0 > jy || jy > h) {
+ if (edge_zero_fill) {
+ continue
+ }
+ jt = it
+ }
+ r += data[jt]
+// g += data[jt+1]
+// b += data[jt+2]
+// a += data[jt+3]
+ }
+ r /= klen
+// g /= klen
+// b /= klen
+// a /= klen
+
+ var diff = 0
+ var accumulator = 0
+
+ for (var j = 0; j < klen; j++) {
+ jx = ix + j%size + kx
+ jy = iy + ((j/size)|0) + ky
+ jt = 4 * (jx + jy*w)
+ if (0 > jx || jx > w || 0 > jy || jy > h) {
+ if (edge_zero_fill) {
+ continue
+ }
+ jt = it
+ }
+ diff = data[ jt ] - ave
+ diff *= diff
+ accumulator += diff
+ }
+
+ var rms = accumulator / klen
+ rms = Math.sqrt(rms) / 255
+ return rms
+ }
+
+ function lerpPixel( src, dest, blur, i, amt) {
+ dest[i] = lerp(src[i], blur[i], amt)
+ dest[i+1] = lerp(src[i+1], blur[i+1], amt)
+ dest[i+2] = lerp(src[i+2], blur[i+2], amt)
+ dest[i+3] = lerp(src[i+3], blur[i+3], amt)
+ }
+
+ function blurImage( src, dest, blur, sensitivity ) {
+ var newPixel = 0
+ var amt = 0
+ var size = REGION_SIZE
+ var w = src.width, rms
+
+ var srcData = src.data
+ var destData = dest.data
+ var blurData = blur.data
+ for (var i = 0, len = srcData.length/4; i < len; i++) {
+
+ rms = rmsError(src, i, size)
+
+// amt = rms < sensitivity ? rms/sensitivity : 1.0
+ lerpPixel( srcData, destData, blurData, i*4, rms)
+ }
+
+ return dest
+ }
+
+ this.blur = function (src_canvas, dest_canvas) {
+ var convolver = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
+
+ // clone image into target
+ if (! dest_canvas) dest_canvas = document.createElement("canvas")
+ var w = dest_canvas.width = src_canvas.width
+ var h = dest_canvas.height = src_canvas.height
+ var srcctx = src_canvas.getContext('2d')
+ var destctx = dest_canvas.getContext('2d')
+
+ destctx.drawImage(src_canvas, 0, 0);
+
+ // get source pixels
+ var src = srcctx.getImageData(0,0,w,h)
+ var dest = destctx.getImageData(0,0,w,h)
+
+ // blur the cloned image
+ dest = convolver.filter(src, dest);
+
+ destctx.putImageData(dest, 0,0)
+ var blurred = destctx.getImageData(0,0,w,h)
+ var dest = srcctx.getImageData(0,0,w,h)
+ dest = blurImage(src, dest, blurred, SENSITIVITY)
+ destctx.putImageData(dest, 0,0)
+
+ return dest_canvas
+ }
+} \ No newline at end of file