diff --git a/src/filters/ColorPack.js b/src/filters/ColorPack.js index 6c18f43f..ae5c2dff 100644 --- a/src/filters/ColorPack.js +++ b/src/filters/ColorPack.js @@ -70,7 +70,69 @@ }; - Kinetic.Filters.HSV = Kinetic.Util._FilterWrapSingleBuffer(HSV); + Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterHue', 0); + Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterSaturation', 1); + Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterValue', 1); + + Kinetic.Filters.HSV = function(src,dst,opt){ + if( this === Kinetic.Filters ){ + HSV(src, dst||src, opt ); + }else{ + HSV.call(this, src, dst||src, opt || { + hue: this.getFilterHue(), + saturation: this.getFilterSaturation(), + value: this.getFilterValue() + }); + } + }; + + /** + * get filter hue. Returns the hue shift for the HSV filter. + * 0 is no change, 359 is the maximum shift. + * @name getFilterHue + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * set filter hue. Sets the hue shift for the HSV filter. + * 0 is no change, 359 is the maximum shift. + * @name setFilterHue + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * get filter saturation. Returns the saturation scale for the HSV + * filter. 1 is no change, 0.5 halves the saturation, 2.0 doubles, etc.. + * @name getFilterSaturation + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * set filter saturation. Set the saturation scale for the HSV + * filter. 1 is no change, 0.5 halves the saturation, 2.0 doubles, etc.. + * @name setFilterSaturation + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * get filter value. Returns the value scale for the HSV + * filter. 1 is no change, 0.5 halves the value, 2.0 doubles, etc.. + * @name getFilterValue + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * set filter value. Set the value scale for the HSV + * filter. 1 is no change, 0.5 halves the value, 2.0 doubles, etc.. + * @name setFilterValue + * @method + * @memberof Kinetic.Image.prototype + */ })(); diff --git a/src/filters/ColorStretch.js b/src/filters/ColorStretch.js index d171290d..3b45cc27 100644 --- a/src/filters/ColorStretch.js +++ b/src/filters/ColorStretch.js @@ -90,6 +90,12 @@ }; - Kinetic.Filters.ColorStretch = Kinetic.Util._FilterWrapSingleBuffer(ColorStretch); + Kinetic.Filters.ColorStretch = function(src,dst,opt){ + if( this === Kinetic.Filters ){ + ColorStretch(src, dst||src, opt ); + }else{ + ColorStretch.call(this, src, dst||src, opt); + } + }; })(); diff --git a/src/filters/Flip.js b/src/filters/Flip.js index aad863fb..8ba6adf8 100644 --- a/src/filters/Flip.js +++ b/src/filters/Flip.js @@ -16,16 +16,27 @@ var srcPixels = src.data, dstPixels = dst.data, xSize = src.width, + xEnd = Math.ceil(0.5*xSize), ySize = src.height, - i, m, x, y; - for (x = 0; x < xSize; x += 1) { + i, m, x, y, r,g,b,a; + for (x = 0; x < xEnd; x += 1) { for (y = 0; y < ySize; y += 1) { i = (y * xSize + x) * 4; // original m = (y * xSize + (xSize-1) - x) * 4; // flipped + // Instead of copying each row from the source to the destiation + // swap rows - this let's us achive a full flip in a single buffer + r = srcPixels[m + 0]; + g = srcPixels[m + 1]; + b = srcPixels[m + 2]; + a = srcPixels[m + 3]; dstPixels[m + 0] = srcPixels[i + 0]; dstPixels[m + 1] = srcPixels[i + 1]; dstPixels[m + 2] = srcPixels[i + 2]; dstPixels[m + 3] = srcPixels[i + 3]; + dstPixels[i + 0] = r; + dstPixels[i + 1] = g; + dstPixels[i + 2] = b; + dstPixels[i + 3] = a; } } }; @@ -47,19 +58,44 @@ dstPixels = dst.data, xSize = src.width, ySize = src.height, - i, m, x, y; + yEnd = Math.ceil(0.5*ySize), + i, m, x, y, r,g,b,a; for (x = 0; x < xSize; x += 1) { - for (y = 0; y < ySize; y += 1) { + for (y = 0; y < yEnd; y += 1) { i = (y * xSize + x) * 4; // original m = ((ySize-1 - y) * xSize + x) * 4; // flipped + // Instead of copying each row from the source to the destiation + // swap rows - this let's us achive a full flip in a single buffer + r = srcPixels[m + 0]; + g = srcPixels[m + 1]; + b = srcPixels[m + 2]; + a = srcPixels[m + 3]; dstPixels[m + 0] = srcPixels[i + 0]; dstPixels[m + 1] = srcPixels[i + 1]; dstPixels[m + 2] = srcPixels[i + 2]; dstPixels[m + 3] = srcPixels[i + 3]; + dstPixels[i + 0] = r; + dstPixels[i + 1] = g; + dstPixels[i + 2] = b; + dstPixels[i + 3] = a; } } }; - Kinetic.Filters.FlipX = Kinetic.Util._FilterWrapSingleBuffer(FlipX); - Kinetic.Filters.FlipY = Kinetic.Util._FilterWrapSingleBuffer(FlipY); + Kinetic.Filters.FlipX = function(src,dst,opt){ + if( this === Kinetic.Filters ){ + FlipX(src, dst||src, opt ); + }else{ + FlipX.call(this, src, dst||src, opt); + } + }; + + Kinetic.Filters.FlipY = function(src,dst,opt){ + if( this === Kinetic.Filters ){ + FlipY(src, dst||src, opt ); + }else{ + FlipY.call(this, src, dst||src, opt); + } + }; + })(); diff --git a/src/filters/Levels.js b/src/filters/Levels.js index 0ab28b24..2a41beb7 100644 --- a/src/filters/Levels.js +++ b/src/filters/Levels.js @@ -16,7 +16,7 @@ */ var Levels = function (src, dst, opt) { - var nLevels = opt.quantizationLevels || 2; + var nLevels = Math.round(opt.quantizationLevels || 2); var srcPixels = src.data, dstPixels = dst.data, nPixels = srcPixels.length, @@ -27,5 +27,31 @@ } }; - Kinetic.Filters.Levels = Kinetic.Util._FilterWrapSingleBuffer(Levels); + Kinetic.Filters.Levels = function(src,dst,opt){ + if( this === Kinetic.Filters ){ + Levels(src, dst||src, opt ); + }else{ + Levels.call(this, src, dst||src, { + quantizationLevels: this.getQuantizationLevels() + }); + } + }; + + Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'quantizationLevels', 4); + + /** + * get quantization levels. Returns the number of unique levels for each color + * channel. 2 is the minimum, 255 is the maximum. For Kinetic.Filters.Levels + * @name getQuantizationLevels + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * get quantization levels. Sets the number of unique levels for each color + * channel. 2 is the minimum, 255 is the maximum. For Kinetic.Filters.Levels + * @name setQuantizationLevels + * @method + * @memberof Kinetic.Image.prototype + */ })(); \ No newline at end of file diff --git a/src/filters/Mirror.js b/src/filters/Mirror.js index 04945ee7..2de1fd88 100644 --- a/src/filters/Mirror.js +++ b/src/filters/Mirror.js @@ -73,7 +73,20 @@ } }; - Kinetic.Filters.MirrorX = Kinetic.Util._FilterWrapSingleBuffer(MirrorX); - Kinetic.Filters.MirrorY = Kinetic.Util._FilterWrapSingleBuffer(MirrorY); + Kinetic.Filters.MirrorX = function(src,dst,opt){ + if( this === Kinetic.Filters ){ + MirrorX(src, dst||src, opt ); + }else{ + MirrorX.call(this, src, dst||src, opt); + } + }; + + Kinetic.Filters.MirrorY = function(src,dst,opt){ + if( this === Kinetic.Filters ){ + MirrorY(src, dst||src, opt ); + }else{ + MirrorY.call(this, src, dst||src, opt); + } + }; })(); diff --git a/src/filters/Noise.js b/src/filters/Noise.js index ed8082ef..6bdaa194 100644 --- a/src/filters/Noise.js +++ b/src/filters/Noise.js @@ -11,12 +11,12 @@ * @param {Object} opt * @param {Number} [opt.noiseAmount] The amount of noise to add. Between 0 and 255. * Each channel of each pixel will change by a random amount - * between +- amount/2. Default is 32. + * between +- amount/2. Default is 0. * @param {Number} [opt.affectAlpha] 1 to add noise to the alpha channel. * Default is 0. */ var Noise = function (src, dst, opt) { - var amount = opt.noiseAmount || 32, + var amount = opt.noiseAmount || 0, affectAlpha = opt.affectAlpha || 0; var srcPixels = src.data, dstPixels = dst.data, @@ -40,5 +40,30 @@ } }; - Kinetic.Filters.Noise = Kinetic.Util._FilterWrapSingleBuffer(Noise); + Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'noiseAmount', 32); + + Kinetic.Filters.Noise = function(src,dst,opt){ + if( this === Kinetic.Filters ){ + Noise(src, dst||src, opt ); + }else{ + Noise.call(this, src, dst||src, opt || { + noiseAmount: this.getNoiseAmount() + }); + } + }; + + /** + * get noise amount. Returns the amount of noise. Between 0 and 255. + * @name getNoiseAmount + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * set noise amount. Sets the amount of noise. Between 0 and 255. + * @name setNoiseAmount + * @method + * @memberof Kinetic.Image.prototype + */ + })(); diff --git a/src/filters/Threshold.js b/src/filters/Threshold.js index 72b6bb41..9b60a766 100644 --- a/src/filters/Threshold.js +++ b/src/filters/Threshold.js @@ -16,7 +16,10 @@ */ var Threshold = function (src, dst, opt) { - var level = opt.thresholdLevel || 128; + var level = 128; + if( opt.hasOwnProperty ){ + level = opt.thresholdLevel; + } var srcPixels = src.data, dstPixels = dst.data, nPixels = srcPixels.length, @@ -30,5 +33,29 @@ } }; - Kinetic.Filters.Threshold = Kinetic.Util._FilterWrapSingleBuffer(Threshold); + Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'thresholdLevel', 128); + + Kinetic.Filters.Threshold = function(src,dst,opt){ + if( this === Kinetic.Filters ){ + Threshold(src, dst||src, opt ); + }else{ + Threshold.call(this, src, dst||src, opt || { + thresholdLevel: this.getThresholdLevel() + }); + } + }; + + /** + * get threshold level. Returns the level which divides the color channel (0-255). + * @name getThresholdLevel + * @method + * @memberof Kinetic.Image.prototype + */ + + /** + * set threshold level. Sets the level which divides the color channel (0-255). + * @name setThresholdLevel + * @method + * @memberof Kinetic.Image.prototype + */ })(); \ No newline at end of file diff --git a/src/plugins/Path.js b/src/plugins/Path.js index c9186098..a0f7db48 100644 --- a/src/plugins/Path.js +++ b/src/plugins/Path.js @@ -295,21 +295,21 @@ // Note: lineTo handlers need to be above this point case 'm': - var dx = p.shift(); - var dy = p.shift(); + var dx = p.shift(); + var dy = p.shift(); cpx += dx; cpy += dy; cmd = 'M'; // After closing the path move the current position // to the the first point of the path (if any). if(ca.length>2 && ca[ca.length-1].command==='z'){ - for(var idx=ca.length-2;idx>=0;idx--){ - if(ca[idx].command==='M'){ - cpx=ca[idx].points[0]+dx; - cpy=ca[idx].points[1]+dy; - break; - } - } + for(var idx=ca.length-2;idx>=0;idx--){ + if(ca[idx].command==='M'){ + cpx=ca[idx].points[0]+dx; + cpy=ca[idx].points[1]+dy; + break; + } + } } points.push(cpx, cpy); c = 'l'; diff --git a/test/unit/filters/ColorPack-test.js b/test/unit/filters/ColorPack-test.js index 3bd1243c..d1052b56 100644 --- a/test/unit/filters/ColorPack-test.js +++ b/test/unit/filters/ColorPack-test.js @@ -108,14 +108,100 @@ suite('Color Pack', function() { layer.add(darth); stage.add(layer); - darth.setFilter(Kinetic.Filters.ShiftHue); - darth.setFilterHueShiftDeg(360); + darth.setFilter(Kinetic.Filters.HSV); + darth.setFilterHue(360); layer.draw(); var tween = new Kinetic.Tween({ node: darth, duration: 5.0, - filterHueShiftDeg: 0, + filterHue: 0, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + }; + imageObj.src = 'assets/lion.png'; + + }); + + // ====================================================== + test('saturation tween transparancy', 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.setFilter(Kinetic.Filters.HSV); + darth.setFilterSaturation(2.0); + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 5.0, + filterSaturation: 0.001, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + }; + imageObj.src = 'assets/lion.png'; + + }); + + // ====================================================== + test('value tween transparancy', 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.setFilter(Kinetic.Filters.HSV); + darth.setFilterValue(2.0); + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 5.0, + filterValue: 0.001, easing: Kinetic.Easings.EaseInOut }); @@ -279,4 +365,77 @@ suite('Color Pack', function() { done(); }); + // ====================================================== + test('value gradient', function (done) { + var stage = addStage(); + + var shapesLayer = new Kinetic.Layer(); + + // The important line! + shapesLayer.on('draw', function () { + var src, dst, i, w=40; + var ctx = this.getContext(); + var ctxWidth = this.getCanvas().width; + var ctxHeight = this.getCanvas().height; + var xSize = Math.floor(ctxWidth/w); + var ySize = Math.floor(ctxHeight); + for( i=0; i