Skip to content

Instantly share code, notes, and snippets.

@munkacsimark
Last active December 13, 2020 23:04
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 munkacsimark/6e4e332aaa935f0da103beab4e368d9f to your computer and use it in GitHub Desktop.
Save munkacsimark/6e4e332aaa935f0da103beab4e368d9f to your computer and use it in GitHub Desktop.
// Scales down image to given size
const MAX_SIZE = 200000; // bytes
const DOWNSIZING_STEP = 100; // px
const createBase64SrcFromFile = (file) =>
new Promise((resolve) => {
const reader = new FileReader();
reader.onload = (event) => resolve(event.target.result);
reader.readAsDataURL(file);
});
const createImageElementFromFile = (file) =>
new Promise(async (resolve) => {
const image = new Image();
image.onload = (event) => resolve(event.target);
image.src = await createBase64SrcFromFile(file);
});
const createCanvasWithImage = (imageElement) => {
const canvas = document.createElement("canvas");
canvas.width = imageElement.width;
canvas.height = imageElement.height;
const context = canvas.getContext("2d");
context.drawImage(imageElement, 0, 0, canvas.width, canvas.height);
return canvas;
};
const getFileFromCanvas = (canvas, type, name) =>
new Promise((resolve) => {
canvas.toBlob((blob) => resolve(new File([blob], name)), type);
});
const shrinkCanvas = (canvas, ratio) => {
const newCanvas = document.createElement("canvas");
if (canvas.width > canvas.height) {
if (canvas.width - DOWNSIZING_STEP <= 0) return canvas;
newCanvas.width = canvas.width - DOWNSIZING_STEP;
newCanvas.height = newCanvas.width / ratio;
} else {
if (canvas.height - DOWNSIZING_STEP <= 0) return canvas;
newCanvas.height = canvas.height - DOWNSIZING_STEP;
newCanvas.width = newCanvas.height * ratio;
}
const context = newCanvas.getContext("2d");
context.drawImage(canvas, 0, 0, newCanvas.width, newCanvas.height);
return newCanvas;
};
const shrinkImage = async (file) => {
const imageElement = await createImageElementFromFile(file);
const ratio = imageElement.width / imageElement.height;
let canvas = createCanvasWithImage(imageElement);
let newFile = null;
do {
const shrinkedCanvas = shrinkCanvas(canvas, ratio);
newFile = await getFileFromCanvas(canvas, file.type, file.name);
if (shrinkedCanvas.width === canvas.width) break;
canvas = shrinkedCanvas;
} while (newFile.size > MAX_SIZE);
return newFile;
};
export default shrinkImage;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment