Skip to content

Instantly share code, notes, and snippets.

@bohwaz
Created September 29, 2024 16:52
Show Gist options
  • Save bohwaz/7f283bf9c10ed74f052b8407e2c22670 to your computer and use it in GitHub Desktop.
Save bohwaz/7f283bf9c10ed74f052b8407e2c22670 to your computer and use it in GitHub Desktop.
Use OffscreenCanvas to resize images in javascript
<!DOCTYPE html>
<html>
<head>
<title>Javascript OffscreenCanvas image resize demo</title>
</head>
<body>
<h3>Select a file below to display its thumbnail</h3>
<input type="file" id="file" />
<figure id="preview"></figure>
<script>
/**
* Calculate new image width / height from a given image.
* If height is NULL, then the final image size will use the "width" parameter as max width or height.
* The other dimension will be calculated, maintaining the aspect ratio.
*/
function getNewImageSize(img, width, height = null)
{
if (height === null) {
if (img.width > img.height) {
height = Math.round(img.height * width / img.width)
}
else if (img.width == img.height) {
height = width;
}
else {
height = width;
width = Math.round(img.width * height / img.height);
}
if (img.width < width && img.height < height)
{
width = img.width, height = img.height;
}
}
width = Math.abs(width);
height = Math.abs(height);
return {width, height};
}
/**
* Resize a File object. Returns a promise. On success this promise will return a Blob object.
* Use FileReader.readAsDataURL to obtain a data URI from this blob.
*/
function resizeImage(file, max_width, max_height = null, quality = 'low')
{
if (typeof OffscreenCanvas === 'undefined') {
throw new Error('Your browser is unsupported');
}
if (!(file instanceof File)) {
throw new Error('Invalid file argument');
}
if (!file.type.match(/^image\//)) {
throw new Error('This file is not an image');
}
var url = (window.URL || window.webkitURL).createObjectURL(file);
return new Promise((resolve, reject) => {
let img = new Image;
img.onload = () => {
let n = getNewImageSize(img, max_width, max_height);
const canvas = new OffscreenCanvas(n.width, n.height);
canvas.imageSmoothingEnabled = true;
const context = canvas.getContext('2d');
context.imageSmoothingQuality = quality;
context.drawImage(img, 0, 0, img.width, img.height, 0, 0, n.width, n.height);
const o = {type: "image/webp", quality: 0.75};
const blob = canvas.convertToBlob(o).then((blob) => resolve(blob));
};
img.onerror = reject;
img.src = url;
});
}
const f = document.querySelector('#file');
const p = document.querySelector('#preview');
const fr = new FileReader;
fr.onload = () => {
p.innerHTML = '';
const img = new Image;
img.src = fr.result;
p.appendChild(img);
};
f.onchange = () => {
if (f.files.length != 1) {
return;
}
try {
resizeImage(f.files[0], 300, null, 'medium').then(blob => fr.readAsDataURL(blob));
}
catch (e) {
alert(e.message);
}
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment