Skip to content

Commit

Permalink
ISSUE-6122 blurry image export (#6131)
Browse files Browse the repository at this point in the history
  • Loading branch information
asturur committed Feb 3, 2020
1 parent 426d1b8 commit a9f1fc3
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ breaking: LockScalingFlip with the scaling flip behaviour are missing now, maybe
breaking: Object.lockUniScaling is removed. Alternatives to get the same identical functionality with less code are being evaluated.
breaking: Canvas.onBeforeScaleRotate is removed, developers need to migrate to the event `before:transform

## [3.6.2]
- fix fabric.Object.toDataURL blurriness on images with odd pixel number [#6131](https://github.com/fabricjs/fabric.js/pull/6131)

## [3.6.1]
- fix(gradient, text): ISSUE-6014 ISSUE-6077 support percentage gradient in text [#6090](https://github.com/fabricjs/fabric.js/pull/6090)
Expand Down
13 changes: 8 additions & 5 deletions src/shapes/object.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -1717,7 +1717,8 @@
// skip canvas zoom and calculate with setCoords now.
boundingRect = this.getBoundingRect(true, true),
shadow = this.shadow, scaling,
shadowOffset = { x: 0, y: 0 }, shadowBlur;
shadowOffset = { x: 0, y: 0 }, shadowBlur,
width, height;

if (shadow) {
shadowBlur = shadow.blur;
Expand All @@ -1731,10 +1732,12 @@
shadowOffset.x = 2 * Math.round(abs(shadow.offsetX) + shadowBlur) * (abs(scaling.scaleX));
shadowOffset.y = 2 * Math.round(abs(shadow.offsetY) + shadowBlur) * (abs(scaling.scaleY));
}
el.width = boundingRect.width + shadowOffset.x;
el.height = boundingRect.height + shadowOffset.y;
el.width += el.width % 2 ? 2 - el.width % 2 : 0;
el.height += el.height % 2 ? 2 - el.height % 2 : 0;
width = boundingRect.width + shadowOffset.x;
height = boundingRect.height + shadowOffset.y;
// if the current width/height is not an integer
// we need to make it so.
el.width = Math.ceil(width);
el.height = Math.ceil(height);
var canvas = new fabric.StaticCanvas(el, {
enableRetinaScaling: false,
renderOnAddRemove: false,
Expand Down
Binary file added test/visual/golden/dataurl13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/visual/golden/dataurl14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/visual/golden/dataurl15.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/visual/golden/dataurl16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/visual/golden/dataurl2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/visual/golden/dataurl3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/visual/golden/objectsInActiveSelections.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 86 additions & 2 deletions test/visual/toDataURL.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
code: toDataURL1,
golden: 'dataurl1.png',
newModule: 'DataURL exports',
percentage: 0.09,
percentage: 0.10,
beforeEachHandler: function() {
fabric.Object.prototype.objectCaching = false;
}
Expand All @@ -74,7 +74,7 @@
test: 'Text to DataURL with shadow no offset',
code: toDataURL2,
golden: 'dataurl2.png',
percentage: 0.09,
percentage: 0.10,
});

function toDataURL3(canvas, callback) {
Expand Down Expand Up @@ -344,6 +344,90 @@
height: 300,
});

function toDataURLWithOddPixels(fabricCanvas, callback) {
var imgsrc =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGMAAABjAQMAAAC19SzWAAAABlBMVEUAAAD///+l2Z/dAAAAG0lEQVR4XmNABf+RwANqyI3KjcqNyo3KjcoBACFidLMGY3BLAAAAAElFTkSuQmCC';
var imageEl = fabric.util.createImage();
imageEl.onload = function() {
var fimg = new fabric.Image(imageEl);
callback(fimg.toDataURL());
};
imageEl.src = imgsrc;
}

tests.push({
test: 'images with odd pixels will render crisp',
code: toDataURLWithOddPixels,
// use the same golden on purpose
golden: 'dataurl13.png',
percentage: 0.09,
width: 99,
height: 99,
});

function toDataURLWithEvenPixels(fabricCanvas, callback) {
var imgsrc =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkAQMAAABKLAcXAAAABlBMVEUAAAD///+l2Z/dAAAAG0lEQVR4XmNABf+RwAfqy43KjcqNyo3KjcoBAEFzhKc6XssoAAAAAElFTkSuQmCC';
var imageEl = fabric.util.createImage();
imageEl.onload = function() {
var fimg = new fabric.Image(imageEl);
callback(fimg.toDataURL());
};
imageEl.src = imgsrc;
}

tests.push({
test: 'images with even pixels will render crisp',
code: toDataURLWithEvenPixels,
// use the same golden on purpose
golden: 'dataurl14.png',
percentage: 0.09,
width: 100,
height: 100,
});

function toDataURLWithOddPixelsStrokeWidth(fabricCanvas, callback) {
var imgsrc =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGMAAABjAQMAAAC19SzWAAAABlBMVEUAAAD///+l2Z/dAAAAG0lEQVR4XmNABf+RwANqyI3KjcqNyo3KjcoBACFidLMGY3BLAAAAAElFTkSuQmCC';
var imageEl = fabric.util.createImage();
imageEl.onload = function() {
var fimg = new fabric.Image(imageEl, { strokeWidth: 1, stroke: 'orange' });
callback(fimg.toDataURL());
};
imageEl.src = imgsrc;
}

tests.push({
test: 'images with odd strokeWidth will not render crisp',
code: toDataURLWithOddPixelsStrokeWidth,
// use the same golden on purpose
golden: 'dataurl15.png',
percentage: 0.09,
disabled: true,
width: 100,
height: 100,
});

function toDataURLWithOddPixelsStrokeWidthEven(fabricCanvas, callback) {
var imgsrc =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGMAAABjAQMAAAC19SzWAAAABlBMVEUAAAD///+l2Z/dAAAAG0lEQVR4XmNABf+RwANqyI3KjcqNyo3KjcoBACFidLMGY3BLAAAAAElFTkSuQmCC';
var imageEl = fabric.util.createImage();
imageEl.onload = function() {
var fimg = new fabric.Image(imageEl, { strokeWidth: 2, stroke: 'orange' });
callback(fimg.toDataURL());
};
imageEl.src = imgsrc;
}

tests.push({
test: 'images with even strokeWidth will render crisp',
code: toDataURLWithOddPixelsStrokeWidthEven,
// use the same golden on purpose
golden: 'dataurl16.png',
percentage: 0.09,
width: 100,
height: 100,
});

function testWrapper(test) {
var actualTest = test.code;
Expand Down

0 comments on commit a9f1fc3

Please sign in to comment.