Last active
April 28, 2023 09:00
-
-
Save dcollien/312bce1270a5f511bf4a to your computer and use it in GitHub Desktop.
Resize Images in the Browser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let hasBlobConstructor = typeof(Blob) !== 'undefined' && (function () { | |
try { | |
return Boolean(new Blob()); | |
} catch (e) { | |
return false; | |
} | |
}()); | |
let hasArrayBufferViewSupport = hasBlobConstructor && typeof(Uint8Array) !== 'undefined' && (function () { | |
try { | |
return new Blob([new Uint8Array(100)]).size === 100; | |
} catch (e) { | |
return false; | |
} | |
}()); | |
let hasToBlobSupport = (typeof HTMLCanvasElement !== "undefined" ? HTMLCanvasElement.prototype.toBlob : false); | |
let hasBlobSupport = (hasToBlobSupport || (typeof Uint8Array !== 'undefined' && typeof ArrayBuffer !== 'undefined' && typeof atob !== 'undefined')); | |
let hasReaderSupport = (typeof FileReader !== 'undefined' || typeof URL !== 'undefined'); | |
export default class ImageTools { | |
static resize(file, maxDimensions, callback) { | |
if (typeof maxDimensions === 'function') { | |
callback = maxDimensions; | |
maxDimensions = { | |
width: 640, | |
height: 480 | |
}; | |
} | |
let maxWidth = maxDimensions.width; | |
let maxHeight = maxDimensions.height; | |
if (!ImageTools.isSupported() || !file.type.match(/image.*/)) { | |
callback(file, false); | |
return false; | |
} | |
if (file.type.match(/image\/gif/)) { | |
// Not attempting, could be an animated gif | |
callback(file, false); | |
// TODO: use https://github.com/antimatter15/whammy to convert gif to webm | |
return false; | |
} | |
let image = document.createElement('img'); | |
image.onload = (imgEvt) => { | |
let width = image.width; | |
let height = image.height; | |
let isTooLarge = false; | |
if (width >= height && width > maxDimensions.width) { | |
// width is the largest dimension, and it's too big. | |
height *= maxDimensions.width / width; | |
width = maxDimensions.width; | |
isTooLarge = true; | |
} else if (height > maxDimensions.height) { | |
// either width wasn't over-size or height is the largest dimension | |
// and the height is over-size | |
width *= maxDimensions.height / height; | |
height = maxDimensions.height; | |
isTooLarge = true; | |
} | |
if (!isTooLarge) { | |
// early exit; no need to resize | |
callback(file, false); | |
return; | |
} | |
let canvas = document.createElement('canvas'); | |
canvas.width = width; | |
canvas.height = height; | |
let ctx = canvas.getContext('2d'); | |
ctx.drawImage(image, 0, 0, width, height); | |
if (hasToBlobSupport) { | |
canvas.toBlob((blob) => { | |
callback(blob, true); | |
}, file.type); | |
} else { | |
let blob = ImageTools._toBlob(canvas, file.type); | |
callback(blob, true); | |
} | |
}; | |
ImageTools._loadImage(image, file); | |
return true; | |
} | |
static _toBlob(canvas, type) { | |
let dataURI = canvas.toDataURL(type); | |
let dataURIParts = dataURI.split(','); | |
let byteString; | |
if (dataURIParts[0].indexOf('base64') >= 0) { | |
// Convert base64 to raw binary data held in a string: | |
byteString = atob(dataURIParts[1]); | |
} else { | |
// Convert base64/URLEncoded data component to raw binary data: | |
byteString = decodeURIComponent(dataURIParts[1]); | |
} | |
let arrayBuffer = new ArrayBuffer(byteString.length); | |
let intArray = new Uint8Array(arrayBuffer); | |
for (let i = 0; i < byteString.length; i += 1) { | |
intArray[i] = byteString.charCodeAt(i); | |
} | |
let mimeString = dataURIParts[0].split(':')[1].split(';')[0]; | |
let blob = null; | |
if (hasBlobConstructor) { | |
blob = new Blob( | |
[hasArrayBufferViewSupport ? intArray : arrayBuffer], | |
{type: mimeString} | |
); | |
} else { | |
let bb = new BlobBuilder(); | |
bb.append(arrayBuffer); | |
blob = bb.getBlob(mimeString); | |
} | |
return blob; | |
} | |
static _loadImage(image, file, callback) { | |
if (typeof(URL) === 'undefined') { | |
let reader = new FileReader(); | |
reader.onload = function(evt) { | |
image.src = evt.target.result; | |
if (callback) { callback(); } | |
} | |
reader.readAsDataURL(file); | |
} else { | |
image.src = URL.createObjectURL(file); | |
if (callback) { callback(); } | |
} | |
}; | |
static isSupported() { | |
return ( | |
(typeof(HTMLCanvasElement) !== 'undefined') | |
&& hasBlobSupport | |
&& hasReaderSupport | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
if (typeof exports === "undefined") { | |
var exports = {}; | |
} | |
if (typeof module === "undefined") { | |
var module = {}; | |
} | |
Object.defineProperty(exports, '__esModule', { | |
value: true | |
}); | |
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | |
var hasBlobConstructor = typeof Blob !== 'undefined' && (function () { | |
try { | |
return Boolean(new Blob()); | |
} catch (e) { | |
return false; | |
} | |
})(); | |
var hasArrayBufferViewSupport = hasBlobConstructor && typeof Uint8Array !== 'undefined' && (function () { | |
try { | |
return new Blob([new Uint8Array(100)]).size === 100; | |
} catch (e) { | |
return false; | |
} | |
})(); | |
var hasToBlobSupport = typeof HTMLCanvasElement !== "undefined" ? HTMLCanvasElement.prototype.toBlob : false; | |
var hasBlobSupport = hasToBlobSupport || typeof Uint8Array !== 'undefined' && typeof ArrayBuffer !== 'undefined' && typeof atob !== 'undefined'; | |
var hasReaderSupport = typeof FileReader !== 'undefined' || typeof URL !== 'undefined'; | |
var ImageTools = (function () { | |
function ImageTools() { | |
_classCallCheck(this, ImageTools); | |
} | |
_createClass(ImageTools, null, [{ | |
key: 'resize', | |
value: function resize(file, maxDimensions, callback) { | |
if (typeof maxDimensions === 'function') { | |
callback = maxDimensions; | |
maxDimensions = { | |
width: 640, | |
height: 480 | |
}; | |
} | |
var maxWidth = maxDimensions.width; | |
var maxHeight = maxDimensions.height; | |
if (!ImageTools.isSupported() || !file.type.match(/image.*/)) { | |
callback(file, false); | |
return false; | |
} | |
if (file.type.match(/image\/gif/)) { | |
// Not attempting, could be an animated gif | |
callback(file, false); | |
// TODO: use https://github.com/antimatter15/whammy to convert gif to webm | |
return false; | |
} | |
var image = document.createElement('img'); | |
image.onload = function (imgEvt) { | |
var width = image.width; | |
var height = image.height; | |
var isTooLarge = false; | |
if (width > height && width > maxDimensions.width) { | |
// width is the largest dimension, and it's too big. | |
height *= maxDimensions.width / width; | |
width = maxDimensions.width; | |
isTooLarge = true; | |
} else if (height > maxDimensions.height) { | |
// either width wasn't over-size or height is the largest dimension | |
// and the height is over-size | |
width *= maxDimensions.height / height; | |
height = maxDimensions.height; | |
isTooLarge = true; | |
} | |
if (!isTooLarge) { | |
// early exit; no need to resize | |
callback(file, false); | |
return; | |
} | |
var canvas = document.createElement('canvas'); | |
canvas.width = width; | |
canvas.height = height; | |
var ctx = canvas.getContext('2d'); | |
ctx.drawImage(image, 0, 0, width, height); | |
if (hasToBlobSupport) { | |
canvas.toBlob(function (blob) { | |
callback(blob, true); | |
}, file.type); | |
} else { | |
var blob = ImageTools._toBlob(canvas, file.type); | |
callback(blob, true); | |
} | |
}; | |
ImageTools._loadImage(image, file); | |
return true; | |
} | |
}, { | |
key: '_toBlob', | |
value: function _toBlob(canvas, type) { | |
var dataURI = canvas.toDataURL(type); | |
var dataURIParts = dataURI.split(','); | |
var byteString = undefined; | |
if (dataURIParts[0].indexOf('base64') >= 0) { | |
// Convert base64 to raw binary data held in a string: | |
byteString = atob(dataURIParts[1]); | |
} else { | |
// Convert base64/URLEncoded data component to raw binary data: | |
byteString = decodeURIComponent(dataURIParts[1]); | |
} | |
var arrayBuffer = new ArrayBuffer(byteString.length); | |
var intArray = new Uint8Array(arrayBuffer); | |
for (var i = 0; i < byteString.length; i += 1) { | |
intArray[i] = byteString.charCodeAt(i); | |
} | |
var mimeString = dataURIParts[0].split(':')[1].split(';')[0]; | |
var blob = null; | |
if (hasBlobConstructor) { | |
blob = new Blob([hasArrayBufferViewSupport ? intArray : arrayBuffer], { type: mimeString }); | |
} else { | |
var bb = new BlobBuilder(); | |
bb.append(arrayBuffer); | |
blob = bb.getBlob(mimeString); | |
} | |
return blob; | |
} | |
}, { | |
key: '_loadImage', | |
value: function _loadImage(image, file, callback) { | |
if (typeof URL === 'undefined') { | |
var reader = new FileReader(); | |
reader.onload = function (evt) { | |
image.src = evt.target.result; | |
if (callback) { | |
callback(); | |
} | |
}; | |
reader.readAsDataURL(file); | |
} else { | |
image.src = URL.createObjectURL(file); | |
if (callback) { | |
callback(); | |
} | |
} | |
} | |
}, { | |
key: 'isSupported', | |
value: function isSupported() { | |
return typeof HTMLCanvasElement !== 'undefined' && hasBlobSupport && hasReaderSupport; | |
} | |
}]); | |
return ImageTools; | |
})(); | |
exports['default'] = ImageTools; | |
module.exports = exports['default']; |
Here is an updated gist that adds another parameter, avatar, which takes an integer. If supplied, it will scale the image to the avatar parameter, and center-crop the image into a square. Use as ImageTools.resize(event.target.files[0], 90, {...}
'use strict';
if (typeof exports === "undefined") {
var exports = {};
}
if (typeof module === "undefined") {
var module = {};
}
Object.defineProperty(exports, '__esModule', {
value: true
});
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
var hasBlobConstructor = typeof Blob !== 'undefined' && (function () {
try {
return Boolean(new Blob());
} catch (e) {
return false;
}
})();
var hasArrayBufferViewSupport = hasBlobConstructor && typeof Uint8Array !== 'undefined' && (function () {
try {
return new Blob([new Uint8Array(100)]).size === 100;
} catch (e) {
return false;
}
})();
var hasToBlobSupport = typeof HTMLCanvasElement !== "undefined" ? HTMLCanvasElement.prototype.toBlob : false;
var hasBlobSupport = hasToBlobSupport || typeof Uint8Array !== 'undefined' && typeof ArrayBuffer !== 'undefined' && typeof atob !== 'undefined';
var hasReaderSupport = typeof FileReader !== 'undefined' || typeof URL !== 'undefined';
var ImageTools = (function () {
function ImageTools() {
_classCallCheck(this, ImageTools);
}
_createClass(ImageTools, null, [{
key: 'resize',
value: function resize(file, avatar = false, maxDimensions, callback) {
if (typeof maxDimensions === 'function') {
callback = maxDimensions;
maxDimensions = {
width: 640,
height: 480
};
}
var maxWidth = maxDimensions.width;
var maxHeight = maxDimensions.height;
if (!ImageTools.isSupported() || !file.type.match(/image.*/)) {
callback(file, false);
return false;
}
if (file.type.match(/image\/gif/)) {
// Not attempting, could be an animated gif
callback(file, false);
// TODO: use https://github.com/antimatter15/whammy to convert gif to webm
return false;
}
var image = document.createElement('img');
image.onload = function (imgEvt) {
var width = image.width;
var height = image.height;
var isTooLarge = false;
const getWidthHeight = function(img, side) {
const { width, height } = img;
if (width === height) {
return [0, 0, side, side];
} else if (width < height) {
const rat = height / width;
const top = ((side * rat) - side) / 2;
return [0, -1 * top, side, side * rat]
} else {
const rat = width / height;
const left = ((side * rat) - side) / 2;
return [-1 * left, 0, side * rat, side]
}
}
if (!avatar) {
if (width > height && width > maxDimensions.width) {
// width is the largest dimension, and it's too big.
height *= maxDimensions.width / width;
width = maxDimensions.width;
isTooLarge = true;
} else if (height > maxDimensions.height) {
// either width wasn't over-size or height is the largest dimension
// and the height is over-size
width *= maxDimensions.height / height;
height = maxDimensions.height;
isTooLarge = true;
}
if (!isTooLarge) {
// early exit; no need to resize
callback(file, false);
return;
}
}
var canvas = document.createElement('canvas');
canvas.width = avatar ? avatar : width;
canvas.height = avatar ? avatar : height;
var ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = 'high';
if (avatar) {
ctx.drawImage(image, ...getWidthHeight(image, 90));
} else {
ctx.drawImage(image, 0, 0, width, height);
}
if (hasToBlobSupport) {
canvas.toBlob(function (blob) {
callback(blob, true);
}, file.type);
} else {
var blob = ImageTools._toBlob(canvas, file.type);
callback(blob, true);
}
};
ImageTools._loadImage(image, file);
return true;
}
}, {
key: '_toBlob',
value: function _toBlob(canvas, type) {
var dataURI = canvas.toDataURL(type);
var dataURIParts = dataURI.split(',');
var byteString = undefined;
if (dataURIParts[0].indexOf('base64') >= 0) {
// Convert base64 to raw binary data held in a string:
byteString = atob(dataURIParts[1]);
} else {
// Convert base64/URLEncoded data component to raw binary data:
byteString = decodeURIComponent(dataURIParts[1]);
}
var arrayBuffer = new ArrayBuffer(byteString.length);
var intArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteString.length; i += 1) {
intArray[i] = byteString.charCodeAt(i);
}
var mimeString = dataURIParts[0].split(':')[1].split(';')[0];
var blob = null;
if (hasBlobConstructor) {
blob = new Blob([hasArrayBufferViewSupport ? intArray : arrayBuffer], { type: mimeString });
} else {
var bb = new BlobBuilder();
bb.append(arrayBuffer);
blob = bb.getBlob(mimeString);
}
return blob;
}
}, {
key: '_loadImage',
value: function _loadImage(image, file, callback) {
if (typeof URL === 'undefined') {
var reader = new FileReader();
reader.onload = function (evt) {
image.src = evt.target.result;
if (callback) {
callback();
}
};
reader.readAsDataURL(file);
} else {
image.src = URL.createObjectURL(file);
if (callback) {
callback();
}
}
}
}, {
key: 'isSupported',
value: function isSupported() {
return typeof HTMLCanvasElement !== 'undefined' && hasBlobSupport && hasReaderSupport;
}
}]);
return ImageTools;
})();
exports['default'] = ImageTools;
module.exports = exports['default'];
I'm just using this now: http://nodeca.github.io/pica/demo/
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks! Gracias por la solución!