是否有任何工作示例如何读取动画gif,使用GD库或ImageMagick更改其任何帧中任何像素的颜色并再次将其另存为动画gif?
我已经谷歌搜索了2天,我没有在任何地方找到答案。
编辑: 我有几乎完美的解决方案。但是一些透明(动画)的GIF不能正确保持透明度(只有部分透明度被破坏)。
来源:
GIFEncoder类:http://www.phpclasses.org/package/3163-PHP-Generate-GIF-animations-from-a-set-of-GIF-images.html
require_once('GIFEncoder.class.php');
require_once('GifFrameExtractor-master/src/GifFrameExtractor/GifFrameExtractor.php');
$gifFilePath = "input.gif";
// check this is an animated GIF
if (!\GifFrameExtractor\GifFrameExtractor::isAnimatedGif($gifFilePath)) {
\die('not an namiated image');
}
$gfe = new \GifFrameExtractor\GifFrameExtractor();
$gfe->extract($gifFilePath);
// frames as a GD source
$frameImages = $gfe->getFrameImages();
$frameDurations = $gfe->getFrameDurations();
// color used as a transparent color, if any
$tColor = array('red' => -1,'green'=>-1,'blue'=>-1);
foreach($frameImages as $i => $gdSource) {
// do something with gdSource
colorize($gdSource);
if($i == 0) {
//get the color used as transparent
// should be for any frame the same
$tColor = getTransparentColor($gdSource);
}
//GIFEncoder works only with binary data or files
//It cant work with gd source
//Therfore i output the gd source to stdout, catch it
//and use it as binary data.
//It could be memory consuming, so you might write the
//frames as a file and then use them instead of binary data.
\ob_start(); // catch output
\imagegif($gdSource); // write binary data to output
$frameImages[$i] = \ob_get_contents(); //replace GD source by the binary data
\ob_end_clean();
}
// create animated gif
$gif = new \GIFEncoder(
$frameImages, //binary data (or path to images on file system)
$frameDurations,
0, // infinite loop
2, // dont know what is this for (number 0-3 or -1 to ignore)
$tColor['red'], $tColor['green'], $tColor['blue'],
'bin' // or 'url' if $frameImages is array of paths to images on file system
);
// write image to file system
\FWrite ( \FOpen ( "output.gif", "wb" ), $gif->GetAnimation ( ) );
// send image to browser
//Header ( 'Content-type:image/gif' );
//echo $gif->GetAnimation ( );
//有用的功能
/**
* 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;
}
//有用的功能
/**
* 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);
}
//使用透明度转换GD资源 //可能存在问题,因为如果单独保存帧,则会出现上述透明度问题
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;
}
答案 0 :(得分:1)
我认为动画GIF有多个帧,因此算法是将gif作为多个帧读取,更改每个帧中的像素颜色,然后再次保存。你能在GD中加载动画gif吗?
也许这个库可以帮助您回写GIF图像:http://www.phpclasses.org/package/3163-PHP-Generate-GIF-animations-from-a-set-of-GIF-images.html
答案 1 :(得分:1)
$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);
我不确定这是否适用于GIF动画。