Skip to content

Commit

Permalink
Better use of filter isNeutral (#5129)
Browse files Browse the repository at this point in the history
* done so far

* done so far

* added tests for isNeutral

* mini test for apply filter

* test lint
  • Loading branch information
asturur authored Aug 5, 2018
1 parent 146769e commit 5ee8935
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 57 deletions.
30 changes: 23 additions & 7 deletions src/filters/base_filter.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,31 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
},

/**
* Intentionally left blank, to be overridden in custom filters
* Generic isNeutral implementation for one parameter based filters.
* Used only in image applyFilters to discard filters that will not have an effect
* on the image
* Other filters may need their own verison ( ColorMatrix, HueRotation, gamma, ComposedFilter )
* @param {Object} options
**/
isNeutralState: function(/* options */) {
return false;
var main = this.mainParameter,
_class = fabric.Image.filters[this.type].prototype;
if (main) {
if (Array.isArray(_class[main])) {
for (var i = _class[main].length; i--;) {
if (this[main][i] !== _class[main][i]) {
return false;
}
}
return true;
}
else {
return _class[main] === this[main];
}
}
else {
return false;
}
},

/**
Expand All @@ -212,15 +232,11 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
*/
applyTo: function(options) {
if (options.webgl) {
if (options.passes > 1 && this.isNeutralState(options)) {
// avoid doing something that we do not need
return;
}
this._setupFrameBuffer(options);
this.applyToWebGL(options);
this._swapTextures(options);
}
else if (!this.isNeutralState()) {
else {
this.applyTo2d(options);
}
},
Expand Down
14 changes: 0 additions & 14 deletions src/filters/colormatrix_filter.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,6 @@
this.matrix = this.matrix.slice(0);
},

/**
* Intentionally left blank, to be overridden in custom filters
* @param {Object} options
**/
isNeutralState: function(/* options */) {
var _class = filters.ColorMatrix;
for (var i = 20; i--;) {
if (this.matrix[i] !== _class.prototype.matrix[i]) {
return false;
}
}
return true;
},

/**
* Apply the ColorMatrix operation to a Uint8Array representing the pixels of an image.
*
Expand Down
4 changes: 4 additions & 0 deletions src/filters/composed_filter.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
subFilters: this.subFilters.map(function(filter) { return filter.toObject(); }),
});
},

isNeutralState: function() {
return !this.subFilters.some(function(filter) { return !filter.isNeutralState(); });
}
});

/**
Expand Down
9 changes: 9 additions & 0 deletions src/filters/gamma_filter.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@
*/
mainParameter: 'gamma',

/**
* Constructor
* @param {Object} [options] Options object
*/
initialize: function(options) {
this.gamma = [1, 1, 1];
filters.BaseFilter.prototype.initialize.call(this, options);
},

/**
* Apply the Gamma operation to a Uint8Array representing the pixels of an image.
*
Expand Down
9 changes: 9 additions & 0 deletions src/filters/grayscale_filter.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@
var mode = 1;
gl.uniform1i(uniformLocations.uMode, mode);
},

/**
* Grayscale filter isNeutralState implementation
* The filter is never neutral
* on the image
**/
isNeutralState: function() {
return false;
},
});

/**
Expand Down
13 changes: 12 additions & 1 deletion src/filters/hue_rotation.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@
this.matrix[12] = cos + aThird * OneMinusCos;
},

/**
* HueRotation isNeutralState implementation
* Used only in image applyFilters to discard filters that will not have an effect
* on the image
* @param {Object} options
**/
isNeutralState: function(options) {
this.calculateMatrix();
return filters.BaseFilter.prototype.isNeutralState.call(this, options);
},

/**
* Apply this filter to the input image data provided.
*
Expand All @@ -79,7 +90,7 @@
*/
applyTo: function(options) {
this.calculateMatrix();
fabric.Image.filters.BaseFilter.prototype.applyTo.call(this, options);
filters.BaseFilter.prototype.applyTo.call(this, options);
},

});
Expand Down
13 changes: 10 additions & 3 deletions src/filters/invert_filter.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@
* @param {ImageData} options.imageData The Uint8Array to be filtered.
*/
applyTo2d: function(options) {
if (!this.invert) {
return;
}
var imageData = options.imageData,
data = imageData.data, i,
len = data.length;
Expand All @@ -68,6 +65,16 @@
}
},

/**
* Invert filter isNeutralState implementation
* Used only in image applyFilters to discard filters that will not have an effect
* on the image
* @param {Object} options
**/
isNeutralState: function() {
return !this.invert;
},

/**
* Return WebGL uniform locations for this filter's shader.
*
Expand Down
3 changes: 0 additions & 3 deletions src/filters/pixelate_filter.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,6 @@
* @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.
*/
applyTo2d: function(options) {
if (this.blocksize === 1) {
return;
}
var imageData = options.imageData,
data = imageData.data,
iLen = imageData.height,
Expand Down
16 changes: 5 additions & 11 deletions src/filters/resize_filter.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@
* @param {Number} scaleX
* @default
*/
scaleX: 0,
scaleX: 1,

/**
* Scale factor for resizing, y axis
* @param {Number} scaleY
* @default
*/
scaleY: 0,
scaleY: 1,

/**
* LanczosLobes parameter for lanczos filter, valid for resizeType lanczos
Expand Down Expand Up @@ -158,10 +158,6 @@
*/
applyTo: function(options) {
if (options.webgl) {
if (options.passes > 1 && this.isNeutralState(options)) {
// avoid doing something that we do not need
return;
}
options.passes++;
this.width = options.sourceWidth;
this.horizontal = true;
Expand All @@ -186,15 +182,13 @@
this._swapTextures(options);
options.sourceHeight = options.destinationHeight;
}
else if (!this.isNeutralState(options)) {
else {
this.applyTo2d(options);
}
},

isNeutralState: function(options) {
var scaleX = options.scaleX || this.scaleX,
scaleY = options.scaleY || this.scaleY;
return scaleX === 1 && scaleY === 1;
isNeutralState: function() {
return this.scaleX === 1 && this.scaleY === 1;
},

lanczosCreate: function(lobes) {
Expand Down
6 changes: 3 additions & 3 deletions src/shapes/image.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,8 @@
this._element = elementToFilter;
this._filterScalingX = 1;
this._filterScalingY = 1;
this._lastScaleX = 1;
this._lastScaleY = 1;
this._lastScaleX = scaleX;
this._lastScaleY = scaleY;
return;
}
if (!fabric.filterBackend) {
Expand Down Expand Up @@ -429,7 +429,7 @@
applyFilters: function(filters) {

filters = filters || this.filters || [];
filters = filters.filter(function(filter) { return filter; });
filters = filters.filter(function(filter) { return filter && !filter.isNeutralState(); });
if (this.group) {
this.set('dirty', true);
}
Expand Down
17 changes: 17 additions & 0 deletions test/unit/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,23 @@
});
});

QUnit.test('apply filters run isNeutralState implementation of filters', function(assert) {
var done = assert.async();
createImageObject(function(image) {
var run = false;
image.dirty = false;
var filter = new fabric.Image.filters.Brightness();
image.filters = [filter];
filter.isNeutralState = function() {
run = true;
};
assert.equal(run, false, 'isNeutralState did not run yet');
image.applyFilters();
assert.equal(run, true, 'isNeutralState did run');
done();
});
});

QUnit.test('apply filters do not set the image dirty if not in group', function(assert) {
var done = assert.async();
createImageObject(function(image) {
Expand Down
Loading

0 comments on commit 5ee8935

Please sign in to comment.