diff --git a/src/filters/blendimage_filter.class.js b/src/filters/blendimage_filter.class.js index 3abaa1f5109..ca780e052cd 100644 --- a/src/filters/blendimage_filter.class.js +++ b/src/filters/blendimage_filter.class.js @@ -148,7 +148,7 @@ canvas1, context, image = this.image, blendData; if (!resources.blendImage) { - resources.blendImage = document.createElement('canvas'); + resources.blendImage = fabric.util.createCanvasElement(); } canvas1 = resources.blendImage; if (canvas1.width !== width || canvas1.height !== height) { @@ -159,6 +159,7 @@ context.setTransform(image.scaleX, 0, 0, image.scaleY, image.left, image.top); context.drawImage(image._element, 0, 0, width, height); blendData = context.getImageData(0, 0, width, height).data; + context.clearRect(0, 0, width, height); for (var i = 0; i < iLen; i += 4) { r = data[i]; diff --git a/test/fixtures/greyfloral_partial_transparent.png b/test/fixtures/greyfloral_partial_transparent.png new file mode 100644 index 00000000000..fd96d2fb8a3 Binary files /dev/null and b/test/fixtures/greyfloral_partial_transparent.png differ diff --git a/test/visual/blendimage_filter.js b/test/visual/blendimage_filter.js new file mode 100644 index 00000000000..4d690945d93 --- /dev/null +++ b/test/visual/blendimage_filter.js @@ -0,0 +1,94 @@ +(function() { + fabric.enableGLFiltering = false; + var _pixelMatch = pixelmatch; + if (fabric.isLikelyNode) { + var fs = global.fs; + _pixelMatch = global.pixelmatch; + } + var fabricCanvas = this.canvas = new fabric.Canvas(null, {enableRetinaScaling: false, renderOnAddRemove: false}); + var pixelmatchOptions = { + includeAA: false, + threshold: 0.01 + }; + fabric.Object.prototype.objectCaching = false; + + function getAbsolutePath(path) { + var isAbsolute = /^https?:/.test(path); + if (isAbsolute) { return path; }; + var imgEl = fabric.document.createElement('img'); + imgEl.src = path; + var src = imgEl.src; + imgEl = null; + return src; + } + + function getFixtureName(filename) { + var finalName = '/../fixtures/' + filename; + return fabric.isLikelyNode ? (__dirname + finalName) : getAbsolutePath('test/fixtures/' + filename); + } + + function getImage(filename, original, callback) { + if (fabric.isLikelyNode && original) { + try { + fs.statSync(filename); + } + catch (err) { + var dataUrl = original.toDataURL().split(',')[1]; + console.log('creating original for ', filename); + fs.writeFileSync(filename, dataUrl, { encoding: 'base64' }); + } + } + var img = fabric.document.createElement('img'); + img.onload = function() { + callback(img); + }; + img.onerror = function(err) { + console.log('Image loading errored', err); + }; + img.src = filename; + } + + QUnit.module('Blend image filter test', { + afterEach: function() { + fabricCanvas.clear(); + fabricCanvas.renderAll(); + } + }); + + var testName = 'Multiple applications of filter'; + QUnit.test(testName, function(assert) { + var done = assert.async(); + getImage(getFixtureName('greyfloral.png'), false, function(img) { + getImage(getFixtureName('greyfloral_partial_transparent.png'), false, function(backdrop) { + var image = new fabric.Image(img); + var backdropImage = new fabric.Image(backdrop); + image.filters.push(new fabric.Image.filters.BlendImage({image: backdropImage})); + image.applyFilters(); + + fabricCanvas.add(image); + fabricCanvas.renderAll(); + + var renderedCanvas = fabricCanvas.lowerCanvasEl; + + var width = renderedCanvas.width; + var height = renderedCanvas.height; + var totalPixels = width * height; + var imageDataCanvas = renderedCanvas.getContext('2d').getImageData(0, 0, width, height).data; + + image.applyFilters(); + fabricCanvas.renderAll(); + var imageDataCanvas2 = renderedCanvas.getContext('2d').getImageData(0, 0, width, height).data; + + var differentPixels = _pixelMatch(imageDataCanvas, imageDataCanvas2, null, width, height, pixelmatchOptions); + var percDiff = differentPixels / totalPixels * 100; + var okDiff = totalPixels * 0.01; + assert.ok( + differentPixels < okDiff, + testName + ' has too many different pixels ' + differentPixels + '(' + okDiff + ') representing ' + percDiff + '%' + ); + console.log('Different pixels:', differentPixels, '/', totalPixels, ' diff:', percDiff.toFixed(3), '%'); + done(); + }); + }); + }); +})();