使用JIMP着色

发布于 2025-02-07 04:29:43 字数 1639 浏览 1 评论 0 原文

我正在使用JIMP从文件夹中着色png图像,但是我会遇到错误:W和H必须是数字(第42行 - image.Color函数。)。这似乎应该是一个简单的操作,但是我发现的解决方案非常复杂。似乎JIMP是要走的路,但是显然它有一些我不熟悉的怪癖。

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]);
    }
}

任何提示都将不胜感激。 谢谢, 詹姆斯。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冰葑 2025-02-14 04:29:44

我对此做了一个破解,并提出了这个示例:

请注意,此代码需要在带有 .mjs 扩展的文件中,因为我们使用 import> import 语句而不是需要。您可以使用 .mjs 文件与 node inde index.mjs 的文件完全相同。如果您真的想使用需要,请使用 .js extension将导入更改为需要并命名文件。

import jimp from "jimp";
import fs from "fs";

// I wanted to make this example to use async/await properly with Jimp
// So that's why we are using util.promisify to convert fs.readdir
// into a function named readDir, which we can await on
import util from "util";
const readDir = util.promisify(fs.readdir);

// Colors for mix operations
const colors = [ 
    {r: 0, g: 255, b: 154, a: 1}, 
    {r: 255, g: 40, b: 108, a: 1}, 
    {r: 26, g: 172, b: 255, a: 1}, 
    {r: 255, g: 190, b: 171, a: 1}, 
    {r: 255, g: 239, b: 117, a: 1}, 
    {r: 137, g: 91, b: 255, a: 1} 
];

// Colorsnames for output file naming, these correspond to colors array
const colorNames = ['green', 'red', 'blue', 'orange', 'yellow', 'purple'];

// Define which color operations we want to do, using mix as an example
// https://www.npmjs.com/package/jimp#colour-manipulation
const operations = colors.map((c) => {
    return { apply: "mix", params: [c, 60 ]};
});

// Input and output folder names
const inputFolderName = "./ToColor";
const outputolderName = "./out";
const outputFileSuffix = "edited"; // Optional suffix for the output files

// We're using async/await, so must wrap top level code like this
// https://stackoverflow.com/questions/46515764/how-can-i-use-async-await-at-the-top-level
(async () => {

    // Get filenames of the png files in the specified folder
    let pngFileNames = await readDir(inputFolderName);

    // Optional filtering of only .png files
    pngFileNames = pngFileNames.filter((f) => f.includes(".png"));

    // Go through each file
    // Must use for...of loop here, because we have awaits inside the loop
    let i = 0;
    for (let fileName of pngFileNames) {

        // Optional output file name suffixing
        const outPutFileName = outputFileSuffix.length > 0 ? fileName.split('.').reduce((a, b) => `${a}_${outputFileSuffix}.${b}`) : fileName;

        // Make an actual Jimp image object from the file
        const jimpImage = await jimp.read(`${inputFolderName}/${fileName}`);

        // Make one new image per operation, so in total, we output colors.length * pngFileNames.length images
        let j = 0;
        for(let colorOperation of operations) {
            // Apply operation
            jimpImage.color([colorOperation]);

            // Write the edited image to out folder
            await jimpImage.writeAsync(`${outputolderName}/${colorNames[j]}_${outPutFileName}`);
            j++;
        }
        
        i++;
    }
    
})();

您的代码遇到了多个问题。关于阅读实际图像和有关使用JIMP库的许多问题存在一些问题,但是除非您要我,否则我不会经历所有图像。

您对JIMP文档是对的,但是...很糟糕。尤其是如果您一般与JavaScript有点新秀。

您最大的问题可能是您尝试创建新的JIMP图像对象的方式。 文档说使用 new Jimp(... )用于创建新的图像,这意味着如果您首先没有任何图像,则可以使用它。

但是,当您已经将图像放在某个文件夹中并想加载它们以使用JIMP编辑时,您需要使用 jimp.read(...)而不是使用。 jimp.read 是一个异步函数,这意味着即使尚未读取图像,代码的其余部分也将继续运行。因此,我们需要使用等待jimp.read ,您可以想到“暂停”程序,直到 jimp.read 实际上读取了图像。

在读取图像并将图像对象放入名为 jimpimage 的变量之后,我们将使用预定义操作 jimpimage.color() >,在这种情况下,我们使用 Mix 。此功能不是异步的,因此我们不必等待它。

最后,在将着色操作应用于图像之后,我们通过使用 writeasync 将图像保存到具有相同名称(和可选后缀)的指定输出文件夹。这是一个异步函数,因为它的名称暗示了它,因此我们必须等待 it。

程序运行后,您可以在指定的输出文件夹中找到修改的图像。

另请注意,JIMP将其中的一些文档委托,尤其是关于“颜色的东西”, tinycolor github github page 由于JIMP在引擎盖下使用TinyColor作为某些相关的实用程序。因此,如果您想知道是否可以使用“红色”一词,而不是“#ff0000”,那么TinyColor文档就有答案。

关于错误:W和H必须是数字 -Error;最有可能的原因是您用 var image = new Jimp(pngfiles [i]); 初始化了JIMP错误的图像。就像我说的那样,这是用于从头开始创建新图像,我指的是再次说,如果您使用此语法来创建新图像,则将其使用(其中前两个参数为 width height ,这不是在您的代码中给出的):

new Jimp(256, 256, (err, image) => {
  // this image is 256 x 256, every pixel is set to 0x00000000
});

我为您提供了一个简化的示例,说明了如何读取图像,将某些操作应用于它们,然后将修改后的图像写回某些文件夹。我将其余的留给你!

请问您是否有任何疑问,我现在是JIMP大师。

这些是我使用的测试图像:

​/oe6xy.png“ rel =” nofollow noreferrer“> ”

Allright I took a crack at it and came up with this example:

Note that this code needs to be in a file with .mjs extension, because we're using import statements instead of require. You can run .mjs file exactly the same way than normal .js files with node index.mjs. If you really want to use requires instead, change the imports to requires and name the file normally with .js extension.

import jimp from "jimp";
import fs from "fs";

// I wanted to make this example to use async/await properly with Jimp
// So that's why we are using util.promisify to convert fs.readdir
// into a function named readDir, which we can await on
import util from "util";
const readDir = util.promisify(fs.readdir);

// Colors for mix operations
const colors = [ 
    {r: 0, g: 255, b: 154, a: 1}, 
    {r: 255, g: 40, b: 108, a: 1}, 
    {r: 26, g: 172, b: 255, a: 1}, 
    {r: 255, g: 190, b: 171, a: 1}, 
    {r: 255, g: 239, b: 117, a: 1}, 
    {r: 137, g: 91, b: 255, a: 1} 
];

// Colorsnames for output file naming, these correspond to colors array
const colorNames = ['green', 'red', 'blue', 'orange', 'yellow', 'purple'];

// Define which color operations we want to do, using mix as an example
// https://www.npmjs.com/package/jimp#colour-manipulation
const operations = colors.map((c) => {
    return { apply: "mix", params: [c, 60 ]};
});

// Input and output folder names
const inputFolderName = "./ToColor";
const outputolderName = "./out";
const outputFileSuffix = "edited"; // Optional suffix for the output files

// We're using async/await, so must wrap top level code like this
// https://stackoverflow.com/questions/46515764/how-can-i-use-async-await-at-the-top-level
(async () => {

    // Get filenames of the png files in the specified folder
    let pngFileNames = await readDir(inputFolderName);

    // Optional filtering of only .png files
    pngFileNames = pngFileNames.filter((f) => f.includes(".png"));

    // Go through each file
    // Must use for...of loop here, because we have awaits inside the loop
    let i = 0;
    for (let fileName of pngFileNames) {

        // Optional output file name suffixing
        const outPutFileName = outputFileSuffix.length > 0 ? fileName.split('.').reduce((a, b) => `${a}_${outputFileSuffix}.${b}`) : fileName;

        // Make an actual Jimp image object from the file
        const jimpImage = await jimp.read(`${inputFolderName}/${fileName}`);

        // Make one new image per operation, so in total, we output colors.length * pngFileNames.length images
        let j = 0;
        for(let colorOperation of operations) {
            // Apply operation
            jimpImage.color([colorOperation]);

            // Write the edited image to out folder
            await jimpImage.writeAsync(`${outputolderName}/${colorNames[j]}_${outPutFileName}`);
            j++;
        }
        
        i++;
    }
    
})();

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.read is 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 use await jimp.read which you could think of like "pausing" the program until jimp.read has actually read the image.

After the image has been read and the image object lies into a variable named jimpImage, we call jimpImage.color() with the array of predefined operations, in this case we're using mix. This function is not asynchronous, so we don't have to await it.

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 to await it.

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 with var 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):

new Jimp(256, 256, (err, image) => {
  // this image is 256 x 256, every pixel is set to 0x00000000
});

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:

testimgs

And these are what the program output (remember the amount is only 60 and our base images have strong colors):

output

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文