I am coloring png images from a folder using jimp, but I'm getting the error: w and h must be numbers (Line 42 - the image.color function.). This seems like it should be a simple operation but solutions I have found have been extremely complicated. It seems as though jimp is the way to go but obviously it has some quirks I'm not familiar with.
const { jimpEvChange } = require('@jimp/core');
const { write } = require('jimp');
const { composite } = require('jimp');
const jimp = require('jimp');
var fs = require('fs');
// create an array of 6 colors and specify the colors
const colors = [
['green'],
['red'],
['blue'],
['yellow'],
['purple'],
['orange']
];
// call functions to colorize the images
var pngFiles = GetPNGs("ToColor/");
for (var i = 0; i < pngFiles.length; i++) {
var image = new jimp(pngFiles[i]);
Colorize(image, colors[i]);
image.write(pngFiles[i]);
}
// get pngs from a folder "ToColor" and colorize them each using the colors array
function GetPNGs (folder) {
var pngFiles = [];
const newLocal = fs.readdirSync(folder);
var files = newLocal;
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (file.split(".").pop() == "png") {
pngFiles.push(folder + "/" + file);
}
}
return pngFiles;
}
// colorize the images
function Colorize (image, color) {
image.color([
{ apply: 'red', params: [color[0]] },
{ apply: 'green', params: [color[0]] },
{ apply: 'blue', params: [color[0]] }
]);
}
// loop through the images and colorize them
function ColorizeImages (pngs, colors) {
for (var i = 0; i < pngs.length; i++) {
var image = new jimp(pngs[i]);
Colorize(image, colors[i]);
image.write(pngs[i]);
}
}
Any tips would be much appreciated. Thanks, James.
Allright I took a crack at it and came up with this example:
Note that this code needs to be in a file with
.mjsextension, because we're usingimportstatements instead ofrequire. You can run.mjsfile exactly the same way than normal.jsfiles withnode index.mjs. If you really want to userequiresinstead, change the imports to requires and name the file normally with.jsextension.Your code had, well, multiple problems. There was some issues regarding reading the actual images and a multitude of issues regarding using the Jimp library, but I am not going to go through all of them unless you want me to.
You are right though about the Jimp documentations, it's... awful. Especially if you are somewhat rookie with JavaScript in general.
You biggest issue was probably how you tried to create new Jimp image objects. The documentation says that using
new Jimp(...)is for creating new images, which means that you would use it if you had no images anywhere in the first place.However, when you already have your images in some folder and want to load them up to edit with Jimp, you need to use
jimp.read(...)instead.jimp.readis an asynchronous function, which means that the rest of your code will continue running even if the image hasn't been read yet. For this reason we need to useawait jimp.readwhich you could think of like "pausing" the program untiljimp.readhas actually read the image.After the image has been read and the image object lies into a variable named
jimpImage, we calljimpImage.color()with the array of predefinedoperations, in this case we're usingmix. This function is not asynchronous, so we don't have toawaitit.Finally after we've applied the coloring operations to the image, we save the image to the specified output folder with the same name (and optional suffix) by using
writeAsync. This is an asynchronous function as the name of it implies, so we have toawaitit.After the program has finished running, you can find your modified images in the specified output folder.
Also note that Jimp delegates some of the documentation, especially regarding "color stuff", to TinyColor Github page, as Jimp uses TinyColor under the hood for certain color related utility stuff. So if you're wondering if you can use the word "red" instead of "#FF0000" for example, TinyColor documentation has the answer for that.
Regarding the
error: w and h must be numbers-error; most likely cause for it was that you initialized the images wrong for Jimp withvar image = new jimp(pngFiles[i]);. Like I said, this is for creating new images from scratch and I refer to the documentation again, which says that if you ARE using this syntax to create new images, it is used like this (where the first two parameters are the width and height, which were not given in your code):I've given you a simplified example of how to read images, apply some operations to them and write the modified images back to some folder. I'll leave the rest to you!
Do ask if you have any questions, I'm a Jimp master now.
These are the test images I used:
And these are what the program output (remember the amount is only 60 and our base images have strong colors):