Search code examples
node.jsgraphicsmagick

Why GraphicsMagick 1:1 color exchange with opaque & fill not work?


I try exchange one color in my png with node + GraphicsMagick.

My code:

const gm = require('gm');

gm('./in.png').fill('black').opaque('#ccffff').write('./out.png', (err) => {
        console.log("recolored file saved");
});

This script changes not only the color but also the content of the image!

How can I change the color only?

in.png in.png

out.png out.png


Solution

  • This color exchange 1:1 you can't do in gm (or imagemagick) there is another concept (details: https://legacy.imagemagick.org/Usage/color_basics/#replace)

    But you can this convert pixel by pixel:

    var fs = require('fs'),
        PNG = require('pngjs').PNG;
    
    console.log("run convert ...")
    
    fs.createReadStream('./in.png')
        .pipe(new PNG())
        .on('parsed', function() {
    
            for (var y = 0; y < this.height; y++) {
                for (var x = 0; x < this.width; x++) {
                    var idx = (this.width * y + x) << 2;
    
                    // exchange color
                    if(this.data[idx] == 204 && this.data[idx+1] == 255 && this.data[idx+2] == 255){
                        this.data[idx] = 255; // R
                        this.data[idx+1] = 0; // G
                        this.data[idx+2] = 0; // B
                    }
    
                }
            }
    
            this.pack().pipe(fs.createWriteStream('out.png'));
        });