Skip to content

Instantly share code, notes, and snippets.

@philippeauriach
Created December 1, 2019 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save philippeauriach/00123d6b660a0978d4cfa58f587703cd to your computer and use it in GitHub Desktop.
Save philippeauriach/00123d6b660a0978d4cfa58f587703cd to your computer and use it in GitHub Desktop.
Client side image resizing
/* eslint-env browser */
const hasBlobConstructor =
typeof Blob !== 'undefined' &&
(function() {
try {
return Boolean(new Blob());
} catch (e) {
return false;
}
})();
const hasArrayBufferViewSupport =
hasBlobConstructor &&
typeof Uint8Array !== 'undefined' &&
(function() {
try {
return new Blob([new Uint8Array(100)]).size === 100;
} catch (e) {
return false;
}
})();
const hasToBlobSupport = typeof HTMLCanvasElement !== 'undefined' ? HTMLCanvasElement.prototype.toBlob : false;
const hasBlobSupport =
hasToBlobSupport ||
(typeof Uint8Array !== 'undefined' && typeof ArrayBuffer !== 'undefined' && typeof atob !== 'undefined');
const 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,
};
}
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;
}
const image = document.createElement('img');
image.onload = () => {
let { width } = image;
let { height } = image;
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;
}
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, width, height);
if (hasToBlobSupport) {
canvas.toBlob(blob => {
callback(blob, true);
}, file.type);
} else {
const blob = ImageTools._toBlob(canvas, file.type);
callback(blob, true);
}
};
ImageTools._loadImage(image, file);
return true;
}
static _toBlob(canvas, type) {
const dataURI = canvas.toDataURL(type);
const 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]);
}
const arrayBuffer = new ArrayBuffer(byteString.length);
const intArray = new Uint8Array(arrayBuffer);
for (let i = 0; i < byteString.length; i += 1) {
intArray[i] = byteString.charCodeAt(i);
}
const mimeString = dataURIParts[0].split(':')[1].split(';')[0];
let blob = null;
if (hasBlobConstructor) {
blob = new Blob([hasArrayBufferViewSupport ? intArray : arrayBuffer], { type: mimeString });
} else {
const bb = new BlobBuilder();
bb.append(arrayBuffer);
blob = bb.getBlob(mimeString);
}
return blob;
}
static _loadImage(image, file, callback) {
if (typeof URL === 'undefined') {
const 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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment