How to Create an Image Compressor Website using pure JavaScript
Published: 2022-12-04 03:49:54

In this post, I will talk about creating a small Image Compressor website, if you prefer to watch a video on this topic rather reading this whole post, you can watch it below:

{%embed https://youtu.be/YYDGVBdDTQI %}

First, we will create three files **index.html, style.css & main.js**.
We will create **style.css** file inside a folder called **_css_** & **main.js** file inside a folder called **_js_**.

---

We will put following contents into **index.html** file:
```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Compressor</title>
    <link rel="stylesheet" href="css/style.css">
</head>

<body>
    <h1 class="heading">Image Compressor</h1>

    <div class="main_content">
        <input type="file" id="my_image">

        <span>Original Image</span>
        <div id="original_image_container"></div>
        <span>Compressed Image</span>
        <div id="compressed_image_container"></div>
    </div>

    <!-- JS -->
    <script src="js/main.js"></script>
</body>

</html>
```
Now, in above code, what I'm doing is creating an input element of type file to choose an image that we will later process & compress it.
I'm also adding two container divs, one for displaying the original image & other for displaying the compressed image.

---
Now, we will put the following contents in **css/style.css** file:
```css
@import url('https://fonts.googleapis.com/css2?family=Montserrat&display=swap');

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body,
button,
input {
    font-family: 'Montserrat', sans-serif;
}

.heading {
    text-align: center;
    background-color: #00b00f;
    color: #fff;
    padding: 1rem;
}

.main_content {
    width: 1000px;
    margin: 1rem auto;
    box-shadow: 0px 3px 3px #ccc;
    padding: 1rem;
    border-top: 3px solid #00b00f;
}

input {
    display: block;
    margin: 1rem;
}

#original_image_container,
#compressed_image_container {
    border: 1px solid #ff6600;
    padding: 1rem;
    margin: 1rem;
}

#compressed_image_container {
    cursor: pointer;
}
```
There is nothing to explain in above code, I'm just putting some basic CSS to style our website.

---
Now, we will put following contents into **js/main.js** file:
```javascript
const myImage = document.querySelector("#my_image");
const originalImageContainer = document.querySelector("#original_image_container");
const compressedImageContainer = document.querySelector("#compressed_image_container");

myImage.addEventListener("change", (evt) => {
    const image = evt.target.files[0];

    const reader = new FileReader();
    reader.onload = () => {
        const newImage = new Image();
        newImage.src = reader.result;
        newImage.onload = () => {
            const canvas = document.createElement('canvas');
            canvas.height = newImage.height;
            canvas.width = newImage.width;
            const ctx = canvas.getContext('2d');

            newImage.width = 150;
            originalImageContainer.appendChild(newImage);

            ctx.drawImage(newImage, 0, 0);

            const newUrl = canvas.toDataURL('image/jpeg', 0.5);

            compressedImageContainer.innerHTML = `<img src="${newUrl}" width="150" onclick="downloadImage(event)">`;
        };

    };
    reader.readAsDataURL(image);
});

const downloadImage = (evt) => {
    const a = document.createElement('a');
    a.download = 'compressed_image.jpeg';
    a.href = evt.target.src;
    a.target = '_blank';
    a.click();
};
```
So, in above code, I'm selecting all the HTML elements that we require here using **querySelector**.
I'm taking input element in myImage variable & attaching "change" event listener on it, so when someone will choose image using input element, it will fire "change" event handler defined in the above code.
In the handler, I'm taking the image that user selected using the following code:
```javascript
const image = evt.target.files[0];
```
After that, I'm creating an instance of FileReader API to read the image file as dataURL(base64 format).
```javascript
const reader = new FileReader();
reader.readAsDataURL(image);
```
Now, when FileReader API will finish reading the image, it will fire onload event handler & give it's base64 encoded dataURL in reader.result property.
Once, we have the base64 encoded format of image file that user has selected, we can create an image element from that dataURL.
Next, we will take that image and draw a canvas out of it, the main reason for drawing a canvas out of that image is to use a method of canvas that is **_toDataURL_** that take two parameters, first one it takes mime type & second it takes the quality of the image.
The lowest quality value is 0 and highest quality value is 1, so we will take its middle value to take the medium quality so that it will compress it and size will be less from original image.
In the following code, we can see that we are getting new dataURL of compressed image.
```javascript
const newUrl = canvas.toDataURL('image/jpeg', 0.5);
```
Now, using the dataURL of compressed image, we can display this on our website and also add a functionality to download this compressed image which size will be less from original image.

You can find the whole code on github [here](https://github.com/jp024556/image-compressor)

**Please note, the code given in this post can be further optimized to suit our needs, I just tried to show how to create core functionality of an Image Compressor just using pure JavaScript.**