Wholesale replacing of pixel/spot colour in png.jpg/gif

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
dkierans

Wholesale replacing of pixel/spot colour in png.jpg/gif

Post by dkierans »

Hey guys/gals.

I have googled and googled and not found the killer answer.

I have a gif, jpg or png file in which I want to change every pixel that has RGB of say FFD2BB to FFAA44.
Can you point me to the a solution via the command line or perl wrapper? Also would there be a way to convert a range? Say...

Change every FFD2** to FFAA44?

I have millions of these files to change so any batch type tricks appreciated as well.


Now that I think of it I also have another problem.
I have a jpg or png with resolution of say 300 dpi. I want to convert to eps but I seem to loose the resolution according to identify after? I have tried density before/after reading etc but am now stuck. Can anyone help with a command line to change source.png to dest.eps and maintain resolution/DPI header info?

Thanks in advance.
Dave.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Wholesale replacing of pixel/spot colour in png.jpg/gif

Post by fmw42 »

I have a gif, jpg or png file in which I want to change every pixel that has RGB of say FFD2BB to FFAA44.
Can you point me to the a solution via the command line or perl wrapper?
convert input -fill "#FFAA44" -opaque "#FFD2BB" output
Also would there be a way to convert a range? Say...
Change every FFD2** to FFAA44?
The best you can do simply and directly as far as I know with IM is to use -fuzz to define a range of values within some color distance or percent. But there is no direct way to restrict -fuzz to just some red and green combination and any blue.

You might separate channels and then convert graylevels in each channel per what you want, then define the new blue channel graylevel you want and recombine.

Thus for example:

convert image.png -separate image_%d.png

results in image_0.png (red), image_1.png (green), image_2.png (blue)

Then (as your red channel is unchanged) and you just want a blue channel of 44 (not caring what it was before)

convert image_0.png \
\( image_1.png -fill "#AAAAAA" -opaque "#D2D2D2" \) \
\( image_2.png -threshold -1 -fill "#444444" -opaque white \) \
-combine output.png

(The -threshold -1 is just to convert everything in the blue channel to white so that I can change it to 44)
This is untested and may be way off base.
dkierans

Re: Wholesale replacing of pixel/spot colour in png.jpg/gif

Post by dkierans »

Perfect. Thank you very much. Script attached for anyone interested.

Code: Select all

#!/usr/bin/perl -w
use Image::Magick;

use strict;

#convert i.gif -fill "#FFD100" -opaque "#FF0099" o.gif

my $dirname = shift;
my $from = shift;
my $to   = shift;

opendir(BIN, $dirname) or die "Can't open $dirname: $!";
while ( defined (my $filename = readdir BIN) ) {
    next if $filename =~ /^\.\.?$/;     # skip . and ..
    next if $filename !~ /\.gif$/;     # skip non gif

    print "recolor($filename,$from,$to)\n";
    recolor($filename,$from,$to);
}

sub recolor
{   
    my $filename = shift;
    my $from     = shift;
    my $to       = shift;
    
    my $image = Image::Magick->new;

    $image->read($filename);

    $image->Opaque( color => $from, fill => $to, channel => 'all');
    
    $image->Write( $filename );
    undef $image;
    return 1;
}
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Wholesale replacing of pixel/spot colour in png.jpg/gif

Post by fmw42 »

can you post a link to any examples. I would certainly like to see what you are doing with this color mapping scheme.
Post Reply