From 0d944aac27568dfd63c8ea9f493ca987c72c8436 Mon Sep 17 00:00:00 2001 From: Eric Rowell Date: Sat, 4 Jan 2014 05:21:44 -0800 Subject: [PATCH] removed convolve pack. Added pixastic emboss filter --- Gruntfile.js | 2 +- src/filters/ConvolvePack.js | 201 ------------------------- src/filters/Emboss.js | 169 +++++++++++++++++++++ test/runner.html | 2 +- test/unit/filters/ConvolvePack-test.js | 179 ---------------------- test/unit/filters/Emboss-test.js | 96 ++++++++++++ 6 files changed, 267 insertions(+), 382 deletions(-) delete mode 100644 src/filters/ConvolvePack.js create mode 100644 src/filters/Emboss.js delete mode 100644 test/unit/filters/ConvolvePack-test.js create mode 100644 test/unit/filters/Emboss-test.js diff --git a/Gruntfile.js b/Gruntfile.js index e415abfa..ad924792 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -17,7 +17,7 @@ module.exports = function(grunt) { 'src/filters/Mask.js', 'src/filters/RGB.js', 'src/filters/HSV.js', - 'src/filters/ConvolvePack.js', + 'src/filters/Emboss.js', 'src/filters/Enhance.js', 'src/filters/Posterize.js', 'src/filters/Noise.js', diff --git a/src/filters/ConvolvePack.js b/src/filters/ConvolvePack.js deleted file mode 100644 index 13b63d99..00000000 --- a/src/filters/ConvolvePack.js +++ /dev/null @@ -1,201 +0,0 @@ -(function() { - - // Definition of a gaussian function - var gaussian = function(x,mean,sigma){ - var dx = x - mean; - return Math.pow(Math.E, -dx*dx / (2*sigma*sigma)); - }; - - var make_blur_kernel = function( size, scale, sigma ){ - - // make sure size is odd: - if( size % 2 === 0 ){ size += 1; } - - // Generate the kernel, we can just multiply 2 single dimensional - // gaussians to get a 2D guassian - var kernel = [], i,j, row; - for( i=0; i 0) ? px : -px; - py = (y + i - matrixMidY) % ySize; - py = (py > 0) ? py : -py; - - // get the pixel and convolve - pos = (py * xSize + px) * 4; - r += matrix[j][i] * srcPixels[pos + 0]; - g += matrix[j][i] * srcPixels[pos + 1]; - b += matrix[j][i] * srcPixels[pos + 2]; - //a += matrix[j][i]*srcPixels[pos+3]; - } - } - - // Store the result - pos = (y * xSize + x) * 4; - dstPixels[pos + 0] = r; - dstPixels[pos + 1] = g; - dstPixels[pos + 2] = b; - dstPixels[pos + 3] = srcPixels[pos + 3]; - } - } - }; - - Kinetic.Filters.Emboss = Kinetic.Util._FilterWrapDoubleBuffer(function(src,dst,opt){ - var s = this.getFilterAmount()/100; - convolve(src,dst,{kernel:[ - [-1*s, -0.5*s, 0], - [-0.5*s,1+0.5*s, 0.5*s], - [ 0, 0.5*s, 1*s] - ]}); - }); - - Kinetic.Filters.Edge = Kinetic.Util._FilterWrapDoubleBuffer(function(src,dst,opt){ - var s = this.getFilterAmount()/100; - convolve(src,dst,{kernel:[ - [ 0, -1*s, 0], - [-1*s,(1-s)+4*s,-1*s], - [ 0, -1*s, 0] - ]}); - }); - - Kinetic.Filters.SoftBlur = Kinetic.Util._FilterWrapDoubleBuffer(function(src,dst,opt){ - var s = this.getFilterAmount()/100; - convolve(src,dst,{kernel:make_soft_blur_kernel(5,s)}); - }); - - Kinetic.Filters.UnsharpMask = Kinetic.Util._FilterWrapDoubleBuffer(function(src,dst,opt){ - var s = this.getFilterAmount()/100; - convolve(src,dst,{kernel:make_unsharp_kernel(5,s)}); - }); - -})(); diff --git a/src/filters/Emboss.js b/src/filters/Emboss.js new file mode 100644 index 00000000..f547a89a --- /dev/null +++ b/src/filters/Emboss.js @@ -0,0 +1,169 @@ +(function () { + /** + * Emboss Filter + * @function + * @memberof Kinetic.Filters + * @param {Object} imageData + * Pixastic Lib - Emboss filter - v0.1.0 + * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ + * License: [http://www.pixastic.com/lib/license.txt] + */ + Kinetic.Filters.Emboss = function (imageData) { + + // pixastic strength is between 0 and 10. I want it between 0 and 1 + // pixastic greyLevel is between 0 and 255. I want it between 0 and 1. Also, + // a max value of greyLevel yields a white emboss, and the min value yields a black + // emboss. Therefore, I changed greyLevel to whiteLevel + var strength = this.embossStrength() * 10, + greyLevel = this.embossWhiteLevel() * 255, + direction = this.embossDirection(), + blend = this.embossBlend(), + dirY = 0, + dirX = 0, + data = imageData.data, + invertAlpha = false, + w = imageData.width, + h = imageData.height, + w4 = w*4, + y = h; + + switch (direction) { + case 'top-left': + dirY = -1; + dirX = -1; + break; + case 'top': + dirY = -1; + dirX = 0; + break; + case 'top-right': + dirY = -1; + dirX = 1; + break; + case 'right': + dirY = 0; + dirX = 1; + break; + case 'bottom-right': + dirY = 1; + dirX = 1; + break; + case 'bottom': + dirY = 1; + dirX = 0; + break; + case 'bottom-left': + dirY = 1; + dirX = -1; + break; + case 'left': + dirY = 0; + dirX = -1; + break; + } + + do { + var offsetY = (y-1)*w4; + + var otherY = dirY; + if (y + otherY < 1) otherY = 0; + if (y + otherY > h) otherY = 0; + + var offsetYOther = (y-1+otherY)*w*4; + + var x = w; + do { + var offset = offsetY + (x-1)*4; + + var otherX = dirX; + if (x + otherX < 1) otherX = 0; + if (x + otherX > w) otherX = 0; + + var offsetOther = offsetYOther + (x-1+otherX)*4; + + var dR = data[offset] - data[offsetOther]; + var dG = data[offset+1] - data[offsetOther+1]; + var dB = data[offset+2] - data[offsetOther+2]; + + var dif = dR; + var absDif = dif > 0 ? dif : -dif; + + var absG = dG > 0 ? dG : -dG; + var absB = dB > 0 ? dB : -dB; + + if (absG > absDif) { + dif = dG; + } + if (absB > absDif) { + dif = dB; + } + + dif *= strength; + + if (blend) { + var r = data[offset] + dif; + var g = data[offset+1] + dif; + var b = data[offset+2] + dif; + + data[offset] = (r > 255) ? 255 : (r < 0 ? 0 : r); + data[offset+1] = (g > 255) ? 255 : (g < 0 ? 0 : g); + data[offset+2] = (b > 255) ? 255 : (b < 0 ? 0 : b); + } else { + var grey = greyLevel - dif; + if (grey < 0) { + grey = 0; + } else if (grey > 255) { + grey = 255; + } + + data[offset] = data[offset+1] = data[offset+2] = grey; + } + + } while (--x); + } while (--y); + }; + + Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'embossStrength', 0.5); + /** + * get/set emboss strength + * @name embossStrength + * @method + * @memberof Kinetic.Node.prototype + * @param {Number} level between 0 and 1. Default is 0.5 + * @returns {Number} + */ + + Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'embossWhiteLevel', 0.5); + /** + * get/set emboss white level + * @name embossWhiteLevel + * @method + * @memberof Kinetic.Node.prototype + * @param {Number} embossWhiteLevel between 0 and 1. Default is 0.5 + * @returns {Number} + */ + + Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'embossDirection', 'top-left'); + /** + * get/set emboss direction + * @name embossDirection + * @method + * @memberof Kinetic.Node.prototype + * @param {String} embossDirection can be top-left, top, top-right, right, bottom-right, bottom, bottom-left or left + * The default is top-left + * @returns {String} + */ + + Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'embossBlend', false); + /** + * get/set emboss blend + * @name embossBlend + * @method + * @memberof Kinetic.Node.prototype + * @param {Boolean} embossBlend + * @returns {Boolean} + */ + +})(); + + diff --git a/test/runner.html b/test/runner.html index 5e2d1abe..b8a9841a 100644 --- a/test/runner.html +++ b/test/runner.html @@ -87,7 +87,6 @@ - @@ -97,6 +96,7 @@ + diff --git a/test/unit/filters/ConvolvePack-test.js b/test/unit/filters/ConvolvePack-test.js deleted file mode 100644 index ebabea73..00000000 --- a/test/unit/filters/ConvolvePack-test.js +++ /dev/null @@ -1,179 +0,0 @@ -suite('ConvolvePack', function() { - - // ====================================================== - test('emboss', function(done) { - var stage = addStage(); - - var imageObj = new Image(); - imageObj.onload = function() { - var layer = new Kinetic.Layer(); - darth = new Kinetic.Image({ - x: 10, - y: 10, - image: imageObj, - draggable: true - }); - - layer.add(darth); - stage.add(layer); - darth.cache(); - darth.filters([Kinetic.Filters.Emboss]); - darth.filterAmount(100); - layer.draw(); - - var tween = new Kinetic.Tween({ - node: darth, - duration: 0.6, - filterAmount: 0, - easing: Kinetic.Easings.EaseInOut - }); - - darth.on('mouseover', function() { - tween.play(); - }); - - darth.on('mouseout', function() { - tween.reverse(); - }); - - done(); - - }; - imageObj.src = 'assets/darth-vader.jpg'; - //imageObj.src = 'assets/lion.png'; - - }); - - // ====================================================== - test('edge detect', function(done) { - var stage = addStage(); - - var imageObj = new Image(); - imageObj.onload = function() { - var layer = new Kinetic.Layer(); - darth = new Kinetic.Image({ - x: 10, - y: 10, - image: imageObj, - draggable: true - }); - - layer.add(darth); - stage.add(layer); - darth.cache(); - darth.filters([Kinetic.Filters.Edge]); - darth.setFilterAmount(100); - layer.draw(); - - var tween = new Kinetic.Tween({ - node: darth, - duration: 0.6, - filterAmount: 0, - easing: Kinetic.Easings.EaseInOut - }); - - darth.on('mouseover', function() { - tween.play(); - }); - - darth.on('mouseout', function() { - tween.reverse(); - }); - - done(); - - }; - //imageObj.src = 'assets/darth-vader.jpg'; - imageObj.src = 'assets/lion.png'; - - }); - - // ====================================================== - test('unsharp mask', function(done) { - var stage = addStage(); - - var imageObj = new Image(); - imageObj.onload = function() { - var layer = new Kinetic.Layer(); - darth = new Kinetic.Image({ - x: 10, - y: 10, - image: imageObj, - draggable: true - }); - - layer.add(darth); - stage.add(layer); - darth.cache(); - darth.filters([Kinetic.Filters.UnsharpMask]); - darth.setFilterAmount(100); - layer.draw(); - - var tween = new Kinetic.Tween({ - node: darth, - duration: 0.6, - filterAmount: 0, - easing: Kinetic.Easings.EaseInOut - }); - - darth.on('mouseover', function() { - tween.play(); - }); - - darth.on('mouseout', function() { - tween.reverse(); - }); - - done(); - - }; - //imageObj.src = 'assets/darth-vader.jpg'; - imageObj.src = 'assets/lion.png'; - - }); - - // ====================================================== - test('soft blur', function(done) { - var stage = addStage(); - - var imageObj = new Image(); - imageObj.onload = function() { - var layer = new Kinetic.Layer(); - darth = new Kinetic.Image({ - x: 10, - y: 10, - image: imageObj, - draggable: true - }); - - layer.add(darth); - stage.add(layer); - darth.cache(); - darth.filters([Kinetic.Filters.SoftBlur]); - darth.setFilterAmount(100); - layer.draw(); - - var tween = new Kinetic.Tween({ - node: darth, - duration: 0.6, - filterAmount: 0, - easing: Kinetic.Easings.EaseInOut - }); - - darth.on('mouseover', function() { - tween.play(); - }); - - darth.on('mouseout', function() { - tween.reverse(); - }); - - done(); - - }; - //imageObj.src = 'assets/darth-vader.jpg'; - imageObj.src = 'assets/lion.png'; - - }); - -}); \ No newline at end of file diff --git a/test/unit/filters/Emboss-test.js b/test/unit/filters/Emboss-test.js new file mode 100644 index 00000000..12d66b45 --- /dev/null +++ b/test/unit/filters/Emboss-test.js @@ -0,0 +1,96 @@ +suite('Emboss', function() { + + // ====================================================== + test('basic emboss', function(done) { + var stage = addStage(); + + var imageObj = new Image(); + imageObj.onload = function() { + var layer = new Kinetic.Layer(); + darth = new Kinetic.Image({ + x: 10, + y: 10, + image: imageObj, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + darth.cache(); + darth.filters([Kinetic.Filters.Emboss]); + darth.embossStrength(0.5); + darth.embossWhiteLevel(0.8); + darth.embossDirection('top-right'); + + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 0.6, + embossStrength: 10, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + //imageObj.src = 'assets/lion.png'; + + }); + + // ====================================================== + test('blended emboss', function(done) { + var stage = addStage(); + + var imageObj = new Image(); + imageObj.onload = function() { + var layer = new Kinetic.Layer(); + darth = new Kinetic.Image({ + x: 10, + y: 10, + image: imageObj, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + darth.cache(); + darth.filters([Kinetic.Filters.Emboss]); + darth.embossStrength(0.5); + darth.embossWhiteLevel(0.2); + darth.embossBlend(true); + + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 0.6, + embossStrength: 10, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + //imageObj.src = 'assets/lion.png'; + + }); +}); \ No newline at end of file