fix an issue with incorrect scaling of png images

This commit is contained in:
or-else
2018-06-11 11:31:18 +03:00
parent 973b71eb80
commit 3829b26cc8
+43 -38
View File
@@ -137,22 +137,38 @@
'data:image/' + photo.type + ';base64,' + photo.data : null; 'data:image/' + photo.type + ';base64,' + photo.data : null;
} }
// Scale liner dimensions down to fit uder certain size. // Calculate linear dimensions for scaling image down to fit under a certain size.
function fitImageSize(width, height, maxWidth, maxHeight) { // Returns an object which contains destination sizes, source sizes, and offsets
// into source (when making square images).
function fitImageSize(width, height, maxWidth, maxHeight, forceSquare) {
if (!width || !height || !maxWidth || !maxHeight) { if (!width || !height || !maxWidth || !maxHeight) {
return null; return null;
} }
if (forceSquare) {
maxWidth = maxHeight = Math.min(maxWidth, maxHeight);
}
var scale = Math.min( var scale = Math.min(
Math.min(width, maxWidth) / width, Math.min(width, maxWidth) / width,
Math.min(height, maxHeight) / height Math.min(height, maxHeight) / height
); );
var size = {width: (width * scale) | 0, height: (height * scale) | 0}; var size = {
if (maxWidth == maxHeight) { dstWidth: (width * scale) | 0,
dstHeight: (height * scale) | 0,
};
if (forceSquare) {
// Also calculate parameters for making the image square. // Also calculate parameters for making the image square.
size.square = Math.min(width, height); size.dstWidth = size.dstHeight = Math.min(size.dstWidth, size.dstHeight);
size.xoffset = ((width - size.square) / 2) | 0; size.srcWidth = size.srcHeight = Math.min(width, height);
size.yoffset = ((height - size.square) / 2) | 0; size.xoffset = ((width - size.srcWidth) / 2) | 0;
size.yoffset = ((height - size.srcWidth) / 2) | 0;
} else {
size.xoffset = size.yoffset = 0;
size.srcWidth = width;
size.srcHeight = height;
} }
return size; return size;
} }
@@ -176,7 +192,7 @@
} }
// Convert uploaded image into a base64-encoded string possibly scaling // Convert uploaded image into a base64-encoded string possibly scaling
// linear dimensions. // linear dimensions or constraining to a square.
function imageFileScaledToBase64(file, width, height, forceSquare, onSuccess, onError) { function imageFileScaledToBase64(file, width, height, forceSquare, onSuccess, onError) {
var img = new Image(); var img = new Image();
img.crossOrigin = 'Anonymous'; img.crossOrigin = 'Anonymous';
@@ -184,28 +200,22 @@
onError("Image format unrecognized"); onError("Image format unrecognized");
} }
img.onload = function() { img.onload = function() {
var size = fitImageSize(this.width, this.height, width, height); var dim = fitImageSize(this.width, this.height, width, height, forceSquare);
if (!size) { if (!dim) {
onError("Invalid image"); onError("Invalid image");
return; return;
} }
var canvas = document.createElement('CANVAS'); var canvas = document.createElement("canvas");
if (forceSquare) { canvas.width = dim.dstWidth;
canvas.width = canvas.height = width; canvas.height = dim.dstHeight;
} else {
canvas.width = size.width;
canvas.height = size.height;
}
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = true; ctx.imageSmoothingEnabled = true;
if (forceSquare) { ctx.drawImage(this, dim.xoffset, dim.yoffset, dim.srcWidth, dim.srcHeight,
ctx.drawImage(this, size.xoffset, size.yoffset, size.square, size.square, 0, 0, dim.dstWidth, dim.dstHeight);
0, 0, canvas.width, canvas.height);
} else { var mime = (this.width != dim.dstWidth ||
ctx.drawImage(this, 0, 0, this.width, this.height, this.height != dim.dstHeight ||
0, 0, canvas.width, canvas.height); SUPPORTED_IMAGE_FORMATS.indexOf(file.type) < 0) ? "image/jpeg" : file.type;
}
var mime = (forceSquare || SUPPORTED_IMAGE_FORMATS.indexOf(file.type) < 0) ? "image/jpeg" : file.type;
var imageBits = canvas.toDataURL(mime); var imageBits = canvas.toDataURL(mime);
var parts = imageBits.split(','); var parts = imageBits.split(',');
// Get actual image type: 'data:image/png;base64,' // Get actual image type: 'data:image/png;base64,'
@@ -229,7 +239,7 @@
return; return;
} }
canvas = null; canvas = null;
onSuccess(imageBits.split(',')[1], mime, size.width, size.height, fileNameForMime(file.name, mime)); onSuccess(imageBits.split(',')[1], mime, dim.dstWidth, dim.dstHeight, fileNameForMime(file.name, mime));
}; };
img.src = URL.createObjectURL(file); img.src = URL.createObjectURL(file);
} }
@@ -3149,10 +3159,10 @@
attr.key = elementKey; attr.key = elementKey;
if (style == "IM") { if (style == "IM") {
// Additional processing for images // Additional processing for images
var size = fitImageSize(data.width, data.height, var dim = fitImageSize(data.width, data.height,
Math.min(this.props.viewportWidth - REM_SIZE * 4, REM_SIZE * 36), REM_SIZE * 24); Math.min(this.props.viewportWidth - REM_SIZE * 4, REM_SIZE * 36), REM_SIZE * 24, false);
attr.className = "inline-image"; attr.className = "inline-image";
attr.style = size ? { width: size.width + "px", height: size.height + "px" } : null; attr.style = dim ? { width: dim.dstWidth + "px", height: dim.dstHeight + "px" } : null;
attr.onClick = this.handlePreviewImage; attr.onClick = this.handlePreviewImage;
} }
return React.createElement(el, attr, values); return React.createElement(el, attr, values);
@@ -4037,15 +4047,10 @@
return null; return null;
} }
var instance = this; var instance = this;
var size = fitImageSize(this.props.content.width, this.props.content.height, var dim = fitImageSize(this.props.content.width, this.props.content.height,
this.state.width, this.state.height); this.state.width, this.state.height, false);
if (size) { var size = dim ? { width: dim.dstWidth + "px", height: dim.dstHeight + "px" } :
size.width += "px"; ((this.props.content.width > this.props.content.height) ? {width: '100%'} : {height: '100%'});
size.height += "px";
} else {
size = (this.props.content.width > this.props.content.height) ?
{width: '100%'} : {height: '100%'};
}
size.maxWidth = "100%"; size.maxWidth = "100%";
size.maxHeight = "100%"; size.maxHeight = "100%";