From 541393b9911670a6272274da38e00c8f2dd81bd5 Mon Sep 17 00:00:00 2001 From: Marc Galang Date: Wed, 30 Jul 2014 09:50:52 +0300 Subject: [PATCH 1/2] Add blend filter. Implements several image blend modes (can add more later) --- build.js | 1 + src/filters/blend_filter.class.js | 108 ++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/filters/blend_filter.class.js diff --git a/build.js b/build.js index 3959b3a2..71bcee0b 100644 --- a/build.js +++ b/build.js @@ -234,6 +234,7 @@ var filesToInclude = [ ifSpecifiedInclude('image_filters', 'src/filters/sepia2_filter.class.js'), ifSpecifiedInclude('image_filters', 'src/filters/tint_filter.class.js'), ifSpecifiedInclude('image_filters', 'src/filters/multiply_filter.class.js'), + ifSpecifiedInclude('image_filters', 'src/filters/blend_filter.class.js'), ifSpecifiedInclude('text', 'src/shapes/text.class.js'), ifSpecifiedInclude('cufon', 'src/shapes/text.cufon.js'), diff --git a/src/filters/blend_filter.class.js b/src/filters/blend_filter.class.js new file mode 100644 index 00000000..4374072e --- /dev/null +++ b/src/filters/blend_filter.class.js @@ -0,0 +1,108 @@ +(function(global){ + 'use strict'; + + var fabric = global.fabric; + + /** + * Color Blend filter class + * @class fabric.Image.filter.Blend + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @example + * var filter = new fabric.Image.filters.Blend({ + * color: '#000', + * mode: 'multiply' + * }); + * + * var filter = new fabric.Image.filters.Blend({ + * image: fabricImageObject, + * mode: 'multiply', + * alpha: 0.5 + * }); + + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Blend = fabric.util.createClass({ + type: 'Blend', + + initialize: function(options){ + options = options || {}; + this.color = options.color || '#000'; + this.image = options.image || false; + this.mode = options.mode || 'multiply'; + this.alpha = options.alpha || 1; + }, + + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + tr, tg, tb, r, g, b, source, + isImage = false; + + if(this.image){ + // Blend images + isImage = true; + + var _el = document.createElement('canvas'); + _el.width = this.image.width; + _el.height = this.image.height; + + var _tmp_canvas = new fabric.StaticCanvas(_el); + _tmp_canvas.add(this.image); + var context2 = _tmp_canvas.getContext('2d'); + source = context2.getImageData(0, 0, _tmp_canvas.width, _tmp_canvas.height).data; + } else { + // Blend color + source = new fabric.Color(this.color).getSource(); + + tr = source[0] * this.alpha; + tg = source[1] * this.alpha; + tb = source[2] * this.alpha; + } + + for (var i = 0, len = data.length; i < len; i += 4) { + + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + if(isImage){ + tr = source[i] * this.alpha; + tg = source[i + 1] * this.alpha; + tb = source[i + 2] * this.alpha; + } + + switch(this.mode){ + case 'multiply': + data[i] = r * tr / 255; + data[i + 1] = g * tg / 255; + data[i + 2] = b * tb / 255; + break; + case 'screen': + data[i] = 1 - (1-r) * (1-tr); + data[i + 1] = 1 - (1-g) * (1-tg); + data[i + 2] = 1 - (1-b) * (1-tb); + break; + case 'add': + data[i] = Math.min(255, r + tr); + data[i + 1] = Math.min(255, g + tg); + data[i + 2] = Math.min(255, b + tb); + break; + case 'diff': + data[i] = Math.abs(r - tr); + data[i + 1] = Math.abs(g - tg); + data[i + 2] = Math.abs(b - tb); + break; + } + } + + context.putImageData(imageData, 0, 0); + } + }); + + fabric.Image.filters.Blend.fromObject = function(object) { + return new fabric.Image.filters.Blend(object); + }; +})(typeof exports !== 'undefined' ? exports : this); From 47d06c0cad17d2240b42a6c0b4cf25f29ab8d287 Mon Sep 17 00:00:00 2001 From: Marc Galang Date: Wed, 30 Jul 2014 20:04:57 +0300 Subject: [PATCH 2/2] Use createCanvasElement instead of createElement. Fix indentations. --- src/filters/blend_filter.class.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/filters/blend_filter.class.js b/src/filters/blend_filter.class.js index 4374072e..33be971c 100644 --- a/src/filters/blend_filter.class.js +++ b/src/filters/blend_filter.class.js @@ -36,16 +36,18 @@ applyTo: function(canvasEl) { var context = canvasEl.getContext('2d'), - imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), - data = imageData.data, - tr, tg, tb, r, g, b, source, - isImage = false; + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + tr, tg, tb, + r, g, b, + source, + isImage = false; if(this.image){ // Blend images isImage = true; - var _el = document.createElement('canvas'); + var _el = fabric.util.createCanvasElement(); _el.width = this.image.width; _el.height = this.image.height;