Home/Image Compression using JavaScript in Retool

Image Compression using JavaScript in Retool

Published On: 24 June 2022.By .
  • General

Large image takes more space and time to load and thus needs to be compressed . The biggest trade-off in image compressing is depletion of image quality so a perfect compression is where image quality is acceptable and as well as its size is also considerably reduced . Compression can be of two type lossy and lossless , in lossless the image size is not compressed much but image quality is well preserved , counter to this in lossy compression the image size is compressed significantly but image quality is depleted and this loss is irreversible one can not get original image back from the resultant image . Earlier JPEG (Joint Photographic Experts Group) was used for lossy image compression but nowadays JPEG-2000 is used which provides support for both lossy and lossless compression .

Now let’s see how we can compress image using JavaScript in Retool :

This will be a lossy compression , and we will be using Canvas  to achieve the desired output .

Aim : To compress image before uploading it to any cloud server .

Uploading image on retool

-> Once image is uploaded on Retool we are fetching its details and processing it .

let dataUrl = 'data:'+fileInput1.files['0'].type+';base64,'+fileInput1.value[0];
let imageType = fileInput1.files['0'].type
let resolution = 400 // max width/height in pixels
let quality = .8 //quality can be between 0.00 to 1.00 here 0.8 means 80% of current quality

->After loading the image in JavaScript we  can compress its size in 2 ways , 1 either by reducing its size (height and width) or reducing pixels density

For reducing its height and width :

async function downscaleImage(
        dataUrl,  
        imageType,  // e.g. 'image/jpeg'
        resolution,  // max width/height in pixels
        quality   // e.g. 0.9 = 90% quality
    ) {

    // Create a temporary image so that we can compute the height of the image.
    const image = await getImage(dataUrl);
    const oldWidth = image.naturalWidth;
    const oldHeight = image.naturalHeight;
    console.log('dims', oldWidth, oldHeight);

    const longestDimension = oldWidth > oldHeight ? 'width' : 'height';
    const currentRes = longestDimension == 'width' ? oldWidth : oldHeight;
    console.log('longest dim', longestDimension, currentRes);

    if (currentRes > resolution) {
        console.log('need to resize...');

        // Calculate new dimensions
        const newSize = longestDimension == 'width' ? Math.floor(oldHeight / oldWidth * resolution) : Math.floor(oldWidth / oldHeight * resolution);
        const newWidth = longestDimension == 'width' ? resolution : newSize;
        const newHeight = longestDimension == 'height' ? resolution : newSize;
        console.log('new width / height', newWidth, newHeight);

        // Create a temporary canvas to draw the downscaled image on.
        const canvas = document.createElement('canvas');
        canvas.width = newWidth;
        canvas.height = newHeight;

if you want to conserve original height and width then we can skip this part of code .

->To reduce quality without compromising with its height and width :

    const image = await getImage(dataUrl);
    const oldWidth = image.naturalWidth;
    const oldHeight = image.naturalHeight;
    console.log('dims', oldWidth, oldHeight);

    // Create a temporary canvas to draw the downscaled image on.
    const canvas = document.createElement('canvas');
    canvas.width = oldWidth;
    canvas.height = oldHeight;

    // Draw the downscaled image on the canvas and return the new data URL.
    const ctx = canvas.getContext('2d');
    ctx.drawImage(image, 0, 0, oldWidth, oldHeight);
    const newDataUrl = canvas.toDataURL(imageType, quality);
    return newDataUrl;

 

->Complete code for compressing image without changing its width and height :

function getImage(dataUrl)
{
    return new Promise((resolve, reject) => {
        const image = new Image();
        image.src = dataUrl;
        image.onload = () => {
            resolve(image);
        };
        image.onerror = (el, err) => {
            reject(err.error);
        };
    });
}

async function downscaleImage(
        dataUrl,  
        imageType,  // e.g. 'image/jpeg'
        quality   // e.g. 0.9 = 90% quality
    ) {

    // Create a temporary image so that we can compute the height of the image.
    const image = await getImage(dataUrl);
    const oldWidth = image.naturalWidth;
    const oldHeight = image.naturalHeight;
    console.log('dims', oldWidth, oldHeight);

    // Create a temporary canvas to draw the downscaled image on.
    const canvas = document.createElement('canvas');
    canvas.width = oldWidth;
    canvas.height = oldHeight;

    // Draw the downscaled image on the canvas and return the new data URL.
    const ctx = canvas.getContext('2d');
    ctx.drawImage(image, 0, 0, oldWidth, oldHeight);
    const newDataUrl = canvas.toDataURL(imageType, quality);
    return newDataUrl;
}

let dataUrl = 'data:'+fileInput1.files['0'].type+';base64,'+fileInput1.value[0];
let imageType = fileInput1.files['0'].type
let quality = .3


let ds = downscaleImage(
        dataUrl,  
        imageType,  // e.g. 'image/jpeg'
        quality   // e.g. 0.9 = 90% quality
    )

return ds

Results :

Original Image :


Original Image

Size : 130.9 kB

Compressed Image  :

Size : 109.4 kB                                                          Quality : 0.8 (80% of original image…)

Compressed Image :

Size : 41.6 kB                                                             Quality : 0.3 (30% of original image…)

 

Related content

We Love Conversations

Say Hello
Go to Top