From 1d375fb71187f6625e3cafb331344c44869c6324 Mon Sep 17 00:00:00 2001 From: ippo615 Date: Thu, 11 Jul 2013 19:47:33 -0400 Subject: [PATCH 1/7] Fixed JS Hint errors --- src/Container.js | 2 +- src/filters/Blur.js | 5 +++-- src/filters/Mask.js | 16 ++++++++-------- src/plugins/Label.js | 10 ++++++---- src/plugins/Path.js | 30 +++++++++++++++++------------- 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/Container.js b/src/Container.js index 732fb35e..e61af59d 100644 --- a/src/Container.js +++ b/src/Container.js @@ -30,7 +30,7 @@ child; while(children.length > 0) { - var child = children[0]; + child = children[0]; if (child.hasChildren()) { child.removeChildren(); } diff --git a/src/filters/Blur.js b/src/filters/Blur.js index 1a5fcf89..a68ba61d 100644 --- a/src/filters/Blur.js +++ b/src/filters/Blur.js @@ -105,6 +105,7 @@ radiusPlus1 = radius + 1, sumFactor = radiusPlus1 * ( radiusPlus1 + 1 ) / 2, stackStart = new BlurStack(), + stackEnd = null, stack = stackStart, stackIn = null, stackOut = null, @@ -113,7 +114,7 @@ for ( i = 1; i < div; i++ ) { stack = stack.next = new BlurStack(); - if ( i == radiusPlus1 ) var stackEnd = stack; + if ( i == radiusPlus1 ) stackEnd = stack; } stack.next = stackStart; @@ -167,7 +168,7 @@ for ( x = 0; x < width; x++ ) { pixels[yi+3] = pa = (a_sum * mul_sum) >> shg_sum; - if ( pa != 0 ) + if ( pa !== 0 ) { pa = 255 / pa; pixels[yi] = ((r_sum * mul_sum) >> shg_sum) * pa; diff --git a/src/filters/Mask.js b/src/filters/Mask.js index 1a4d78a7..b6bb6dfa 100644 --- a/src/filters/Mask.js +++ b/src/filters/Mask.js @@ -5,11 +5,11 @@ var d = []; d.push(idata.data[idx++], idata.data[idx++], idata.data[idx++], idata.data[idx++]); return d; - }; + } function rgbDistance(p1, p2) { return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2) + Math.pow(p1[2] - p2[2], 2)); - }; + } function rgbMean(pTab) { var m = [0, 0, 0]; @@ -25,7 +25,7 @@ m[2] /= pTab.length; return m; - }; + } function backgroundMask(idata, threshold) { var rgbv_no = pixelAt(idata, 0, 0); @@ -49,13 +49,13 @@ return mask; } - }; + } function applyMask(idata, mask) { for (var i = 0; i < idata.width * idata.height; i++) { idata.data[4 * i + 3] = mask[i]; } - }; + } function erodeMask(mask, sw, sh) { @@ -89,7 +89,7 @@ } return maskResult; - }; + } function dilateMask(mask, sw, sh) { @@ -123,7 +123,7 @@ } return maskResult; - }; + } function smoothEdgeMask(mask, sw, sh) { @@ -171,7 +171,7 @@ Kinetic.Filters.Mask = function(idata) { // Detect pixels close to the background color var threshold = this.getFilterThreshold(), - mask = backgroundMask(idata, threshold); + mask = backgroundMask(idata, threshold); if (mask) { // Erode mask = erodeMask(mask, idata.width, idata.height); diff --git a/src/plugins/Label.js b/src/plugins/Label.js index 0e106956..9bfdcd45 100644 --- a/src/plugins/Label.js +++ b/src/plugins/Label.js @@ -90,11 +90,13 @@ _addListeners: function(context) { var that = this, n; + var func = function(){ + that._sync(); + }; + // update text data for certain attr changes for(n = 0; n < attrChangeListLen; n++) { - context.on(ATTR_CHANGE_LIST[n] + CHANGE_KINETIC, function() { - that._sync(); - }); + context.on(ATTR_CHANGE_LIST[n] + CHANGE_KINETIC, func); } }, getWidth: function() { @@ -292,4 +294,4 @@ * @method * @memberof Kinetic.Tag.prototype */ -})(); \ No newline at end of file +})(); diff --git a/src/plugins/Path.js b/src/plugins/Path.js index a5feb43d..18892444 100644 --- a/src/plugins/Path.js +++ b/src/plugins/Path.js @@ -235,7 +235,7 @@ // init context point var cpx = 0; var cpy = 0; - for(var n = 1; n < arr.length; n++) { + for( n = 1; n < arr.length; n++) { var str = arr[n]; var c = str.charAt(0); str = str.slice(1); @@ -259,6 +259,10 @@ var cmd = null; var points = []; var startX = cpx, startY = cpy; + // Move var from within the switch to up here (jshint) + var prevCmd, ctlPtx, ctlPty; // Ss, Tt + var rx, ry, psi, fa, fs, x1, y1; // Aa + // convert l, H, h, V, and v to L switch (c) { @@ -328,8 +332,8 @@ points.push(cpx, cpy); break; case 'S': - var ctlPtx = cpx, ctlPty = cpy; - var prevCmd = ca[ca.length - 1]; + ctlPtx = cpx, ctlPty = cpy; + prevCmd = ca[ca.length - 1]; if(prevCmd.command === 'C') { ctlPtx = cpx + (cpx - prevCmd.points[2]); ctlPty = cpy + (cpy - prevCmd.points[3]); @@ -341,8 +345,8 @@ points.push(cpx, cpy); break; case 's': - var ctlPtx = cpx, ctlPty = cpy; - var prevCmd = ca[ca.length - 1]; + ctlPtx = cpx, ctlPty = cpy; + prevCmd = ca[ca.length - 1]; if(prevCmd.command === 'C') { ctlPtx = cpx + (cpx - prevCmd.points[2]); ctlPty = cpy + (cpy - prevCmd.points[3]); @@ -367,8 +371,8 @@ points.push(cpx, cpy); break; case 'T': - var ctlPtx = cpx, ctlPty = cpy; - var prevCmd = ca[ca.length - 1]; + ctlPtx = cpx, ctlPty = cpy; + prevCmd = ca[ca.length - 1]; if(prevCmd.command === 'Q') { ctlPtx = cpx + (cpx - prevCmd.points[0]); ctlPty = cpy + (cpy - prevCmd.points[1]); @@ -379,8 +383,8 @@ points.push(ctlPtx, ctlPty, cpx, cpy); break; case 't': - var ctlPtx = cpx, ctlPty = cpy; - var prevCmd = ca[ca.length - 1]; + ctlPtx = cpx, ctlPty = cpy; + prevCmd = ca[ca.length - 1]; if(prevCmd.command === 'Q') { ctlPtx = cpx + (cpx - prevCmd.points[0]); ctlPty = cpy + (cpy - prevCmd.points[1]); @@ -391,14 +395,14 @@ points.push(ctlPtx, ctlPty, cpx, cpy); break; case 'A': - var rx = p.shift(), ry = p.shift(), psi = p.shift(), fa = p.shift(), fs = p.shift(); - var x1 = cpx, y1 = cpy; cpx = p.shift(), cpy = p.shift(); + rx = p.shift(), ry = p.shift(), psi = p.shift(), fa = p.shift(), fs = p.shift(); + x1 = cpx, y1 = cpy; cpx = p.shift(), cpy = p.shift(); cmd = 'A'; points = this.convertEndpointToCenterParameterization(x1, y1, cpx, cpy, fa, fs, rx, ry, psi); break; case 'a': - var rx = p.shift(), ry = p.shift(), psi = p.shift(), fa = p.shift(), fs = p.shift(); - var x1 = cpx, y1 = cpy; cpx += p.shift(), cpy += p.shift(); + rx = p.shift(), ry = p.shift(), psi = p.shift(), fa = p.shift(), fs = p.shift(); + x1 = cpx, y1 = cpy; cpx += p.shift(), cpy += p.shift(); cmd = 'A'; points = this.convertEndpointToCenterParameterization(x1, y1, cpx, cpy, fa, fs, rx, ry, psi); break; From 1ef20456bacd94c3137208b25ded8bcc17f5fa5d Mon Sep 17 00:00:00 2001 From: ippo615 Date: Thu, 11 Jul 2013 21:02:51 -0400 Subject: [PATCH 2/7] Added color filters --- Gruntfile.js | 5 +- src/filters/Colors.js | 163 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 src/filters/Colors.js diff --git a/Gruntfile.js b/Gruntfile.js index 5b1796d2..4b6efb69 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -39,7 +39,8 @@ module.exports = function(grunt) { 'src/filters/Brighten.js', 'src/filters/Invert.js', 'src/filters/Blur.js', - 'src/filters/Mask.js' + 'src/filters/Mask.js', + 'src/filters/Colors.js' ]; var unitTestFiles = [ @@ -163,4 +164,4 @@ module.exports = function(grunt) { grunt.registerTask('full', ['clean', 'concat:source', 'replace:dev', 'uglify', 'replace:prod']); grunt.registerTask('test', ['concat:test']); grunt.registerTask('hint', ['clean', 'concat:source', 'replace:dev', 'jshint']); -}; \ No newline at end of file +}; diff --git a/src/filters/Colors.js b/src/filters/Colors.js new file mode 100644 index 00000000..c88cd95f --- /dev/null +++ b/src/filters/Colors.js @@ -0,0 +1,163 @@ +(function() { + + function pixelShiftHue(r,g,b,deg){ + + // Input colors are in 0-255, calculations are between 0-1 + r /= 255; g /= 255; b /= 255; + + // http://en.wikipedia.org/wiki/HSL_and_HSV + // Convert to HSL + var max = Math.max(r,g,b), + min = Math.min(r,g,b), + chroma = max - min, + luminance = chroma / 2, + saturation = chroma / (1 - Math.abs(2*luminance-1)), + hue = 0; + + if( max == r ){ hue = ((g-b)/chroma) % 6; }else + if( max == g ){ hue = (b-r)/chroma + 2; }else + if( max == b ){ hue = (r-g)/chroma + 4; } + + hue *= 60; + hue %= 360; + + // Shift hue + hue += deg; + hue %= 360; + //hue /= 360; + + // hsl to rgb: + hue /= 60; + var rR = 0, rG = 0, rB = 0, + //chroma = saturation*(1 - Math.abs(2*luminance - 1)), + tmp = chroma * (1-Math.abs(hue % 2 - 1)), + m = luminance - chroma/2; + + if( 0 <= hue && hue < 1 ){ rR = chroma; rG = tmp; }else + if( 1 <= hue && hue < 2 ){ rG = chroma; rR = tmp; }else + if( 2 <= hue && hue < 3 ){ rG = chroma; rB = tmp; }else + if( 3 <= hue && hue < 4 ){ rB = chroma; rG = tmp; }else + if( 4 <= hue && hue < 5 ){ rB = chroma; rR = tmp; }else + if( 5 <= hue && hue < 6 ){ rR = chroma; rB = tmp; } + + rR += m; rG += m; rB += m; + rR = (255*rR); + rG = (255*rG); + rB = (255*rB); + + return [rR,rG,rB]; + } + + /** + * shift hue + * @function + * @memberof Kinetic.Filters + * @param {Object} imageData + */ + Kinetic.Filters.ShiftHue = function(imageData) { + var data = imageData.data, pixel; + for(var i = 0; i < data.length; i += 4) { + pixel = pixelShiftHue(data[i+0],data[i+1],data[i+2],deg); + data[i+0] = pixel[0]; + data[i+1] = pixel[1]; + data[i+2] = pixel[2]; + } + }; + + Kinetic.Node.addFilterGetterSetter(Kinetic.Image, 'filterHueShiftDeg', 0); + /** + * get hue shift amount. The shift amount is a number between 0 and 360. + * @name getFilterBrightness + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * set hue shift amount + * @name setFilterBrightness + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * show only red + * @function + * @memberof Kinetic.Filters + * @param {Object} imageData + */ + Kinetic.Filters.OnlyRed = function(imageData) { + var data = imageData.data; + for(var i = 0; i < data.length; i += 4) { + data[i + 1] = 0; // green + data[i + 2] = 0; // blue + } + }; + + /** + * show only green + * @function + * @memberof Kinetic.Filters + * @param {Object} imageData + */ + Kinetic.Filters.OnlyGreen = function(imageData) { + var data = imageData.data; + for(var i = 0; i < data.length; i += 4) { + data[i + 0] = 0; // red + data[i + 2] = 0; // blue + } + }; + + /** + * show only blue + * @function + * @memberof Kinetic.Filters + * @param {Object} imageData + */ + Kinetic.Filters.OnlyGreen = function(imageData) { + var data = imageData.data; + for(var i = 0; i < data.length; i += 4) { + data[i + 0] = 0; // red + data[i + 1] = 0; // green + } + }; + + /** + * removes all red from an image + * @function + * @memberof Kinetic.Filters + * @param {Object} imageData + */ + Kinetic.Filters.NoRed = function(imageData) { + var data = imageData.data; + for(var i = 0; i < data.length; i += 4) { + data[i + 0] = 0; + } + }; + + /** + * removes all green from an image + * @function + * @memberof Kinetic.Filters + * @param {Object} imageData + */ + Kinetic.Filters.NoGreen = function(imageData) { + var data = imageData.data; + for(var i = 0; i < data.length; i += 4) { + data[i + 1] = 0; + } + }; + + /** + * removes all blue from an image + * @function + * @memberof Kinetic.Filters + * @param {Object} imageData + */ + Kinetic.Filters.NoBlue = function(imageData) { + var data = imageData.data; + for(var i = 0; i < data.length; i += 4) { + data[i + 2] = 0; + } + }; + +})(); From 3c49dc9536b3858032b214df546668f3ea4cad56 Mon Sep 17 00:00:00 2001 From: ippo615 Date: Thu, 11 Jul 2013 21:05:11 -0400 Subject: [PATCH 3/7] Fixed bug in hue shifting --- src/filters/Colors.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/filters/Colors.js b/src/filters/Colors.js index c88cd95f..98882a60 100644 --- a/src/filters/Colors.js +++ b/src/filters/Colors.js @@ -55,7 +55,9 @@ * @param {Object} imageData */ Kinetic.Filters.ShiftHue = function(imageData) { - var data = imageData.data, pixel; + var data = imageData.data, + deg = this.getFilterHueShiftDeg(), + pixel; for(var i = 0; i < data.length; i += 4) { pixel = pixelShiftHue(data[i+0],data[i+1],data[i+2],deg); data[i+0] = pixel[0]; From 66cef11ae9bb1a8fe429e6ab167dbb3b3058df30 Mon Sep 17 00:00:00 2001 From: ippo615 Date: Thu, 11 Jul 2013 21:57:49 -0400 Subject: [PATCH 4/7] Fixed bug in color filters, added visual tests. --- src/filters/Colors.js | 2 +- tests/js/visualTests.js | 190 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+), 1 deletion(-) diff --git a/src/filters/Colors.js b/src/filters/Colors.js index 98882a60..53ee6b52 100644 --- a/src/filters/Colors.js +++ b/src/filters/Colors.js @@ -115,7 +115,7 @@ * @memberof Kinetic.Filters * @param {Object} imageData */ - Kinetic.Filters.OnlyGreen = function(imageData) { + Kinetic.Filters.OnlyBlue = function(imageData) { var data = imageData.data; for(var i = 0; i < data.length; i += 4) { data[i + 0] = 0; // red diff --git a/tests/js/visualTests.js b/tests/js/visualTests.js index 3a9226ef..9d59e575 100644 --- a/tests/js/visualTests.js +++ b/tests/js/visualTests.js @@ -1432,6 +1432,196 @@ Test.Modules.IMAGE = { }; imageObj.src = '../assets/darth-vader.jpg'; }, + 'no red filter': function(containerId) { + var imageObj = new Image(); + imageObj.onload = function() { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + darth = new Kinetic.Image({ + x: 10, + y: 10, + image: imageObj, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.NoRed); + layer.draw(); + var dataUrl = layer.toDataURL(); + //console.log(dataUrl); + testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); + }; + imageObj.src = '../assets/darth-vader.jpg'; + }, + 'no green filter': function(containerId) { + var imageObj = new Image(); + imageObj.onload = function() { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + darth = new Kinetic.Image({ + x: 10, + y: 10, + image: imageObj, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.NoGreen); + layer.draw(); + var dataUrl = layer.toDataURL(); + //console.log(dataUrl); + testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); + }; + imageObj.src = '../assets/darth-vader.jpg'; + }, + 'no blue filter': function(containerId) { + var imageObj = new Image(); + imageObj.onload = function() { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + darth = new Kinetic.Image({ + x: 10, + y: 10, + image: imageObj, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.NoBlue); + layer.draw(); + var dataUrl = layer.toDataURL(); + //console.log(dataUrl); + testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); + }; + imageObj.src = '../assets/darth-vader.jpg'; + }, + 'only red filter': function(containerId) { + var imageObj = new Image(); + imageObj.onload = function() { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + darth = new Kinetic.Image({ + x: 10, + y: 10, + image: imageObj, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.OnlyRed); + layer.draw(); + var dataUrl = layer.toDataURL(); + //console.log(dataUrl); + testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); + }; + imageObj.src = '../assets/darth-vader.jpg'; + }, + 'only green filter': function(containerId) { + var imageObj = new Image(); + imageObj.onload = function() { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + darth = new Kinetic.Image({ + x: 10, + y: 10, + image: imageObj, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.OnlyGreen); + layer.draw(); + var dataUrl = layer.toDataURL(); + //console.log(dataUrl); + testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); + }; + imageObj.src = '../assets/darth-vader.jpg'; + }, + 'only blue filter': function(containerId) { + var imageObj = new Image(); + imageObj.onload = function() { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + darth = new Kinetic.Image({ + x: 10, + y: 10, + image: imageObj, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.OnlyBlue); + layer.draw(); + var dataUrl = layer.toDataURL(); + //console.log(dataUrl); + testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); + }; + imageObj.src = '../assets/darth-vader.jpg'; + }, + 'shift hue filter': function(containerId) { + var imageObj = new Image(); + imageObj.onload = function() { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + darth = new Kinetic.Image({ + x: 10, + y: 10, + image: imageObj, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.ShiftHue); + darth.setFilterHueShiftDeg(90); + layer.draw(); + var dataUrl = layer.toDataURL(); + //console.log(dataUrl); + testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); + }; + imageObj.src = '../assets/lion.png'; + }, 'filter transformed image': function(containerId) { var imageObj = new Image(); imageObj.onload = function() { From f640d19042694e433c8f8e0a2bf7ac071df71c8f Mon Sep 17 00:00:00 2001 From: ippo615 Date: Sun, 14 Jul 2013 22:20:45 -0400 Subject: [PATCH 5/7] Working on convolution based filters --- Gruntfile.js | 3 +- src/filters/Convolution.js | 389 +++++++++++++++++++++++++++++++++++++ tests/js/visualTests.js | 43 ++++ 3 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 src/filters/Convolution.js diff --git a/Gruntfile.js b/Gruntfile.js index 4b6efb69..52441e53 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -40,7 +40,8 @@ module.exports = function(grunt) { 'src/filters/Invert.js', 'src/filters/Blur.js', 'src/filters/Mask.js', - 'src/filters/Colors.js' + 'src/filters/Colors.js', + 'src/filters/Convolution.js' ]; var unitTestFiles = [ diff --git a/src/filters/Convolution.js b/src/filters/Convolution.js new file mode 100644 index 00000000..23d54e80 --- /dev/null +++ b/src/filters/Convolution.js @@ -0,0 +1,389 @@ +(function() { + + var convolve_internal = function(imageData,matrix){ + // Input data + var pixels = imageData.data, + imageSizeX = imageData.width, + imageSizeY = imageData.height, + nPixels = imageSizeX*imageSizeY, + pixel; + + // An array for storing the result + var result = []; + result.length = imageSizeX*imageSizeY*4; + + // Determine the size and demsionality of the matrix + // Note: it should be square and odd (3,5,7,9 etc...) + var is2D = (matrix[0].length > 0) || 0, + matrixSizeX = matrix.length, + matrixSizeY = matrix.length; + + // Make sure we don't try to access pixels outside the image + var xMax = Math.floor(imageSizeX - matrixSizeX/2), + xMin = Math.floor(matrixSizeX/2), + yMax = Math.floor(imageSizeY - matrixSizeY/2), + yMin = Math.floor(matrixSizeY/2); + + // Accumlators and positions for iterating + var r,g,b,a, x, y, pos, i,j; + + if( is2D ){ + for( y=yMin; y Date: Mon, 15 Jul 2013 20:09:36 -0400 Subject: [PATCH 6/7] Improved 'colorizing' - now any color --- src/filters/Colors.js | 139 ++++++++++++++++---------------------- tests/js/visualTests.js | 144 ++-------------------------------------- 2 files changed, 63 insertions(+), 220 deletions(-) diff --git a/src/filters/Colors.js b/src/filters/Colors.js index 53ee6b52..abf46a31 100644 --- a/src/filters/Colors.js +++ b/src/filters/Colors.js @@ -1,6 +1,26 @@ (function() { - function pixelShiftHue(r,g,b,deg){ + var rgb_to_hsl = function(r,g,b){ + // Input colors are in 0-255, calculations are between 0-1 + r /= 255; g /= 255; b /= 255; + + // http://en.wikipedia.org/wiki/HSL_and_HSV + // Convert to HSL + var max = Math.max(r,g,b), + min = Math.min(r,g,b), + chroma = max - min, + luminance = chroma / 2, + saturation = chroma / (1 - Math.abs(2*luminance-1)), + hue = 0; + + if( max == r ){ hue = ((g-b)/chroma) % 6; }else + if( max == g ){ hue = (b-r)/chroma + 2; }else + if( max == b ){ hue = (r-g)/chroma + 4; } + + return [(hue*60+360) % 360, saturation, luminance]; + }; + + var pixelShiftHue = function(r,g,b,deg){ // Input colors are in 0-255, calculations are between 0-1 r /= 255; g /= 255; b /= 255; @@ -46,7 +66,18 @@ rB = (255*rB); return [rR,rG,rB]; - } + }; + + var shift_hue = function(imageData,deg){ + var data = imageData.data, + pixel; + for(var i = 0; i < data.length; i += 4) { + pixel = pixelShiftHue(data[i+0],data[i+1],data[i+2],deg); + data[i+0] = pixel[0]; + data[i+1] = pixel[1]; + data[i+2] = pixel[2]; + } + }; /** * shift hue @@ -55,15 +86,7 @@ * @param {Object} imageData */ Kinetic.Filters.ShiftHue = function(imageData) { - var data = imageData.data, - deg = this.getFilterHueShiftDeg(), - pixel; - for(var i = 0; i < data.length; i += 4) { - pixel = pixelShiftHue(data[i+0],data[i+1],data[i+2],deg); - data[i+0] = pixel[0]; - data[i+1] = pixel[1]; - data[i+2] = pixel[2]; - } + shift_hue(imageData,this.getFilterHueShiftDeg()); }; Kinetic.Node.addFilterGetterSetter(Kinetic.Image, 'filterHueShiftDeg', 0); @@ -81,85 +104,39 @@ * @memberof Kinetic.Image.prototype */ - /** - * show only red - * @function - * @memberof Kinetic.Filters - * @param {Object} imageData - */ - Kinetic.Filters.OnlyRed = function(imageData) { - var data = imageData.data; - for(var i = 0; i < data.length; i += 4) { - data[i + 1] = 0; // green - data[i + 2] = 0; // blue - } - }; - /** - * show only green - * @function - * @memberof Kinetic.Filters - * @param {Object} imageData - */ - Kinetic.Filters.OnlyGreen = function(imageData) { - var data = imageData.data; - for(var i = 0; i < data.length; i += 4) { - data[i + 0] = 0; // red - data[i + 2] = 0; // blue - } - }; - /** - * show only blue - * @function - * @memberof Kinetic.Filters - * @param {Object} imageData - */ - Kinetic.Filters.OnlyBlue = function(imageData) { + Kinetic.Filters.Colorize = function(imageData) { var data = imageData.data; - for(var i = 0; i < data.length; i += 4) { - data[i + 0] = 0; // red - data[i + 1] = 0; // green - } - }; - /** - * removes all red from an image - * @function - * @memberof Kinetic.Filters - * @param {Object} imageData - */ - Kinetic.Filters.NoRed = function(imageData) { - var data = imageData.data; - for(var i = 0; i < data.length; i += 4) { - data[i + 0] = 0; - } - }; + // First we'll colorize it red, then shift by the hue specified + var color = this.getFilterColorizeColor(), + hsl = rgb_to_hsl(color[0],color[1],color[2]), + hue = hsl[0]; - /** - * removes all green from an image - * @function - * @memberof Kinetic.Filters - * @param {Object} imageData - */ - Kinetic.Filters.NoGreen = function(imageData) { - var data = imageData.data; + // Color it red for(var i = 0; i < data.length; i += 4) { data[i + 1] = 0; - } - }; - - /** - * removes all blue from an image - * @function - * @memberof Kinetic.Filters - * @param {Object} imageData - */ - Kinetic.Filters.NoBlue = function(imageData) { - var data = imageData.data; - for(var i = 0; i < data.length; i += 4) { data[i + 2] = 0; } + + // Shift by the hue + shift_hue(imageData,hue); }; + Kinetic.Node.addFilterGetterSetter(Kinetic.Image, 'filterColorizeColor', [255,0,0] ); + /** + * Gets the colorizing color. + * @name getFilterColorizeColor + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * Gets the colorizing color. Should be an array [r,g,b] ie [255,0,128]. + * @name setFilterColorizeColor + * @method + * @memberof Kinetic.Image.prototype + */ + })(); diff --git a/tests/js/visualTests.js b/tests/js/visualTests.js index a8527ac6..27f41007 100644 --- a/tests/js/visualTests.js +++ b/tests/js/visualTests.js @@ -1432,7 +1432,7 @@ Test.Modules.IMAGE = { }; imageObj.src = '../assets/darth-vader.jpg'; }, - 'no red filter': function(containerId) { + 'colorizing filter': function(containerId) { var imageObj = new Image(); imageObj.onload = function() { var stage = new Kinetic.Stage({ @@ -1451,146 +1451,12 @@ Test.Modules.IMAGE = { layer.add(darth); stage.add(layer); - darth.setFilter(Kinetic.Filters.NoRed); + darth.setFilter(Kinetic.Filters.Colorize); + darth.setFilterColorizeColor([255,0,128]); layer.draw(); var dataUrl = layer.toDataURL(); //console.log(dataUrl); - testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); - }; - imageObj.src = '../assets/darth-vader.jpg'; - }, - 'no green filter': function(containerId) { - var imageObj = new Image(); - imageObj.onload = function() { - var stage = new Kinetic.Stage({ - container: containerId, - width: 578, - height: 200 - }); - var layer = new Kinetic.Layer(); - darth = new Kinetic.Image({ - x: 10, - y: 10, - image: imageObj, - draggable: true - }); - - layer.add(darth); - stage.add(layer); - - darth.setFilter(Kinetic.Filters.NoGreen); - layer.draw(); - var dataUrl = layer.toDataURL(); - //console.log(dataUrl); - testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); - }; - imageObj.src = '../assets/darth-vader.jpg'; - }, - 'no blue filter': function(containerId) { - var imageObj = new Image(); - imageObj.onload = function() { - var stage = new Kinetic.Stage({ - container: containerId, - width: 578, - height: 200 - }); - var layer = new Kinetic.Layer(); - darth = new Kinetic.Image({ - x: 10, - y: 10, - image: imageObj, - draggable: true - }); - - layer.add(darth); - stage.add(layer); - - darth.setFilter(Kinetic.Filters.NoBlue); - layer.draw(); - var dataUrl = layer.toDataURL(); - //console.log(dataUrl); - testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); - }; - imageObj.src = '../assets/darth-vader.jpg'; - }, - 'only red filter': function(containerId) { - var imageObj = new Image(); - imageObj.onload = function() { - var stage = new Kinetic.Stage({ - container: containerId, - width: 578, - height: 200 - }); - var layer = new Kinetic.Layer(); - darth = new Kinetic.Image({ - x: 10, - y: 10, - image: imageObj, - draggable: true - }); - - layer.add(darth); - stage.add(layer); - - darth.setFilter(Kinetic.Filters.OnlyRed); - layer.draw(); - var dataUrl = layer.toDataURL(); - //console.log(dataUrl); - testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); - }; - imageObj.src = '../assets/darth-vader.jpg'; - }, - 'only green filter': function(containerId) { - var imageObj = new Image(); - imageObj.onload = function() { - var stage = new Kinetic.Stage({ - container: containerId, - width: 578, - height: 200 - }); - var layer = new Kinetic.Layer(); - darth = new Kinetic.Image({ - x: 10, - y: 10, - image: imageObj, - draggable: true - }); - - layer.add(darth); - stage.add(layer); - - darth.setFilter(Kinetic.Filters.OnlyGreen); - layer.draw(); - var dataUrl = layer.toDataURL(); - //console.log(dataUrl); - testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); - }; - imageObj.src = '../assets/darth-vader.jpg'; - }, - 'only blue filter': function(containerId) { - var imageObj = new Image(); - imageObj.onload = function() { - var stage = new Kinetic.Stage({ - container: containerId, - width: 578, - height: 200 - }); - var layer = new Kinetic.Layer(); - darth = new Kinetic.Image({ - x: 10, - y: 10, - image: imageObj, - draggable: true - }); - - layer.add(darth); - stage.add(layer); - - darth.setFilter(Kinetic.Filters.OnlyBlue); - layer.draw(); - var dataUrl = layer.toDataURL(); - //console.log(dataUrl); - testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); + testDataUrl(dataUrl, 'colorizing filter', 'problem with colorizing filter.'); }; imageObj.src = '../assets/darth-vader.jpg'; }, @@ -1618,7 +1484,7 @@ Test.Modules.IMAGE = { layer.draw(); var dataUrl = layer.toDataURL(); //console.log(dataUrl); - testDataUrl(dataUrl, 'blur filter', 'problem with Blur filter.'); + testDataUrl(dataUrl, 'shift hue filter', 'problem with hue shifting filter.'); }; imageObj.src = '../assets/lion.png'; }, From 9ca025d35f93515c1849e311e10f6bd4cddef4ad Mon Sep 17 00:00:00 2001 From: ippo615 Date: Mon, 15 Jul 2013 20:45:34 -0400 Subject: [PATCH 7/7] Cleaned js, added tests for all convolution filters --- src/filters/Colors.js | 8 +- src/filters/Convolution.js | 84 ++++++++------- tests/js/visualTests.js | 215 ++++++++++++++++++++++++++++++++++--- 3 files changed, 249 insertions(+), 58 deletions(-) diff --git a/src/filters/Colors.js b/src/filters/Colors.js index abf46a31..cec8992b 100644 --- a/src/filters/Colors.js +++ b/src/filters/Colors.js @@ -105,7 +105,12 @@ */ - + /** + * colorizes the image so that it is just varying shades of the specified color + * @function + * @memberof Kinetic.Filters + * @param {Object} imageData + */ Kinetic.Filters.Colorize = function(imageData) { var data = imageData.data; @@ -134,6 +139,7 @@ /** * Gets the colorizing color. Should be an array [r,g,b] ie [255,0,128]. + * note that white [255,255,255] black [0,0,0] and greys [r,r,r] get treated as red. * @name setFilterColorizeColor * @method * @memberof Kinetic.Image.prototype diff --git a/src/filters/Convolution.js b/src/filters/Convolution.js index 23d54e80..92af8566 100644 --- a/src/filters/Convolution.js +++ b/src/filters/Convolution.js @@ -27,6 +27,7 @@ // Accumlators and positions for iterating var r,g,b,a, x, y, pos, i,j; + // Handle the 2D matrix if( is2D ){ for( y=yMin; y