mirror of
https://github.com/konvajs/konva.git
synced 2026-01-08 18:54:40 +08:00
first pass at integrating filters into new caching mechanism. added group filter test. Removed blurX and blurY filters because I don't think they'll be needed in their current state. Commented out half filter blur test because it's not a common use case. other filter tests have been disabled for now. Working on enabling them with future commits
This commit is contained in:
@@ -241,26 +241,41 @@
|
||||
drawScene: function(can) {
|
||||
var layer = this.getLayer(),
|
||||
canvas = can || (layer && layer.getCanvas()),
|
||||
context = canvas && canvas.getContext(),
|
||||
cachedCanvas = this._cache.canvas,
|
||||
cachedSceneCanvas = cachedCanvas && cachedCanvas.scene;
|
||||
|
||||
if (this.isVisible()) {
|
||||
this._draw(canvas, cachedSceneCanvas, 'drawScene');
|
||||
if (cachedSceneCanvas) {
|
||||
this._drawCachedSceneCanvas(context);
|
||||
}
|
||||
else {
|
||||
this._drawChildren(canvas, 'drawScene');
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
drawHit: function(can) {
|
||||
var layer = this.getLayer(),
|
||||
canvas = can || (layer && layer.hitCanvas),
|
||||
context = canvas && canvas.getContext(),
|
||||
cachedCanvas = this._cache.canvas,
|
||||
cachedHitCanvas = cachedCanvas && cachedCanvas.hit;
|
||||
|
||||
if (this.shouldDrawHit()) {
|
||||
this._draw(canvas, cachedHitCanvas, 'drawHit');
|
||||
if (cachedHitCanvas) {
|
||||
context.save();
|
||||
context._applyTransform(this);
|
||||
context.drawImage(cachedHitCanvas._canvas, 0, 0);
|
||||
context.restore();
|
||||
}
|
||||
else {
|
||||
this._drawChildren(canvas, 'drawHit');
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
_draw: function(canvas, cachedCanvas, drawMethod) {
|
||||
_drawChildren: function(canvas, drawMethod) {
|
||||
var context = canvas && canvas.getContext(),
|
||||
clipWidth = this.getClipWidth(),
|
||||
clipHeight = this.getClipHeight(),
|
||||
@@ -279,17 +294,9 @@
|
||||
context.reset();
|
||||
}
|
||||
|
||||
if (cachedCanvas) {
|
||||
context.save();
|
||||
context._applyTransform(this);
|
||||
context.drawImage(cachedCanvas._canvas, 0, 0);
|
||||
context.restore();
|
||||
}
|
||||
else {
|
||||
this.children.each(function(child) {
|
||||
child[drawMethod](canvas);
|
||||
});
|
||||
}
|
||||
this.children.each(function(child) {
|
||||
child[drawMethod](canvas);
|
||||
});
|
||||
|
||||
if (hasClip) {
|
||||
context.restore();
|
||||
|
||||
@@ -111,11 +111,17 @@
|
||||
this.addColorComponentSetter(constructor, attr, G);
|
||||
this.addColorComponentSetter(constructor, attr, B);
|
||||
|
||||
// overloaders
|
||||
this.addOverloadedGetterSetter(constructor, attr + RGB);
|
||||
this.addOverloadedGetterSetter(constructor, attr + UPPER_R);
|
||||
this.addOverloadedGetterSetter(constructor, attr + UPPER_G);
|
||||
this.addOverloadedGetterSetter(constructor, attr + UPPER_B);
|
||||
},
|
||||
addFilterGetterSetter: function(constructor, attr, def) {
|
||||
this.addGetter(constructor, attr, def);
|
||||
this.addFilterSetter(constructor, attr);
|
||||
this.addOverloadedGetterSetter(constructor, attr);
|
||||
},
|
||||
|
||||
// getter adders
|
||||
addColorRGBGetter: function(constructor, attr) {
|
||||
@@ -237,6 +243,15 @@
|
||||
return this;
|
||||
};
|
||||
},
|
||||
addFilterSetter: function(constructor, attr) {
|
||||
var method = SET + Kinetic.Util._capitalize(attr);
|
||||
|
||||
constructor.prototype[method] = function(val) {
|
||||
this._setAttr(attr, val);
|
||||
this._filterUpToDate = false;
|
||||
return this;
|
||||
};
|
||||
},
|
||||
addPointSetter: function(constructor, attr) {
|
||||
var that = this,
|
||||
baseMethod = SET + Kinetic.Util._capitalize(attr);
|
||||
|
||||
82
src/Node.js
82
src/Node.js
@@ -43,6 +43,7 @@
|
||||
this.eventListeners = {};
|
||||
this.attrs = {};
|
||||
this._cache = {};
|
||||
this._filterUpToDate = false;
|
||||
this.setAttrs(config);
|
||||
|
||||
// event bindings for cache handling
|
||||
@@ -112,18 +113,25 @@
|
||||
* @example
|
||||
* node.cache();
|
||||
*/
|
||||
cache: function(box) {
|
||||
var x = box.x || 0,
|
||||
cache: function(b) {
|
||||
var box = b || {},
|
||||
x = box.x || 0,
|
||||
y = box.y || 0,
|
||||
width = box.width || this.width(),
|
||||
height = box.height || this.height(),
|
||||
sceneCanvasCache = new Kinetic.SceneCanvas({
|
||||
pixelRatio: 1,
|
||||
width: box.width,
|
||||
height: box.height
|
||||
width: width,
|
||||
height: height
|
||||
}),
|
||||
filterCanvasCache = new Kinetic.SceneCanvas({
|
||||
pixelRatio: 1,
|
||||
width: width,
|
||||
height: height
|
||||
}),
|
||||
hitCanvasCache = new Kinetic.HitCanvas({
|
||||
pixelRatio: 1,
|
||||
width: box.width,
|
||||
height: box.height
|
||||
width: width,
|
||||
height: height
|
||||
}),
|
||||
origTransEnabled = this.transformsEnabled(),
|
||||
origX = this.x(),
|
||||
@@ -142,6 +150,7 @@
|
||||
|
||||
this._cache.canvas = {
|
||||
scene: sceneCanvasCache,
|
||||
filter: filterCanvasCache,
|
||||
hit: hitCanvasCache,
|
||||
x: x,
|
||||
y: y
|
||||
@@ -149,6 +158,48 @@
|
||||
|
||||
return this;
|
||||
},
|
||||
_drawCachedSceneCanvas: function(context) {
|
||||
var filters = this.filters(),
|
||||
cachedCanvas = this._cache.canvas,
|
||||
sceneCanvas = cachedCanvas.scene,
|
||||
filterCanvas = cachedCanvas.filter,
|
||||
filterContext = filterCanvas.getContext(),
|
||||
len, imageData, n, filter;
|
||||
|
||||
context.save();
|
||||
context._applyTransform(this);
|
||||
|
||||
if (filters) {
|
||||
if (!this._filterUpToDate) {
|
||||
try {
|
||||
len = filters.length;
|
||||
filterContext.clear();
|
||||
// copy cached canvas onto filter context
|
||||
filterContext.drawImage(sceneCanvas._canvas, 0, 0);
|
||||
imageData = filterContext.getImageData(0, 0, filterCanvas.getWidth(), filterCanvas.getHeight());
|
||||
|
||||
// apply filters to filter context
|
||||
for (n=0; n<len; n++) {
|
||||
filter = filters[n];
|
||||
filter.call(this, imageData);
|
||||
filterContext.putImageData(imageData, 0, 0);
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
Kinetic.Util.warn('Unable to apply filter. ' + e.message);
|
||||
}
|
||||
|
||||
this._filterUpToDate = true;
|
||||
}
|
||||
|
||||
context.drawImage(filterCanvas._canvas, 0, 0);
|
||||
}
|
||||
else {
|
||||
context.drawImage(sceneCanvas._canvas, 0, 0);
|
||||
}
|
||||
|
||||
context.restore();
|
||||
},
|
||||
/*
|
||||
* the default isDraggable method returns false.
|
||||
* if the DragAndDrop module is included, this is overwritten
|
||||
@@ -1753,6 +1804,23 @@
|
||||
* @returns {Boolean|String}
|
||||
*/
|
||||
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'filters');
|
||||
/**
|
||||
* get/set filters
|
||||
* @name filters
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Array} filters array of filters
|
||||
* @returns {Array}
|
||||
* @example
|
||||
* // set a single filter<br>
|
||||
* node.filters([Kinetic.Filters.Blur]);<br><br>
|
||||
*
|
||||
* // get filters<br>
|
||||
* var filters = node.filters();
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'visible', 'inherit');
|
||||
|
||||
/**
|
||||
|
||||
22
src/Shape.js
22
src/Shape.js
@@ -236,19 +236,16 @@
|
||||
var canvas = can || this.getLayer().getCanvas(),
|
||||
context = canvas.getContext(),
|
||||
cachedCanvas = this._cache.canvas,
|
||||
cachedSceneCanvas = cachedCanvas && cachedCanvas.scene,
|
||||
drawFunc = this.getDrawFunc(),
|
||||
hasShadow = this.hasShadow(),
|
||||
stage, bufferCanvas, bufferContext;
|
||||
|
||||
if(this.isVisible()) {
|
||||
context.save();
|
||||
|
||||
if (cachedSceneCanvas) {
|
||||
context._applyTransform(this);
|
||||
context.drawImage(cachedSceneCanvas._canvas, 0, 0);
|
||||
if (cachedCanvas) {
|
||||
this._drawCachedSceneCanvas(context);
|
||||
}
|
||||
else if (drawFunc) {
|
||||
context.save();
|
||||
// if buffer canvas is needed
|
||||
if (this._useBufferCanvas()) {
|
||||
stage = this.getStage();
|
||||
@@ -286,10 +283,9 @@
|
||||
|
||||
context._applyOpacity(this);
|
||||
drawFunc.call(this, context);
|
||||
}
|
||||
}
|
||||
context.restore();
|
||||
}
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -302,18 +298,22 @@
|
||||
cachedHitCanvas = cachedCanvas && cachedCanvas.hit;
|
||||
|
||||
if(this.shouldDrawHit()) {
|
||||
context.save();
|
||||
|
||||
if (cachedHitCanvas) {
|
||||
context.save();
|
||||
context._applyTransform(this);
|
||||
context.drawImage(cachedHitCanvas._canvas, 0, 0);
|
||||
context.restore();
|
||||
}
|
||||
else if (drawFunc) {
|
||||
context.save();
|
||||
context._applyLineJoin(this);
|
||||
context._applyTransform(this);
|
||||
|
||||
drawFunc.call(this, context);
|
||||
context.restore();
|
||||
}
|
||||
context.restore();
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
@@ -352,24 +352,19 @@
|
||||
Blur(src, dst||src, opt );
|
||||
}else{
|
||||
Blur.call(this, src, dst||src, opt || {
|
||||
filterRadius: this.getFilterRadius()
|
||||
filterRadius: this.blurRadius()
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterRadius', 0);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'blurRadius', 0);
|
||||
|
||||
/**
|
||||
* get filter radius. Returns the radius for Gaussian blur filter.
|
||||
* @name getFilterRadius
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
*/
|
||||
|
||||
/**
|
||||
* get filter radius. Set the radius for Gaussian blur filter.
|
||||
* @name setFilterRadius
|
||||
* get/set blur radius
|
||||
* @name blurRadius
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
* @param {Integer} radius
|
||||
* @returns {Integer}
|
||||
*/
|
||||
})();
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterBrightness', 0);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'brightness', 0);
|
||||
/**
|
||||
* get filter brightness. The brightness is a number between -255 and 255. Positive values
|
||||
* increase the brightness and negative values decrease the brightness, making the image darker
|
||||
|
||||
@@ -70,9 +70,9 @@
|
||||
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterHue', 0);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterSaturation', 1);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterValue', 1);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'hue', 0);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'saturation', 1);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'value', 1);
|
||||
|
||||
Kinetic.Filters.HSV = function(src,dst,opt){
|
||||
if( this === Kinetic.Filters ){
|
||||
@@ -97,7 +97,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterHueShiftDeg', 0);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'hueShiftDeg', 0);
|
||||
|
||||
/**
|
||||
* get filter hue. Returns the hue shift for the HSV filter.
|
||||
@@ -184,7 +184,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterColorizeColor', [255,0,0] );
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'colorizeColor', [255,0,0] );
|
||||
/**
|
||||
* Gets the colorizing color.
|
||||
* @name getFilterColorizeColor
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
return kernel;
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterAmount', 50);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'convoltion', 50);
|
||||
/**
|
||||
* get the current filter amount
|
||||
* @name getFilterAmount
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'quantizationLevels', 4);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'quantizationLevels', 4);
|
||||
|
||||
/**
|
||||
* get quantization levels. Returns the number of unique levels for each color
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
return idata;
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filterThreshold', 0);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'threshold', 0);
|
||||
|
||||
//threshold The RGB euclidian distance threshold (default : 10)
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'noiseAmount', 32);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'noise', 32);
|
||||
|
||||
Kinetic.Filters.Noise = function(src,dst,opt){
|
||||
if( this === Kinetic.Filters ){
|
||||
|
||||
@@ -86,16 +86,15 @@
|
||||
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'pixelWidth', 8);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'pixelHeight', 8);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'pixelationSize', 8);
|
||||
|
||||
Kinetic.Filters.Pixelate = function(src,dst,opt){
|
||||
if( this === Kinetic.Filters ){
|
||||
Pixelate(src, dst||src, opt );
|
||||
}else{
|
||||
Pixelate.call(this, src, dst||src, opt || {
|
||||
pixelWidth: this.getPixelWidth(),
|
||||
pixelHeight: this.getPixelHeight()
|
||||
pixelWidth: this.pixelationSize(),
|
||||
pixelHeight: this.pixelationSize()
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
(function () {
|
||||
|
||||
/**
|
||||
* BlurX Filter. Blurs the image in the X direction (horizontally). It
|
||||
* performs w*h pixel reads, and w*h pixel writes. It is faster than a
|
||||
* Gaussian blur but does not look as nice. Use Kinetic.Filters.Blur for
|
||||
* a Gaussian blur.
|
||||
* @function
|
||||
* @author ippo615
|
||||
* @memberof Kinetic.Filters
|
||||
* @param {ImageData} src, the source image data (what will be transformed)
|
||||
* @param {ImageData} dst, the destination image data (where it will be saved)
|
||||
* @param {Object} opt
|
||||
* @param {Number} [opt.blurWidth] how many neighboring pixels to will affect the
|
||||
* blurred pixel, default: 5
|
||||
*/
|
||||
|
||||
var BlurX = function(src,dst,opt){
|
||||
|
||||
var srcPixels = src.data,
|
||||
dstPixels = dst.data,
|
||||
xSize = src.width,
|
||||
ySize = src.height,
|
||||
i, m, x, y, k, tmp, r=0,g=0,b=0,a=0;
|
||||
|
||||
// DONT USE: kSize = opt.blurWidth || 5;
|
||||
// HINT: consider when (opt.blurWidth = 0)
|
||||
var kSize = 5;
|
||||
if( opt.hasOwnProperty('blurWidth') ){
|
||||
kSize = Math.round( Math.abs(opt.blurWidth) )+1;
|
||||
}
|
||||
var kMid = Math.floor(kSize/2);
|
||||
|
||||
//console.info('Blur Width: '+kSize);
|
||||
//console.info('Blur Middle: '+kMid);
|
||||
|
||||
var xEnd = xSize - kMid;
|
||||
|
||||
for (y = 0; y < ySize; y += 1) {
|
||||
r=0;g=0;b=0;a=0;
|
||||
for (x=-kMid; x<kMid; x+=1 ){
|
||||
// Add the new
|
||||
//if( y === 0 ){ console.info('Loading pixel at: '+((x+xSize)%xSize) ); }
|
||||
i = (y * xSize + (x+xSize)%xSize ) * 4;
|
||||
r += srcPixels[i+0];
|
||||
g += srcPixels[i+1];
|
||||
b += srcPixels[i+2];
|
||||
a += srcPixels[i+3];
|
||||
}
|
||||
|
||||
for (x = 0; x < xSize; x += 1) {
|
||||
//if( y === 0 ){ console.info('Added pixel at: '+(x+kMid)); }
|
||||
//if( y === 0 ){ console.info('Recorded pixel at: '+x); }
|
||||
//if( y === 0 ){ console.info('Removed pixel at: '+((x-kMid+xSize)%xSize) ); }
|
||||
// Add the new
|
||||
i = (y * xSize + (x+kMid)%xSize ) * 4;
|
||||
r += srcPixels[i+0];
|
||||
g += srcPixels[i+1];
|
||||
b += srcPixels[i+2];
|
||||
a += srcPixels[i+3];
|
||||
// Store the result
|
||||
i = (y * xSize + x) * 4;
|
||||
dstPixels[i+0] = r/kSize;
|
||||
dstPixels[i+1] = g/kSize;
|
||||
dstPixels[i+2] = b/kSize;
|
||||
dstPixels[i+3] = a/kSize;
|
||||
// Subtract the old
|
||||
i = (y * xSize + (x-kMid+xSize)%xSize ) * 4;
|
||||
r -= srcPixels[i+0];
|
||||
g -= srcPixels[i+1];
|
||||
b -= srcPixels[i+2];
|
||||
a -= srcPixels[i+3];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* BlurY Filter. Blurs the image in the Y direction (vertically). It
|
||||
* performs w*h pixel reads, and w*h pixel writes. It is faster than a
|
||||
* Gaussian blur but does not look as nice. Use Kinetic.Filters.Blur for
|
||||
* a Gaussian blur.
|
||||
* @function
|
||||
* @author ippo615
|
||||
* @memberof Kinetic.Filters
|
||||
* @param {ImageData} src, the source image data (what will be transformed)
|
||||
* @param {ImageData} dst, the destination image data (where it will be saved)
|
||||
* @param {Object} opt
|
||||
* @param {Number} [opt.blurHeight] how many neighboring pixels to will affect the
|
||||
* blurred pixel, default: 5
|
||||
*/
|
||||
|
||||
var BlurY = function(src,dst,opt){
|
||||
|
||||
var srcPixels = src.data,
|
||||
dstPixels = dst.data,
|
||||
xSize = src.width,
|
||||
ySize = src.height,
|
||||
i, m, x, y, k, tmp, r=0,g=0,b=0,a=0;
|
||||
|
||||
var kSize = 5;
|
||||
if( opt.hasOwnProperty('blurHeight') ){
|
||||
kSize = Math.round( Math.abs(opt.blurHeight) )+1;
|
||||
}
|
||||
var kMid = Math.floor(kSize/2);
|
||||
|
||||
var yEnd = ySize - kMid;
|
||||
|
||||
for (x = 0; x < xSize; x += 1) {
|
||||
r=0;g=0;b=0;a=0;
|
||||
for (y=-kMid; y<kMid; y+=1 ){
|
||||
// Add the new
|
||||
i = ((y+ySize)%ySize * xSize + x ) * 4;
|
||||
r += srcPixels[i+0];
|
||||
g += srcPixels[i+1];
|
||||
b += srcPixels[i+2];
|
||||
a += srcPixels[i+3];
|
||||
}
|
||||
|
||||
for (y = 0; y < ySize; y += 1) {
|
||||
// Add the new
|
||||
i = ((y+kMid+ySize)%ySize * xSize + x ) * 4;
|
||||
r += srcPixels[i+0];
|
||||
g += srcPixels[i+1];
|
||||
b += srcPixels[i+2];
|
||||
a += srcPixels[i+3];
|
||||
// Store the result
|
||||
i = (y * xSize + x) * 4;
|
||||
dstPixels[i+0] = r/kSize;
|
||||
dstPixels[i+1] = g/kSize;
|
||||
dstPixels[i+2] = b/kSize;
|
||||
dstPixels[i+3] = a/kSize;
|
||||
// Subtract the old
|
||||
i = ((y-kMid+ySize)%ySize * xSize + x ) * 4;
|
||||
r -= srcPixels[i+0];
|
||||
g -= srcPixels[i+1];
|
||||
b -= srcPixels[i+2];
|
||||
a -= srcPixels[i+3];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'blurWidth', 5);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'blurHeight', 5);
|
||||
|
||||
Kinetic.Filters.BlurX = function(src,dst,opt){
|
||||
if( this === Kinetic.Filters ){
|
||||
BlurX(src, dst||src, opt );
|
||||
}else{
|
||||
BlurX.call(this, src, dst||src, opt || {
|
||||
blurWidth: this.getBlurWidth()
|
||||
});
|
||||
}
|
||||
};
|
||||
Kinetic.Filters.BlurY = function(src,dst,opt){
|
||||
if( this === Kinetic.Filters ){
|
||||
BlurY(src, dst||src, opt );
|
||||
}else{
|
||||
BlurY.call(this, src, dst||src, opt || {
|
||||
blurHeight: this.getBlurHeight()
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get filter blur width. Returns the width of a blurred pixel. Must be
|
||||
* an integer greater than 0.
|
||||
* @name getBlurWidth
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
*/
|
||||
|
||||
/**
|
||||
* set filter blur width.
|
||||
* @name setBlurWidth
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
*/
|
||||
|
||||
/**
|
||||
* get filter blur height. Returns the height of a blurred pixel. Must be
|
||||
* an integer greater than 0.
|
||||
* @name getBlurHeight
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
*/
|
||||
|
||||
/**
|
||||
* set filter blur height.
|
||||
* @name setBlurHeight
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
*/
|
||||
|
||||
})();
|
||||
@@ -33,7 +33,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'thresholdLevel', 128);
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Node, 'threshold', 128);
|
||||
|
||||
Kinetic.Filters.Threshold = function(src,dst,opt){
|
||||
if( this === Kinetic.Filters ){
|
||||
|
||||
@@ -45,36 +45,18 @@
|
||||
_drawFunc: function(context) {
|
||||
var width = this.getWidth(),
|
||||
height = this.getHeight(),
|
||||
crop, cropWidth, cropHeight,
|
||||
params,
|
||||
image;
|
||||
image = this.getImage(),
|
||||
crop, cropWidth, cropHeight, params;
|
||||
|
||||
//TODO: this logic needs to hook int othe new caching system
|
||||
|
||||
// if a filter is set, and the filter needs to be updated, reapply
|
||||
if (this.getFilter() && this._applyFilter) {
|
||||
this.applyFilter();
|
||||
this._applyFilter = false;
|
||||
}
|
||||
|
||||
// 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(),
|
||||
cropWidth = crop.width;
|
||||
cropHeight = crop.height;
|
||||
if (cropWidth && cropHeight) {
|
||||
params = [image, crop.x, crop.y, cropWidth, cropHeight, 0, 0, width, height];
|
||||
} else {
|
||||
params = [image, 0, 0, width, height];
|
||||
}
|
||||
if (image) {
|
||||
crop = this.getCrop(),
|
||||
cropWidth = crop.width;
|
||||
cropHeight = crop.height;
|
||||
if (cropWidth && cropHeight) {
|
||||
params = [image, crop.x, crop.y, cropWidth, cropHeight, 0, 0, width, height];
|
||||
}
|
||||
else {
|
||||
params = [image, 0, 0, width, height];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,59 +88,6 @@
|
||||
context.fillStrokeShape(this);
|
||||
}
|
||||
},
|
||||
applyFilter: function() {
|
||||
var image = this.getImage(),
|
||||
width = this.getWidth(),
|
||||
height = this.getHeight(),
|
||||
filter = this.getFilter(),
|
||||
crop = this.getCrop(),
|
||||
filterCanvas, context, imageData;
|
||||
|
||||
// Determine the region we are cropping
|
||||
crop.x = crop.x;
|
||||
crop.y = crop.y;
|
||||
crop.width = crop.width || width - crop.x;
|
||||
crop.height = crop.height || 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: crop.width,
|
||||
height: crop.height,
|
||||
pixelRatio: 1
|
||||
});
|
||||
}
|
||||
|
||||
context = filterCanvas.getContext();
|
||||
|
||||
try {
|
||||
// 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);
|
||||
}
|
||||
catch(e) {
|
||||
this.clearFilter();
|
||||
Kinetic.Util.warn('Unable to apply filter. ' + e.message);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* clear filter
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
*/
|
||||
clearFilter: function() {
|
||||
this.filterCanvas = null;
|
||||
this._applyFilter = false;
|
||||
},
|
||||
/**
|
||||
* create image hit region which enables more accurate hit detection mapping of the image
|
||||
* by avoiding event detections for transparent pixels
|
||||
@@ -227,31 +156,10 @@
|
||||
getHeight: function() {
|
||||
var image = this.getImage();
|
||||
return this.attrs.height || (image ? image.height : 0);
|
||||
},
|
||||
destroy: function(){
|
||||
Kinetic.Shape.prototype.destroy.call(this);
|
||||
delete this.filterCanvas;
|
||||
delete this.attrs;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
Kinetic.Util.extend(Kinetic.Image, Kinetic.Shape);
|
||||
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter = function(constructor, attr, def) {
|
||||
this.addGetter(constructor, attr, def);
|
||||
this.addFilterSetter(constructor, attr);
|
||||
};
|
||||
|
||||
Kinetic.Factory.addFilterSetter = function(constructor, attr) {
|
||||
var method = SET + Kinetic.Util._capitalize(attr);
|
||||
|
||||
constructor.prototype[method] = function(val) {
|
||||
this._setAttr(attr, val);
|
||||
this._applyFilter = true;
|
||||
};
|
||||
};
|
||||
|
||||
// add getters setters
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Image, 'image');
|
||||
|
||||
@@ -363,22 +271,4 @@
|
||||
* @memberof Kinetic.Image.prototype
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addFilterGetterSetter(Kinetic.Image, 'filter');
|
||||
|
||||
/**
|
||||
* set filter
|
||||
* @name setFilter
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
* @param {Function} filter
|
||||
*/
|
||||
|
||||
/**
|
||||
* get filter
|
||||
* @name getFilter
|
||||
* @method
|
||||
* @memberof Kinetic.Image.prototype
|
||||
* @returns {Function}
|
||||
*/
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user