HomeTutorsContact

How to crop image in browser using JIMP?

By Gulshan Saini
Published in NodeJS
July 26, 2020
2 min read

I had a situation where I had no backend server to handle the crop and resizing of an image. I know of a few cloud services which could do this easily however they come with a cost. So I thought to implement the solution within the browser itself. Before we proceed, let we warn you that this might not be an optimal solution for a page with a lot of images and which might require the use of web worker to offload the task to worker threads.

So let’s start with the process of resizing the image using JIMP - The “JavaScript Image Manipulation Program” :-)

Step 1 - Load JIMP in browser

To load JIMP in browser we are going to use unpkg CDN. If you are not familiar with unpkg or how to load any npm package in browser, please refer to tutorial, How to load any npm module in browser

To load JIMP using unkpg, we create a script tag

<script src="https://unpkg.com/jimp@0.14.0/browser/lib/jimp.js"></script>

Step 2 - Define markup for the original and cropped image

Next, we create simple markup where original and cropped images will be loaded

<div id="container">
  <div id="before">
    <h3>Original</h3>
    <div class="image-container">
      <img src="" />
    </div>
  </div>
  <div id="afterCrop">
    <h3>After Crop</h3>
    <div class="image-container"><img src="" /></div>
  </div>
</div>

and little bit of styling :-)

body {
  font-family: sans-serif;
}

#container {
  display: flex;
}

#before,
#afterCrop {
  padding: 10px;
}

#before {
  background: lightcyan;
}

#afterCrop {
  background: powderblue;
}

span {
  position: absolute;
  color: #fff;
  background: #000;
  opacity: 0.4;
}

.image-container {
  border: 1px dashed grey;
  padding: 0;
  margin: 0;
}

Step 3 - Setting the source of the base image

Since we are going to use the same image source in HTML markup and JavaScript, I preferred to store the same in a JavaScript variable. In the future, if we want to change the image URL, it will be easy for us to swap this image with any other image by just changing the source at a single location.

const imageUrl =
  'https://images.unsplash.com/photo-1595303526913-c7037797ebe7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=640&q=80'

// handlers for before and after image elements
const before = document.querySelector('#before img')
const afterCrop = document.querySelector('#afterCrop img')

// load image for original container element
before.src = imageUrl

Step 4 - Read/Load image with JIMP

Now coming to the interesting stuff let’s play with JIMP to crop the image.

First, we need to load the image with Jimp.read() method that returns a promise.

Jimp.read({
  url: imageUrl,
})
  .then((image) => {
    // Crop logic goes here
  })
  .catch((error) => {
    console.log(`Error loading image -> ${error}`)
  })

The Jimp.read() return Jimp object. If we log the image variable on the console, returned by Jimp.read() method we should see output something similar to below image

Jimp read method output
Jimp read method output

Jimp prototype chain contains a method crop which we will use in the next step to crop the image.

Step 5 - Crop image

Once we have Jimp object, we can pass the x, y, w, h as arguments to define crop region inside image.crop() method which would return Promise.

// rest of code removed for brevity
...
.then((image) => {
  image.crop(80, 125, 100, 200)
})
...

Once the Promise to crop an image is resolved, we can use then() method to get the base64 image using the method getBase64(). The getBase64() method accepts, mime and callback as first and second arguments respectively.

// rest of code removed for brevity
...
.then((image) => {
  image.crop(80, 125, 100, 200)
    .then("image/png", (err, res) => {
      afterCrop.src = res;
    })
})
...

In the callback arrow function, we are setting a source of second image element that is stored in variable afterCrop.

Step 6 - Add the size of the image on top (optional)

This step is optional as I want to demonstrate how we can compare the size of the original with cropped one.

To display the dimension of the image, I used for loop to create a span element. The span element will be displayed on top of the existing images on the top left corner with the respective image size as the text.

// print width and height of each image
const images = document.querySelectorAll('img')
images.forEach((i) => {
  let img = new Image()
  img.src = i.src
  img.onload = function () {
    let span = document.createElement('span')
    let spanText = document.createTextNode(`${img.width}X${img.height}`)
    span.appendChild(spanText)
    i.insertAdjacentElement('beforebegin', span)
  }
})

Completed Code and output

const imageUrl =
  'https://images.unsplash.com/photo-1595303526913-c7037797ebe7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=640&q=80'

// handlers for before and after image elements
const before = document.querySelector('#before img')
const afterCrop = document.querySelector('#afterCrop img')

// load image for original container element
before.src = imageUrl

Jimp.read({
  url: imageUrl,
})
  .then((image) => {
    image.crop(80, 125, 100, 200).getBase64('image/png', (err, res) => {
      afterCrop.src = res

      // print width and height of each image
      const images = document.querySelectorAll('img')
      images.forEach((i) => {
        let img = new Image()
        img.src = i.src
        img.onload = function () {
          let span = document.createElement('span')
          let spanText = document.createTextNode(`${img.width}X${img.height}`)
          span.appendChild(spanText)
          i.insertAdjacentElement('beforebegin', span)
        }
      })
    })
  })
  .catch((error) => {
    console.log(`Error loading image -> ${error}`)
  })

Crop image vs original image JIMP output
Crop image vs original image JIMP output

As we can see the size of original image was 640x400 whereas the size of new image is 100x200

Output


Tags

#jimp#image-processing
Previous Article
How to open Visual Studio Code(VSCode) from terminal?

Related Posts

NodeJS
How to redirect http url request in server?
December 18, 2020
1 min
Gulshan Saini

Gulshan Saini

Fullstack Developer

Topics

Flutter
JavaScript
NextJS
ReactJS
Typescript

Subscribe to our newsletter!

We'll send you the best of our blog just once a month. We promise.
© 2021, All Rights Reserved.

Quick Links

Contact UsBrowserCSSPythonPuppeteer

Social Media