Skip to content

Instantly share code, notes, and snippets.

@vipertechofficial
Created May 4, 2022 12:43
Show Gist options
  • Save vipertechofficial/3fa5569972fddde19f8096b0d9e2c181 to your computer and use it in GitHub Desktop.
Save vipertechofficial/3fa5569972fddde19f8096b0d9e2c181 to your computer and use it in GitHub Desktop.
Resize Images in JavaScript in Web Worker with fallback using try catch to make it work on the main thread in old browser too
// CONST:
// imgd_data (you get img_data using a canvas, please get familiar with canvas)
// no_transparent (Boolean to know which file format to use)
// pxl_width (Simply width of the image)
// pxl_height (Simply height of the image)
// resize_width (Which size of width will it get at the end?)
try { // Can work in Web Worker so you can run it on a CPU thread different from the main one which doesn't freeze the UI
var imgd = null;
// imgd = new ImageData(pxl_width, pxl_height);
// imgd.data = imgd_data;
var canvas = new OffscreenCanvas(pxl_width, pxl_height);
var ctx = canvas.getContext('2d');
imgd = ctx.getImageData(0, 0, pxl_width, pxl_height);
var resize_ratio = resize_width / pxl_width;
var resizeWidth = parseInt(pxl_width * resize_ratio);
var resizeHeight = parseInt(pxl_height * resize_ratio);
var canvas2 = new OffscreenCanvas(resizeWidth, resizeHeight);
var ctx2 = canvas2.getContext("bitmaprenderer"); // "bitmaprenderer" context is available in web worker which isn't true for "2d" context
// Of course with a bitmaprenderer context we may need to create a bitmap image, this is how we do :
// 1) We create a Bitmap Image which will be transferred onto our canvas made for bitmap images
// 2) We convert the raster image into a file format we choose when we create a blob file (a file-like object)
// 3) We convert that file-like object into a dataurl which is base64 encoded image (data:image/png;base64,...and some base64)
// THIS IS MAGIC
return createImageBitmap(imgd, {
premultiplyAlpha: 'none',
colorSpaceConversion: 'none',
resizeWidth: resizeWidth,
resizeHeight: resizeHeight,
resizeQuality: "pixelated", // One of pixelated, low (default), medium, or high
}).then((btmp_i) => {
// And at once, we resized it before transfering it now onto the canvas context responsible for exporting it
ctx2.transferFromImageBitmap(btmp_i);
var blob_params = no_transparent ? {type: "image/jpeg", quality: 0.3}: {type: "image/png"}; // We can also export the image in webp format but just wrap it into a try catch because it isn't supported everywhere
// We call the canvas of our second context (canvas2) and ask the browser to create a blob (which is a file-like object of immutable, raw data)
return ctx2.canvas.convertToBlob(blob_params).then((blob) => {
// With it, we read the blob file as a data url you know (data:image/png;base64,...and some base64)
function blob_to_base64(blob) {
return new Promise((resolve, _) => {
var reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(blob);
})
}
return blob_to_base64(blob).then((data_url) => { // This we get a promise so we can call ".then()" to this function
return data_url;
});
});
});
}catch(e) { // Hopefully if OffscreenCanvas or such isn't supported we can use the classical method but it won't work in Web Worker my friend
var canvas = document.createElement("canvas");
canvas.width = pxl_width;
canvas.height = pxl_height;
var ctx = canvas.getContext('2d');
var imgd = null;
// imgd = new ImageData(pxl_width, pxl_height);
// imgd.data = imgd_data;
// ctx.putImageData(image_data, 0, 0);
var resize_ratio = resize_width / pxl_width;
var resizeWidth = parseInt(pxl_width * resize_ratio);
var resizeHeight = parseInt(pxl_height * resize_ratio);
// THIS IS NOT MAGIC, we just draw an image on our simple secondary canvas (but again it doesn't work off the main thread since it can't work in Web Worker)
var canvas2 = document.createElement("canvas");
canvas2.width = resizeWidth;
canvas2.height = resizeHeight;
var ctx2 = canvas2.getContext("2d");
ctx2.drawImage(canvas, 0, 0, resizeWidth, resizeHeight);
if(no_transparent){
return canvas2.toDataURL("image/jpeg", 0.3);
}else {
return canvas2.toDataURL("image/png");
}
// We can also export the image in webp format but just wrap it into a try catch because it isn't supported everywhere
}
// USEFULL TIPS: Use https://www.npmjs.com/package/workerpool combined with THIS ENSOULEMENT:
new Function(`return async function(param1, param2){}`)()(param1, param2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment