Petr
Petr

Reputation: 1179

change colors in an animated gif in php

Is there any working example how to read an animated gif, change color of any pixel in any frame of it using GD library or ImageMagick and save it as an animated gif again?

I have been googling for it for 2 days and I did not found answer anywhere.

Edit: I have almost perfect solution. But some transparent (animated) gifs do not retain its transparency correctly (only part of the transparency is corrupted).

Source:

//helpful function

    /**
     * Make grayscale color
     * @param $color array('red'=>,'green'=>,'blue'=>);
     * @return array('red'=>,'green'=>,'blue'=>);
     */
    function transformColor($color) {
        $gst = $color['red']*0.15+$color['green']*0.5+$color['blue']*0.35;
        $color['red'] = $color['green'] = $color['blue'] = $gst;
         return $color;
    }  

//helpful function

    /**
     * Get the transparent color from GD resource.
     * If no tranpsarent color, all returned RGB values are -1
     * @param $rs GD resource
     * @return array('red'=>,'green'=>,'blue'=>)
     */
    function getTransparentColor($rs) {
        $transparentIndex = \ImageColorTransparent($rs);
        $transparentColor = NULL;

        if ($transparentIndex >= 0 && $transparentIndex < \ImageColorsTotal($rs)) {
            $transparentColor = @\ImageColorsForIndex($rs, $transparentIndex);
        }
        return $transparentColor ? $transparentColor : array('red' => -1,'green'=>-1,'blue'=>-1);
    }

// transform the GD resource with transparency // there is probably problem,because if I save frames alone, they have the problem with transparency described above

    function colorize($rs) {
        assert('gd' === \get_resource_type($rs));
            // you might want to create copy of the source here 
            // (instead of resource alias)
            $bild = $rs;

            //width
            $x = \imagesx($bild);
            // height
            $y = \imagesy($bild);

            $transparentIndex = \ImageColorTransparent($rs);
            $transparentColor = NULL;

            if ($transparentIndex >= 0 && $transparentIndex < \ImageColorsTotal($bild)) {

                $transparentColor = @\ImageColorsForIndex($rs, $transparentIndex);
            }

            \ImageSaveAlpha($bild, TRUE);
            \ImageAlphaBlending($bild, FALSE);

            $transparentNewIndex = NULL;
            $transparentNewColor = NULL;

            if (!empty($transparentColor)) {
                $transparentIndexNew = \ImageColorAllocate($bild, 255, 0, 255);
                \ImageColorTransparent($bild, $transparentIndexNew);
                $transparentColorNew = @ImageColorsForIndex($bild, transparentIndexNew);
            }
             // transform pixels
            for ($i = 0; $i < $y; $i++) {
                for ($j = 0; $j < $x; $j++) {
                    $index = \imagecolorat($rs, $j, $i);
                    $color = \imagecolorsforindex($rs, $index);
                    if ($index === $transparentIndex) {
                        $col = $transparentIndexNew;
                    } else {
                        $rgb = transformColor($color);
                        //TODO: we have a problem here, if $rgb ~= $transparentColorNew,
                        //      then this pixel will be transparent and not the desired  color
                        $col = \imagecolorresolvealpha($bild, $rgb['red'], $rgb['green'], $rgb['blue'], intval($color['alpha']));
                        if($col == $transparentIndexNew) {
                            //TODO: fix the color not to be transparent
                            // it do not die with the example gif 
                            //die('This might be a problem, but not the problem describlet above this example');
                        }
                    }
                    \imagesetpixel($bild, $j, $i, $col);
                }
            }

            return $bild;
        }

Upvotes: 2

Views: 1733

Answers (2)

S.Visser
S.Visser

Reputation: 4725

$file = "yourImage.gif";
$im = imagecreatefromgif ($file);

$index = imagecolorclosest ( $im,  255,255,255 ); // get your color (rgb)
imagecolorset($im,$index,92,92,92); // set new color (rgb)

$file= "yourResult.gif";
imagegif($im, $file); // save image as gif
imagedestroy($im);

I'm not sure if this works with a animated gif.

Upvotes: 1

Husman
Husman

Reputation: 6909

I believe that an animated GIF has multiple frames, so the algorithm for this would be to read the gif as multiple frames, change the pixel colours in each frame, and then save it again. Are you able to load an animated gif in GD?

Perhaps this library can help you to write the GIF image back: http://www.phpclasses.org/package/3163-PHP-Generate-GIF-animations-from-a-set-of-GIF-images.html

Upvotes: 1

Related Questions