diff --git a/build.js b/build.js index 84fff03082b..196248c2dbd 100644 --- a/build.js +++ b/build.js @@ -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'), diff --git a/src/filters/brightness_filter.class.js b/src/filters/brightness_filter.class.js index e08dc114801..9ef33cde34e 100644 --- a/src/filters/brightness_filter.class.js +++ b/src/filters/brightness_filter.class.js @@ -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 || { }; diff --git a/src/filters/contrast_filter.class.js b/src/filters/contrast_filter.class.js new file mode 100644 index 00000000000..f428015aaae --- /dev/null +++ b/src/filters/contrast_filter.class.js @@ -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); diff --git a/src/filters/saturate_filter.class.js b/src/filters/saturate_filter.class.js new file mode 100644 index 00000000000..f91d9245014 --- /dev/null +++ b/src/filters/saturate_filter.class.js @@ -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);