Created
September 29, 2024 16:52
-
-
Save bohwaz/7f283bf9c10ed74f052b8407e2c22670 to your computer and use it in GitHub Desktop.
Use OffscreenCanvas to resize images in javascript
This file contains hidden or 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
<!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