Search code examples
imagemagickimagickanimated-gif

How to multiply a color over every frame of a gif using Imagemagick


I've been trying to write an imagemagick command that takes an input gif, composite multiplies every frame by a hex color specified in the command (on all channels including transparency), and then saves that new gif.

The goal is to tint the whole gif by the color, and the transparent background becomes the target color. I've gotten it working with the Imagick library in PHP, but it was too slow with my environment and PHP version.

I've tried commands like magick input.gif -coalesce \( -size "300x311"\ xc:"#DEADFF" -compose multiply) output.gif

As well as other variations, composing outside of the () and things like that. The size is hard coded to the correct sizes. I've also tried using convert but nothing I've tried has worked or gotten very close.

The working, but slow, implementation in PHP is

$targetColor = "#DEADFF";
$imagePath = "input.gif";
$image = new Imagick($imagePath);
$colorImage = new Imagick();
$colorImage->newImage($image->getImageWidth(), $image->getImageHeight(), new ImagickPixel($targetColor));

foreach($image as $frame) {
        $frame->compositeImage($colorImage, Imagick::COMPOSITE_MULTIPLY, 0, 0, Imagick::CHANNEL_ALL);
}

header('Content-type: image/gif');
echo $image->getImagesBlob();

$image->clear();
$image->destroy();


Solution

  • Perhaps this will do what you want in Imagemagick. You need to use the null: separator and -layers composite.

    magick input.gif -coalesce null: \( -size "300x311" xc:"#DEADFF" \) -compose multiply -layers composite -layers optimize output.gif