src/utils/scaleImg.js
import EXIF from 'exif-js';
import {decode} from 'base64-arraybuffer';
import {cropImage} from './cropImage';
const REGULAR_EXPRESSION_BASE64 = /^data:([A-Za-z-+/]+);base64,(.+)$/;
function isBase64(url) {
return !!REGULAR_EXPRESSION_BASE64.test(url);
}
/**
* Reset the orientation of an image and return the image in base64
* Reference: https://stackoverflow.com/questions/20600800/js-client-side-exif-orientation-rotate-and-mirror-jpeg-images/31273162#31273162
* @param {String} srcBase64 Base64 uri of an image
* @param {Integer} srcOrientation Identify the orientation of an image
* @return {String} Base64 uri of an transformed image
*/
function resetOrientation(srcBase64, srcOrientation) {
let img = new Image();
return new Promise((resolve) => {
img.onload = function() {
let canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
// set proper canvas dimensions before transform & export
if (srcOrientation > 4 && srcOrientation < 9) {
canvas.width = this.height;
canvas.height = this.width;
} else {
canvas.width = this.width;
canvas.height = this.height;
}
// transform context before drawing image
switch (srcOrientation) {
case 2: ctx.transform(-1, 0, 0, 1, this.width, 0); break;
case 3: ctx.transform(-1, 0, 0, -1, this.width, this.height); break;
case 4: ctx.transform(1, 0, 0, -1, 0, this.height); break;
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
case 6: ctx.transform(0, 1, -1, 0, this.height, 0); break;
case 7: ctx.transform(0, -1, -1, 0, this.height, this.width); break;
case 8: ctx.transform(0, -1, 1, 0, 0, this.width); break;
default: break;
}
// draw image
ctx.drawImage(img, 0, 0, this.width, this.height);
let base64Url = ctx.canvas.toDataURL('image/png');
img = null;
canvas = null;
resolve(base64Url);
};
img.src = srcBase64;
});
}
/**
* Scales an image to the size passed by parameters and returns a URI
* with the new image encoded in base64
* @param {string} url Base64 URI of an image
* @param {number} width Desired width of the image
* @param {number} height Desired height of the image
* @return {Promise<string>} Base64 URI of a transformed image
* @private
*/
export function scaleImg(url, width = 128, height = 128) {
let type, data;
if (!window) {
return url;
}
return new Promise((resolve) => {
if (!isBase64(url)) {
return resolve();
}
[, type, data] = url.match(REGULAR_EXPRESSION_BASE64);
let exifdata = EXIF.readFromBinaryFile(decode(data));
if (exifdata) {
return resolve(exifdata.Orientation);
}
return resolve();
}).then((orientation) => {
if (orientation) {
return resetOrientation(url, orientation, type);
}
return url;
}).then(imageUrl => cropImage(imageUrl, width, height));
}