タグ別アーカイブ: GD

GDで透過ありインデックスカラー画像を合成すると

前回エントリではインデックスカラー画像の合成を試みました。サンプルプログラムのように周囲に余白が無い画像の場合には期待通りの合成ができるのですが、たとえばimagerotate関数で45度傾けた長方形の場合などには、合成する画像の周囲の余白を透明部分として処理する方法が無く暗幕を被せたようになってしまいます。これは前回も触れたとおりです。
ではGDライブラリがインデックスカラーの透過色に全く対応していないかというと、そういうことでもないようです。画像編集ソフトで透過色ありの設定で保存したPNGを読み込むと、それはそのまま透過色ありの画像として扱われ、他の画像に合成しても透過の設定は残ります。例で見てみましょう。

<?php
$img = imagecreate(200,200);
$colour1 = imagecolorallocate($img, 255, 0, 255);
$colour2 = imagecolorallocate($img, 100, 90, 100);
imagefilledrectangle($img, 0, 160, 200, 200, $colour2);
$img2 = imagecreate(200,20);
$colour4 = imagecolorallocate($img2, 255, 255, 255);
$img3 = imagecreatefrompng("test.png");
$img4 = imagerotate($img4,90,$colour4,0);
imagecopy($img,$img4,10,0,0,0,150,200);
header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);
imagedestroy($img2);
imagedestroy($img3);
imagedestroy($img4);
?>

前回とほとんど変わらないプログラムです。新しく出てきた関数imagecreatefrompngはPNG画像を読み込んだキャンバスを作成するもので、他にimagecreategifなどもあるというのはご想像のとおりです。引数に同ディレクトリ内の透過色ありPNGを指定したのですが、結果このように表示されました。

(この部分の画像は000webhostに接収されてしまいました)

判りにくいのですが、元の透過PNGの透過設定が保持され、合成先画像のピンクの背景を突き抜けて透過しています。傾いた長方形の周囲の白い部分は、黒字の背景のページに設置すると黒になります。つまり合成先画像のカラーパレットと、透過色設定を含んだ合成元画像のカラーパレットを単純に結合したためこういう事態になっているということのようです。ちなみにimagerotate関数の引数4を0以外にしても見え方は変わりませんでした。
こうした仕様もあり、GDで複数の画像を合成して画像を作成する場合には、フルカラー画像を前提にしてプログラムを書いた方が予期せぬ壁に阻まれることがないだろう、という教訓も得られようというものです。


GDライブラリを用いてWEB表示用の画像を生成する

htmlコーダからのステップアップでPHPを習得したばかりという人間。クラスを活用したプログラムを書くのはまだ敷居が高いけれど、htmlをパッチワークのように切り貼りして作る練習ばかりではつまらない。そんな状況の人間には、GDライブラリを使ったグラフィックの生成にチャレンジすることをお勧めします。
何がそれほどまでにお勧めなのかというと、まず大抵のレンタルサーバにインストールされていて、ファイルの追加インストールの必要がないということ。includeする必要も無いので、サーバのphpパッケージのディレクトリパスも知っている必要がありません。そして重要なポイントとして、imgタグのsrc属性に指定したときに××.phpという指定が残るので、htmlの知識しか無い人間を当惑させることができるということ。少しだけ優越感に浸れて、PHPを勉強して良かったと思えるかもしれません。

<?php
$img = imagecreate(200,200);
$colour1 = imagecolorallocate($img, 255, 0, 255);
$colour2 = imagecolorallocate($img, 100, 90, 100);
imagefilledrectangle($img, 0, 160, 200, 200, $colour2);
$img2 = imagecreate(200,20);
$colour3 = imagecolorallocate($img2, 0, 0, 0);
$colour4 = imagecolorallocate($img2, 255, 255, 255);
$img3 = imagerotate($img2,90,$colour4,0);
imagecopy($img,$img3,10,0,0,0,20,200);
header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);
imagedestroy($img2);
imagedestroy($img3);
?>

基本的にはこのような流れで画像を作っていきます。細部の説明をしましょう。

まずimagecreate関数ですが、引数に画像サイズ(x,y)を与えて、画像を一時的に保存するメモリを確保する関数です。画像を描くキャンバスをサイズを決めて用意するというイメージで理解するのが良いかもしれません。インデックスカラー画像を作成する場合にこのimagecreate関数を使い、16ビットフルカラー画像の作成の場合にはimagecreatetruecolorという関数を使います。インデックスカラーとフルカラーの違いについてはこちらのエントリを参考にして下さい。

次にimagecolorallocate関数ですが、imagecreate関数で確保したメモリ領域(変数$imgで参照してます)を引数1に、その後の3つの引数はそれぞれ赤、緑、青を0〜255までの256段階で表し、混色しています。
さて、インデックスカラーでは使用する色は必ずカラーパレットで宣言されていなければいけないということを思い出して下さい。そうした仕様のため、imagecreate関数でメモリを確保したあと、最初に呼び出されたimagecolorallocate関数の色は、優先的に背景色としてアサインされます。勿論返り値を格納した変数は、キャンバス上に別の図形を描く際に呼び出して使うことも可能です。

さて、その次のimagefilledrectangle関数では、長方形を描画しています。引数はキャンバス、長方形の左上のx,y座標、右下のx,y座標、塗りつぶしの色という順番です。

下って出てくるimagerotateという関数は、引数1に与えたキャンバスを、反時計回りに引数2の角度回転させたものを返すという関数です。この例では90度回転なのでうまく余白部分が無しになっていますが、引数3にはキャンバスを回転させた余白部分の色、引数4には透過色を無視するかどうか(0以外の値で無視。デフォルトは0。省略可)を与えます。ちなみにこの引数4の設定は残念ながらインデックスカラーのキャンバスに定義した図形には適用できないので(透明色定義のimagecolortransparentが、フルカラーのキャンバスにしか対応していない)、ここでは無視して構いません。

imagecopy関数の引数は、コピー先キャンバス、コピー元キャンバス、コピー先x,y座標(左上)、コピー元x,y座標(左上)、コピー元x,y座標(右下)という順番です。コピー元x,y座標の指定次第で、部分コピーも可能です。

header関数では出力イメージのcontent-typeを指定して下さい。imagepng関数はPNG出力を、imagegif関数ならGIF出力をします。最後にimagedestroy関数で確保したメモリの解放をして終了します。出力されたイメージを見てみましょう。

(この部分のイメージは000webhostによって接収されてしまいました)

ピンク色の背景色にimagefilledrectangleで描いた灰色の長方形が置かれ、その上にimagecopyで合成された回転後の長方形が置かれていますね。

これでファイル名は××.phpながらイメージとしてコピー/ダウンロードできる画像が出来上がります。GDではさらに複雑な画像生成もできるので、プログラマ心を程よく刺激してくれる筈でしょう。