diff --git a/src/shapes/Image.js b/src/shapes/Image.js index bec26df8..55653a0b 100644 --- a/src/shapes/Image.js +++ b/src/shapes/Image.js @@ -44,14 +44,11 @@ return (this.hasShadow() || this.getAbsoluteOpacity() !== 1) && this.hasStroke(); }, drawFunc: function(context) { - var width = this.getWidth(), - height = this.getHeight(), - params, - that = this, - cropX = this.getCropX() || 0, - cropY = this.getCropY() || 0, - cropWidth = this.getCropWidth(), - cropHeight = this.getCropHeight(), + var width = this.getWidth(), + height = this.getHeight(), + that = this, + crop, + params, image; //TODO: this logic needs to hook int othe new caching system @@ -63,11 +60,26 @@ } // NOTE: this.filterCanvas may be set by the above code block + // In that case, cropping is already applied. if (this.filterCanvas) { image = this.filterCanvas._canvas; + params = [image, 0, 0, width, height]; } else { image = this.getImage(); + + if (image) { + crop = this.getCrop(); + if (crop) { + crop.x = crop.x || 0; + crop.y = crop.y || 0; + crop.width = crop.width || image.width - crop.x; + crop.height = crop.height || image.height - crop.y; + params = [image, crop.x, crop.y, crop.width, crop.height, 0, 0, width, height]; + } else { + params = [image, 0, 0, width, height]; + } + } } context.beginPath(); @@ -75,22 +87,13 @@ context.closePath(); context.fillStrokeShape(this); - if(image) { - // if cropping - if(cropWidth && cropHeight) { - params = [image, cropX, cropY, cropWidth, cropHeight, 0, 0, width, height]; - } - // no cropping - else { - params = [image, 0, 0, width, height]; - } - + if (image) { context.drawImage.apply(context, params); } }, drawHitFunc: function(context) { - var width = this.getWidth(), - height = this.getHeight(), + var width = this.getWidth(), + height = this.getHeight(), imageHitRegion = this.imageHitRegion; if(imageHitRegion) { @@ -113,25 +116,37 @@ width = this.getWidth(), height = this.getHeight(), filter = this.getFilter(), + crop = this.getCrop() || {}, filterCanvas, context, imageData; - if (this.filterCanvas){ + // Determine the region we are cropping + crop.x = crop.x || 0; + crop.y = crop.y || 0; + crop.width = crop.width || image.width - crop.x; + crop.height = crop.height || image.height - crop.y; + + // Make a filterCanvas the same size as the cropped image + if (this.filterCanvas && + this.filterCanvas.getWidth() === crop.width && + this.filterCanvas.getHeight() === crop.height) { filterCanvas = this.filterCanvas; filterCanvas.getContext().clear(); } else { filterCanvas = this.filterCanvas = new Kinetic.SceneCanvas({ - width: width, - height: height, - pixelRatio: 1 + width: crop.width, + height: crop.height, + pixelRatio: 1, }); } context = filterCanvas.getContext(); try { - context.drawImage(image, 0, 0, filterCanvas.getWidth(), filterCanvas.getHeight()); - imageData = context.getImageData(0, 0, filterCanvas.getWidth(), filterCanvas.getHeight()); + // Crop the image onto the filterCanvas then apply + // the filter to the filterCanvas + context.drawImage(image, crop.x, crop.y, crop.width, crop.height, 0,0,crop.width, crop.height); + imageData = context.getImageData(0, 0, crop.width, crop.height); filter.call(this, imageData); context.putImageData(imageData, 0, 0); } diff --git a/test/runner.html b/test/runner.html index dd2c43db..e4d86878 100644 --- a/test/runner.html +++ b/test/runner.html @@ -74,6 +74,15 @@ + + + + + + + + + diff --git a/test/unit/filters/Blur-test.js b/test/unit/filters/Blur-test.js new file mode 100644 index 00000000..ce943c1d --- /dev/null +++ b/test/unit/filters/Blur-test.js @@ -0,0 +1,191 @@ +suite('Blur', function() { + // ====================================================== + test('basic 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.setFilter(Kinetic.Filters.Blur); + darth.setFilterRadius(10); + layer.draw(); + + assert.equal(darth.getFilterRadius(), 10); + + done(); + }; + imageObj.src = 'assets/darth-vader.jpg'; + + }); + + // ====================================================== + test('tween 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.setFilter(Kinetic.Filters.Blur); + darth.setFilterRadius(100); + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 2.0, + filterRadius: 0, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + }); + + // ====================================================== + test('crop 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, + crop: {x:128, y:48, width:256, height:128}, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.Blur); + darth.setFilterRadius(10); + layer.draw(); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + }); + + // ====================================================== + test('crop tween 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, + crop: {x:128, y:48, width:256, height:128}, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.Blur); + darth.setFilterRadius(100); + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 2.0, + filterRadius: 0, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + }); + + // ====================================================== + test('transparency', 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.Blur); + darth.setFilterRadius(100); + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 2.0, + filterRadius: 0, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + + }; + imageObj.src = 'assets/lion.png'; + }); + +}); \ No newline at end of file diff --git a/test/unit/filters/Brighten-test.js b/test/unit/filters/Brighten-test.js new file mode 100644 index 00000000..b56184ce --- /dev/null +++ b/test/unit/filters/Brighten-test.js @@ -0,0 +1,150 @@ +suite('Brighten', function() { + // ====================================================== + test('basic', 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.Brighten); + darth.setFilterBrightness(100); + layer.draw(); + + assert.equal(darth.getFilterBrightness(), 100); + + done(); + }; + imageObj.src = 'assets/darth-vader.jpg'; + + }); + + // ====================================================== + test('tween', 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.Brighten); + darth.setFilterBrightness(100); + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 2.0, + filterBrightness: 0, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + }); + + // ====================================================== + test('crop', 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, + crop: {x:128, y:48, width:256, height:128}, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.Brighten); + darth.setFilterBrightness(-50); + layer.draw(); + + assert.equal(darth.getFilterBrightness(), -50); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + }); + + // ====================================================== + test('tween transparency', 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.Brighten); + darth.setFilterBrightness(100); + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 2.0, + filterBrightness: -100, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + + }; + imageObj.src = 'assets/lion.png'; + }); + + +}); \ No newline at end of file diff --git a/test/unit/filters/ColorPack-test.js b/test/unit/filters/ColorPack-test.js new file mode 100644 index 00000000..f1c580ad --- /dev/null +++ b/test/unit/filters/ColorPack-test.js @@ -0,0 +1,136 @@ +suite('Color Pack', function() { + // ====================================================== + test('colorize basic', 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.Colorize); + darth.setFilterColorizeColor([255,0,128]); + layer.draw(); + + // Assert fails even though '[255,0,128] = [255,0,128]' + //assert.equal(darth.getFilterColorizeColor(), [255,0,128]); + + done(); + }; + imageObj.src = 'assets/darth-vader.jpg'; + + }); + + // ====================================================== + test('colorize crop', 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, + crop: {x:128, y:48, width:256, height:128}, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.Colorize); + darth.setFilterColorizeColor([0,255,0]); + layer.draw(); + + // assert.equal(darth.getFilterColorizeColor(), [0,255,0]); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + }); + + // ====================================================== + test('colorize 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.Colorize); + darth.setFilterColorizeColor([0,128,255]); + layer.draw(); + + done(); + }; + imageObj.src = 'assets/lion.png'; + + }); + + + // ====================================================== + test('hue shift 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.ShiftHue); + darth.setFilterHueShiftDeg(360); + layer.draw(); + + var tween = new Kinetic.Tween({ + node: darth, + duration: 5.0, + filterHueShiftDeg: 0, + easing: Kinetic.Easings.EaseInOut + }); + + darth.on('mouseover', function() { + tween.play(); + }); + + darth.on('mouseout', function() { + tween.reverse(); + }); + + done(); + }; + imageObj.src = 'assets/lion.png'; + + }); + +}); \ No newline at end of file diff --git a/test/unit/filters/ConvolvePack-test.js b/test/unit/filters/ConvolvePack-test.js new file mode 100644 index 00000000..51e22748 --- /dev/null +++ b/test/unit/filters/ConvolvePack-test.js @@ -0,0 +1,175 @@ +suite('Convolve Pack', 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.setFilter(Kinetic.Filters.Emboss); + darth.setFilterAmount(50); + 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.setFilter(Kinetic.Filters.Edge); + darth.setFilterAmount(50); + 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.setFilter(Kinetic.Filters.UnsharpMask); + darth.setFilterAmount(50); + 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.setFilter(Kinetic.Filters.SoftBlur); + darth.setFilterAmount(50); + 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/Grayscale-test.js b/test/unit/filters/Grayscale-test.js new file mode 100644 index 00000000..f47d5d15 --- /dev/null +++ b/test/unit/filters/Grayscale-test.js @@ -0,0 +1,82 @@ +suite('Filter Grayscale', function() { + // ====================================================== + test('basic', 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.Grayscale); + layer.draw(); + + done(); + }; + imageObj.src = 'assets/darth-vader.jpg'; + + }); + + // ====================================================== + test('crop', 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, + crop: {x:128, y:48, width:256, height:128}, + filter: Kinetic.Filters.Grayscale, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + }); + + // ====================================================== + test('with transparency', 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.Grayscale); + layer.draw(); + + done(); + }; + imageObj.src = 'assets/lion.png'; + + }); + +}); \ No newline at end of file diff --git a/test/unit/filters/Invert-test.js b/test/unit/filters/Invert-test.js new file mode 100644 index 00000000..1d76bffe --- /dev/null +++ b/test/unit/filters/Invert-test.js @@ -0,0 +1,84 @@ +suite('Invert', function() { + // ====================================================== + test('basic', 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.Invert); + layer.draw(); + + done(); + }; + imageObj.src = 'assets/darth-vader.jpg'; + + }); + + // ====================================================== + test('crop', 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, + crop: {x:128, y:48, width:256, height:128}, + draggable: true + }); + + layer.add(darth); + stage.add(layer); + + darth.setFilter(Kinetic.Filters.Invert); + layer.draw(); + + done(); + + }; + imageObj.src = 'assets/darth-vader.jpg'; + }); + + // ====================================================== + test('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.Invert); + layer.draw(); + + done(); + }; + imageObj.src = 'assets/lion.png'; + + }); + +}); \ No newline at end of file diff --git a/test/unit/filters/Mask-test.js b/test/unit/filters/Mask-test.js new file mode 100644 index 00000000..9560178d --- /dev/null +++ b/test/unit/filters/Mask-test.js @@ -0,0 +1,42 @@ +suite('Mask', function() { + + // ====================================================== + test('basic', function(done) { + var stage = addStage(); + + var imageObj = new Image(); + imageObj.onload = function() { + + var layer = new Kinetic.Layer({ + throttle: 999 + }); + var bamoon = new Kinetic.Image({ + x: 0, + y: 0, + image: imageObj, + draggable: true + }), + filtered = new Kinetic.Image({ + x: 300, + y: 0, + image: imageObj, + draggable: true + }); + + layer.add(bamoon); + layer.add(filtered); + stage.add(layer); + + filtered.setFilter(Kinetic.Filters.Mask); + filtered.setFilterThreshold(10); + + layer.draw(); + + done(); + + }; + imageObj.src = 'assets/bamoon.jpg'; + + }); + +}); \ No newline at end of file