Get colors from images in bulk with Node.js
Posted on September 25, 2021 in
3 min read
Today I need to extract the main or dominant colors from a bunch of images, thus, I created a script in Node.js to do that.
The process I encoded in order to use the script is something like:
- paste a list of image URLs in a txt file (that I grab from a spreadsheet)
- run the script
- get a list (in a .csv file) of the extracted colors in order to paste them on the original spreadsheet
The process might look rough but it works well and with a simple manual copy/paste I can easily decorate a spreadsheet with additional info that otherwise would be hard to integrate automatically.
The script
The Node.js script is quite simple because it uses a specific library for the color extraction task, which is colorthief
.
Let's prepare the input values:
const fs = require('fs')
const source = fs.readFileSync('./source.csv', 'utf-8')
const list = source.split('\n')
Next, I created a Promise based function to process in sequence all the images:
const process = (url) => {
return new Promise((resolve, reject) => {
const f = async () => {
const dominant = await ColorThief.getColor(url)
const palette = await ColorThief.getPalette(url, 5)
resolve({dominant, palette})
}
f()
})
}
The above function uses ColorThief to both extract the single dominant color and the main palette as well.
I've wrapped all the required promises in an array:
const allProms = list.map(url => process(url))
Now the main function in async mode in order to use the great await Promise.all()
command:
;(async () => {
const all = await Promise.all(allProms)
let csv = 'dominant,palette1,palette2,palette3,palette4,palette5\n'
all.forEach(pict => {
csv += rgb2hex(pict.dominant) + ','
pict.palette.forEach(p => {
csv += rgb2hex(p) + ','
})
csv += '\n'
})
fs.writeFileSync('./destination.csv', csv, 'utf-8')
})()
The above function also create the final csv file, saving it in the file system.
You should see also that there's a function to convert RGB value (this is the way ColorThief return the color value) to Hex value. You can skip it if RGB values are ok for you.
const rgb2hex = arr => {
const rs = arr.map(x => {
const y = parseInt(x).toString(16)
return y.length === 1 ? '0'+y : y
})
return '#' + rs.join('')
}
After run the script, you just need to open the destination.csv
to get the extracted values, each row related to each source image.