Skip to content

Instantly share code, notes, and snippets.

@enesien
Last active October 23, 2023 18:49
Show Gist options
  • Save enesien/71b43dee4034d86d8ecee61e74649b02 to your computer and use it in GitHub Desktop.
Save enesien/71b43dee4034d86d8ecee61e74649b02 to your computer and use it in GitHub Desktop.
Resize images in any Typescript project within the client, including Capacitor native apps
interface ResizeOptions {
/**
* Desired width of the image.
*/
width: number;
/**
* Desired height of the image.
*/
height: number;
/**
* A number between 0 and 1 indicating image quality.
*
* @default 1
*/
quality?: number;
/**
* If true, will throw an error if a smaller image is passed in
* @default false
*/
throwOnSmaller?: boolean;
}
export const resizeImage = async (file: File, options: ResizeOptions): Promise<File> => {
return new Promise((resolve, reject) => {
if (!file.type.match(/image.*/)) {
return reject('Not an image');
}
if (file.type.match(/image\/gif/)) {
return reject('Cannot resize GIFs');
}
const image = document.createElement('img');
image.onload = () => {
const canvas = document.createElement('canvas');
const cleanup = () => {
image.remove();
canvas.remove();
}
canvas.width = options.width;
canvas.height = options.height;
if (options.throwOnSmaller && (image.width < options.width || image.height < options.height)) {
cleanup();
return reject('Image too small');
}
const ctx = canvas.getContext('2d');
if (!ctx) {
cleanup();
return reject('Could not create canvas context');
}
const smallestSide = Math.min(image.width, image.height);
const left = (image.width - smallestSide) / 2;
const top = (image.height - smallestSide) / 2;
ctx.drawImage(image, left, top, smallestSide, smallestSide, 0, 0, ctx.canvas.width, ctx.canvas.height);
canvas.toBlob((blob) => {
if (!blob) {
cleanup()
return reject('Could not create canvas blob');
}
resolve(new File([blob], file.name, {
type: 'image/jpeg',
lastModified: Date.now()
}));
cleanup();
}, file.type, options.quality || 1);
};
image.onerror = () => {
image.remove();
return reject('Failed to load image');
}
const reader = new FileReader();
reader.onerror = (e) => {
image.remove();
reject(`Could not read file: ${e.target?.error}`)
};
reader.onload = (evt) => {
if (!evt.target) {
image.remove();
return reject('Could not read file; no target');
}
image.src = evt.target.result as string;
};
reader.readAsDataURL(file);
})
};
@enesien
Copy link
Author

enesien commented Oct 23, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment