OpenPNE のサムネイル作成で透過画像が壊れることへの対応

本エントリに記載されているソースでは対応として不十分であり、結果としてバグが残ります。
OpenPNE のサムネイル作成で透過画像が壊れることへの対応 その2でさらに対応したソースも記載していますので、両方合わせてご覧ください。
2.10のどこかのバージョンで本エントリの内容が公式のソースに取り込まれていますので、
OpenPNE のサムネイル作成で透過画像が壊れることへの対応 その2で記載している対応をするだけでOKです。
それ以前のバージョンでは本エントリの内容を適用し、そのあとで
OpenPNE のサムネイル作成で透過画像が壊れることへの対応 その2の内容を適用してください

 

OpenPNEの旧バージョンでも起こるっぽいですが、ソース確認してないので分かりません。
このエントリは、2.10.0 をベースに書いています。
また、画像処理をImageMagickではなく、GDを使うようになっている場合に起こります。

処理としては、以下の流れになっている。

  1. 画像をアップロードする
  2. 1でアップロードした画像のサムネイルを表示するタイミングで、サムネイル画像がすでに生成されているかチェックする
  3. 2でサムネイル画像がない場合は、作成する
  4. 画像を表示する

このとき、GIFおよびPNG(PNG-8)で透過画像の場合、他で記述されているソースにはいろいろと処理が書かれているが、上記のフローで実行される処理にはその処理が含まれていない。

現状は、新しいイメージリソースを作成(imagecreatetruecolorをコール)して、サムネイルを作る(imagecopyresampledをコールする)しかやっていない。

このため、透過画像の場合に透過色部分がぶっ壊れておかしくなる。
これを解決する方法は以下の通り。

wabapp/lib/OpenPNE/Img.php の369~371行目は以下のようになっている。

$output_gdimg = imagecreatetruecolor($o_width, $o_height);
imagecopyresampled($output_gdimg, $source_gdimg,
        0, 0, 0, 0, $o_width, $o_height, $s_width, $s_height);


これを以下のように書き換える

$output_gdimg = imagecreatetruecolor( $o_width, $o_height );

if( ($this->output_format=='gif' ) || ($this->output_format=='png') )
{
    $trnprt_idx_s = imagecolortransparent( $source_gdimg );
    if( $trnprt_idx_s >= 0){
        imagetruecolortopalette($output_gdimg, true, 256);
        $trnprt_color = imagecolorsforindex( $source_gdimg, $trnprt_idx_s );
        imagecolorset( $source_gdimg, 0, $trnprt_color['red'], $trnprt_color['green'],$trnprt_color['blue']);
        imagefill( $output_gdimg, 0, 0, 0 );
        imagecolortransparent( $output_gdimg, 0);
    }else
    if( $this->$this->output_format == 'png' )
    {
        imagealphablending($output_gdimg, false);
        $color = imagecolorallocatealpha($output_gdimg, 0, 0, 0, 127 );
        imagefill($output_gdimg,0, 0, $color);
        imagesavealpha($output_gdimg, true);
    }
}

imagecopyresampled($output_gdimg, $source_gdimg,
        0, 0, 0, 0, $o_width, $o_height, $s_width, $s_height);


やっていることは、以下の通り。

  • GIFかPNGかどうか調べる
  • 透過色が設定されているかどうか調べる
  • 新画像を256色パレットモードにする
  • 元画像の透過色に設定されている色(RGB)を取得
  • 新画像に上記色を作成
  • 作成した色で画像を塗りつぶす
  • 作成した色を透過色に設定する

2番目の処理で設定されていない場合のPNGはPNG-24かもしれないので、そのための処理をelseで行っている。

  • アルファブレンディングモードをOFFにする
  • 透過色を作る
  • 透過色で塗りつぶす
  • アルファチャンネルで塗りつぶす


256色パレットモードにしない場合、なぜか透過色の設定がうまくいかなかった。

imagecreatetruecolorで作ったままの画像をみたのだけど、RGBが同じ数値の色がインデックスの0と1に設定されている。
つまり色は同じなんだけどパレットが異なるものがあるということに。
そのせいで透過色に設定すると使われていない方のパレットインデックスが透過色に設定されてしまうのです。

とりあえず256色モードにするとなぜかこれが解決された。
GDの元のソース自体を見てみないといかんかな?と思っているのだけど。
サムネイル画像がぶっこわれるのは回避できているので、とりあえず良しとする。

webapp/lib/util/image.php にある画像リサイズ関数には上記のような透過色設定する処理が書かれている。

この処理が足りない件は、
バグとして報告してある。

 

カテゴリ: , ,

関連する記事

この記事に関連する記事は、0 件です。

トラックバック

このブログ記事に対するトラックバックURL
http://fakelife.info/mt/system/mt-tb.cgi/51

コメントする


画像の中に見える文字を入力してください。