アニメーションGIF合成のお話。

アニGIFを扱ったのがだいぶ前なので忘れてて今までファイル生成がうまくできなかったという・・・。
コメントってきちんと書いとくべきですよね・・・。
ついめんどくさくなってやらないことが多いので。
とりあえずなんとかできました。
すごくめんどくさい処理やってます。まずコードをごらんくだしあ。

//アニGIFを重ねるファイル。これはGIFでもjpgでもおk。
$image = new Imagick();
$image->readImage(ファイル先/ファイル名);
//今後の為にバイナリ保存。まぁ、もっかいreadImageでも別に悪くはないと思うんですけどなんとなく。
$binary = $image->getImagesBlob();
//今回の主役アニGIF君
$ani_image = new Imagick();
$ani_image->readImage($face_gif);

$max_frames = 0;
//まずこのアニGIFが何枚重なっているか調べます
foreach($ani_image as $img_ani){
  //フレーム数を取得
  $num = $img_ani->getNumberImages();
  if($num > $max_frames){
    //MAXフレーム数を取得
    $max_frames = $num;
  }
  unset($img_ani);
}

$i = 0;
foreach($ani_image as $img_ani){
 //アニGIFの枚数分合成
if($i >= $max_frames){
break;
}
 $img_ani->setImageIndex($i);
  if($i == 0){
    //アニGIFの1枚目だったら
    $pose_image->compositeImage ( $img_ani , imagick::COMPOSITE_OVER , 0 , 0 );
    //アニGIFの遅延設定
    $pose_image->setImageDelay(50);// アニメーションディレイの設定
    $pose_image->setImageIterations(0);// アニメーションループの設定(0だとループ設定)
  }else{
    //2枚目以降
    $avatar_b = new Imagick();
    //-- 画像を重ねていく
    $avatar_b->readImageBlob( $pose_binary );
    $avatar_b->compositeImage ( $img_ani , imagick::COMPOSITE_OVER , 0 , 0 );
    $avatar_b->setImageDelay(50);// アニメーションディレイの設定
    $pose_image->addImage($avatar_b);
    //使いまわすから消すらしい
    $avatar_b->destroy();
  }
  $pose_image->writeImages("./face_img/swf/{$i}.gif", true) ;
  $i++;
  unset($img_ani);
}
//最適化したい。
// 一度結果画像を書き出す
$file_name1 = "ファイル場所/ファイル名.gif.MIFF";
$file_name2 = "ファイル場所/ファイル名.gif";

$pose_image->writeImages($file_name1, true) ;
// Quantizeが使えないので保存ファイルをconvert +mapに通す
exec("/usr/local/bin/convert {$file_name1} -layers OptimizeTransparency +map {$file_name2}") ;
$pose_image->destroy();
//別ファイルにしたい時はこの下もいるかもです。
//特に問題なければ$file_name2の場所が完成品です
$pose_image = new Imagick();
$pose_image->readImage( $file_name2 );
unlink($file_name1);
unlink($file_name2);

$pose_image->writeImages("ファイル場所/ファイル名.gif", true) ;

とまぁ、ここまでがコードなわけですが、
素材画像は↓の2つで、

これがgifを合成するjpg画像。(22.7KB)


これがアニgif。(30.1KB)
この2つを合成していきます。

まず1コマ目を普通に合成。(これで48.4KB)

1枚目の上に2コマ目をjpgと合成した状態で重ねる。
(普通に2枚分のサイズなので96.8KBです)
もともと大きさが251×250のjpgを合成してますが、それがGIFに変わるのでサイズが・・・。
これを携帯で表示させようと思うとぎりぎりになります。

convert後の画像。これが一応完成品です。
画像によってサイズはいろいろ変わると思いますがこれは71.2KBになりました。
アニGIF自体2コマしかないので25KBしか減ってないですが、
もう少し容量の少ない画像で4コマ分合成をしてみると容量がだいぶ削れた・・・ハズ。
いろいろ試しながらやってみてください。私は必死にグーグル先生にお願いしてました。
これの難点はかならずファイル書き出しを行ってからconvertしなければいけないところ・・・。
あとconvertしても結構2枚目にゴミが残っていて、物によってはすごくクオリティが低く感じます・・。
できればファイル書き出しとかせずにクオリティを維持してやりたいですぉ・・。

今はImagick2.0なのでImagick3.0とかバージョンが上がったらいい感じになったりするのかしら。