Skip to content

Commit

Permalink
Contrast & saturation (#3341)
Browse files Browse the repository at this point in the history
* added filters

* tweak

* fixed docs
  • Loading branch information
asturur authored Oct 15, 2016
1 parent 37976d5 commit 4459ae4
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 1 deletion.
2 changes: 2 additions & 0 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ var filesToInclude = [
ifSpecifiedInclude('image_filters', 'src/filters/blend_filter.class.js'),
ifSpecifiedInclude('image_filters', 'src/filters/resize_filter.class.js'),
ifSpecifiedInclude('image_filters', 'src/filters/colormatrix_filter.class.js'),
ifSpecifiedInclude('image_filters', 'src/filters/contrast_filter.class.js'),
ifSpecifiedInclude('image_filters', 'src/filters/saturate_filter.class.js'),

ifSpecifiedInclude('text', 'src/shapes/text.class.js'),

Expand Down
2 changes: 1 addition & 1 deletion src/filters/brightness_filter.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
* Constructor
* @memberOf fabric.Image.filters.Brightness.prototype
* @param {Object} [options] Options object
* @param {Number} [options.brightness=0] Value to brighten the image up (0..255)
* @param {Number} [options.brightness=0] Value to brighten the image up (-255..255)
*/
initialize: function(options) {
options = options || { };
Expand Down
84 changes: 84 additions & 0 deletions src/filters/contrast_filter.class.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
(function(global) {

'use strict';

var fabric = global.fabric || (global.fabric = { }),
extend = fabric.util.object.extend,
filters = fabric.Image.filters,
createClass = fabric.util.createClass;

/**
* Contrast filter class
* @class fabric.Image.filters.Contrast
* @memberOf fabric.Image.filters
* @extends fabric.Image.filters.BaseFilter
* @see {@link fabric.Image.filters.Contrast#initialize} for constructor definition
* @see {@link http://fabricjs.com/image-filters|ImageFilters demo}
* @example
* var filter = new fabric.Image.filters.Contrast({
* contrast: 40
* });
* object.filters.push(filter);
* object.applyFilters(canvas.renderAll.bind(canvas));
*/
filters.Contrast = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Contrast.prototype */ {

/**
* Filter type
* @param {String} type
* @default
*/
type: 'Contrast',

/**
* Constructor
* @memberOf fabric.Image.filters.Contrast.prototype
* @param {Object} [options] Options object
* @param {Number} [options.contrast=0] Value to contrast the image up (-255...255)
*/
initialize: function(options) {
options = options || { };
this.contrast = options.contrast || 0;
},

/**
* Applies filter to canvas element
* @param {Object} canvasEl Canvas element to apply filter to
*/
applyTo: function(canvasEl) {
var context = canvasEl.getContext('2d'),
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
data = imageData.data,
contrastF = 259 * (this.contrast + 255) / (255 * (259 - this.contrast));

for (var i = 0, len = data.length; i < len; i += 4) {
data[i] = contrastF * (data[i] - 128) + 128;
data[i + 1] = contrastF * (data[i + 1] - 128) + 128;
data[i + 2] = contrastF * (data[i + 2] - 128) + 128;
}

context.putImageData(imageData, 0, 0);
},

/**
* Returns object representation of an instance
* @return {Object} Object representation of an instance
*/
toObject: function() {
return extend(this.callSuper('toObject'), {
contrast: this.contrast
});
}
});

/**
* Returns filter instance from an object representation
* @static
* @param {Object} object Object to create an instance from
* @return {fabric.Image.filters.Contrast} Instance of fabric.Image.filters.Contrast
*/
fabric.Image.filters.Contrast.fromObject = function(object) {
return new fabric.Image.filters.Contrast(object);
};

})(typeof exports !== 'undefined' ? exports : this);
86 changes: 86 additions & 0 deletions src/filters/saturate_filter.class.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
(function(global) {

'use strict';

var fabric = global.fabric || (global.fabric = { }),
extend = fabric.util.object.extend,
filters = fabric.Image.filters,
createClass = fabric.util.createClass;

/**
* Saturate filter class
* @class fabric.Image.filters.Saturate
* @memberOf fabric.Image.filters
* @extends fabric.Image.filters.BaseFilter
* @see {@link fabric.Image.filters.Saturate#initialize} for constructor definition
* @see {@link http://fabricjs.com/image-filters|ImageFilters demo}
* @example
* var filter = new fabric.Image.filters.Saturate({
* saturate: 100
* });
* object.filters.push(filter);
* object.applyFilters(canvas.renderAll.bind(canvas));
*/
filters.Saturate = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Saturate.prototype */ {

/**
* Filter type
* @param {String} type
* @default
*/
type: 'Saturate',

/**
* Constructor
* @memberOf fabric.Image.filters.Saturate.prototype
* @param {Object} [options] Options object
* @param {Number} [options.contrast=0] Value to saturate the image (-255...255)
*/
initialize: function(options) {
options = options || { };
this.saturate = options.saturate || 0;
this.loadProgram();
},

/**
* Applies filter to canvas element
* @param {Object} canvasEl Canvas element to apply filter to
*/
applyTo: function(canvasEl) {
var context = canvasEl.getContext('2d'),
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
data = imageData.data,
max, adjust = -this.saturate * 0.01;

for (var i = 0, len = data.length; i < len; i += 4) {
max = Math.max(data[i], data[i + 1], data[i + 2]);
data[i] += max !== data[i] ? (max - data[i]) * adjust : 0;
data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * adjust : 0;
data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * adjust : 0;
}

context.putImageData(imageData, 0, 0);
},

/**
* Returns object representation of an instance
* @return {Object} Object representation of an instance
*/
toObject: function() {
return extend(this.callSuper('toObject'), {
saturate: this.saturate
});
}
});

/**
* Returns filter instance from an object representation
* @static
* @param {Object} object Object to create an instance from
* @return {fabric.Image.filters.Saturate} Instance of fabric.Image.filters.Saturate
*/
fabric.Image.filters.Saturate.fromObject = function(object) {
return new fabric.Image.filters.Saturate(object);
};

})(typeof exports !== 'undefined' ? exports : this);

0 comments on commit 4459ae4

Please sign in to comment.