Fix multiple applications of blend image filter with transparent images (#5121)

* Fix multiple applications of blend image filter with transparent images

* Add blend image filter visual test
This commit is contained in:
brandondong 2018-07-29 13:12:13 -07:00 committed by Andrea Bogazzi
parent 6353b09c5f
commit acb0b14010
3 changed files with 96 additions and 1 deletions

View file

@ -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];

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -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();
});
});
});
})();