How to remove the background of an NFT image

After a few post on the authentication, wallet connection etc... I think it's time to make something a bit more "fun". Let's talk about removing the background of an NFT image. It's something that can be usefull when you want to make some banners, custom pfp from your favorites NFTs.

There are a lot of tools that can do that, bus most of the time if you want to this in batch it's not free and I wanted something that I can use without doing it via an application.

So I made a simple script that can do that. It's not perfect, but it's a good start.

How we do it and what we need

To remove the background of NFT it's pretty simple. We just need to identify the color of the backgroud and next replace it with a transparent color. To do this we take the first pixel of the image and next we check pixel by pixel if it's the same color. If it's the same color we replace it with a transparent color.

We will need to use two packages :

  • replace-color : As it's name suggest it replaces color with another one pixel by pixel
  • jimp : It's an image processing library for Node written entirely in JavaScript, with zero native dependencies.

The script

Let's start by creating a new folder and install the two packages.

mdkir nft-background-remover
cd nft-background-remover
npm install replace-color jimp

Next we create a new file called script.js and start by creating a function that will be call when we run the script. This function start by loading the image and after we get the color of the first pixel.

const jimp = require('jimp')
const replaceColor = require('replace-color')
async function removeBg() {
  try {
    const inputPath = './input.png'
    const image = await jimp.read(inputPath)
    const rgb = jimp.intToRGBA(image.getPixelColor(1, 1))
  } catch (error) {
    console.log(error)
  }
}
removeBg()

As you can see, jimp to load the image and we get the color of the first pixel by using image.getPixelColor(1, 1). The value returned for the pixel color it's a number that we need to convert to RGB with jimp.intToRGBA.

Next we replace the color with a transparent color and we save the new image.

const jimpObject = await replaceColor({
  image: inputPath,
  colors: {
    type: 'rgb',
    targetColor: [rgb.r, rgb.g, rgb.b],
    replaceColor: [255, 255, 255, 0],
  },
})

await jimpObject.write(outputPath, (err) => {
  if (err) return console.log(err)
})

We use replaceColor to replace the color with a transparent color. We pass the image path, the color to replace and the replacement color. In the replaceColor params we pass the color as an array of 4 values (R, G, B, A) with A between 0 and 1 this allow us to make the background transparant.

Replace color can also works with hex color as mentionned in the doc.

Run the script

To execute the script we just need to run node script.js and it will remove the background of the image.

Scale the script

Let's make the script able to remove the background of multiple images. We will start by listing all the files in the input folder and next we loop over them to remove the background of each image.

const fs = require('fs')
const fsPromises = fs.promises
const replaceColor = require('replace-color')

var path = require('path')
const jimp = require('jimp')

var INPUT_FOLDER = './input'
var OUTPUT_FOLDER = './output'

async function start() {
  const files = await fsPromises.readdir(INPUT_FOLDER)
  const errors = []
  for (let i = 0; i < files.length; i++) {
    const file = files[i]
    const inputPath = path.join(INPUT_FOLDER, file)
    const outputPath = path.join(OUTPUT_FOLDER, file.replace('jpg', 'png'))

    try {
      const image = await jimp.read(inputPath)
      const rgb = jimp.intToRGBA(image.getPixelColor(1, 1))

      const jimpObject = await replaceColor({
        image: inputPath,
        colors: {
          type: 'rgb',
          targetColor: [rgb.r, rgb.g, rgb.b],
          replaceColor: [255, 255, 255, 0],
        },
      })

      await jimpObject.write(outputPath, (err) => {
        if (err) return console.log(err)
      })
    } catch (error) {
      errors.push({ file, error })
    }
  }

  errors.length > 0 ? console.log('errors', errors) : console.log('done')
  console.log('-----------')
}
start()

Now you can remove the background of your favorites NFTs