PHPで画像合成をしてみる
ふと、画像合成をしてみようとか思ったらしい(謎)。
環境構築
とは言っても、とりあえずWindows環境で試すので、php.iniの設定を変えるだけらしい。
やることは単純で、php.iniの以下の行のコメントをはずせばよい。
;extension=php_gd2.dll
編集が終わったら、Apacheの再起動。
phpinfoの中に「gd」が有効になっている旨が記述されていればOK。
画像合成スクリプト
一つのスクリプトで3つの画像ファイルに対応しようとして変な感じになっているけど、まぁサンプルということで。
<?php $ext = $_GET['ext']; $imgName1 = "blue.{$ext}"; $imgName2 = "red.{$ext}"; // 対象の画像ファイルに応じた関数を使ってimage resourceを生成する。 switch ($ext) { case 'png': $img1 = imagecreatefrompng($imgName1); $img2 = imagecreatefrompng($imgName2); break; case 'gif': $img1 = imagecreatefromgif($imgName1); $img2 = imagecreatefromgif($imgName2); break; case 'jpg': $img1 = imagecreatefromjpeg($imgName1); $img2 = imagecreatefromjpeg($imgName2); break; default: exit; } // 画像サイズ(画像タイプは自動判別) list($width1, $height1) = getimagesize($imgName1); list($width2, $height2) = getimagesize($imgName2); // ベースのimage resourceを生成して、背景をgrayに $baseImg = imagecreatetruecolor($width1 * 2 / 3 + $width2, max($height1, $height2)); $bgc = imagecolorallocate($baseImg, 128, 128, 128); imagefilledrectangle($baseImg, 0, 0, $width1 * 2 / 3 + $width2, max($height1, $height2), $bgc); // ベース画像に2枚の画像を順に合成 imagecopy($baseImg, $img1, 0, 0, 0, 0, $width1, $height1); imagecopy($baseImg, $img2, $width1 * 2 / 3, 0, 0, 0, $width2, $height2); // ゴミ掃除(1) imagedestroy($img1); imagedestroy($img2); // PNG形式で吐き出す header('Content-Type: image/png'); imagepng($baseImg); // ゴミ掃除(2) imagedestroy($baseImg); ?>
呼び出す側。
<html> <head> <meta charset="UTF-8" /> <title>PHP:GD test</title> </head> <body> <table> <tr> <th>PNG</th> <th>GIF</th> <th>JPG</th> </tr> <tr> <td><img src="gd-test1.php?ext=png" /></td> <td><img src="gd-test1.php?ext=gif" /></td> <td><img src="gd-test1.php?ext=jpg" /></td> </tr> </table> </body> </html>
こんな感じで表示される。JPEGは透過とかないから当然変な感じになるわな(謎)。
指定した位置にキャラを立たせる
例として、盤面にキャラ(雪だるま)を配置することを考えてみる。
- マスの中央に雪だるまを配置
- 交差点に雪だるまを立たせる
前者は、マスの対角線の交点が指定する座標になるわけだが、そこにキャラ画像の中心を合わせるケース。
後者は、交差点が指定する座標になるわけだが、そこにキャラ画像の足元がくるようにするケース。
盤面は、幅50、高さ100の長方形が並んでいる。
原点(0, 0)は左上、右下の座標は(49, 99)なので、対角線の交点は(24.5, 49.5)になる。
また、一番左の交差点は周囲の長方形の隙間になるので、その座標は(49.5, 99.5)になる。今回は見やすくするために左から3番目の交差点を使用。
プログラムはこんな感じで。
<?php $x1 = 24.5; $y1 = 49.5; $x2 = 149.5; $y2 = 99.5; date_default_timezone_set('Asia/Tokyo'); $boardImgPath = 'board.png'; $snowmanImgPath = 'snowman.png'; $boardImg = imagecreatefrompng($boardImgPath); $snowmanImg = imagecreatefrompng($snowmanImgPath); list($width, $height) = getimagesize($snowmanImgPath); // マスの中央に雪だるまを配置 imagecopy($boardImg, $snowmanImg, $x1 - $width / 2, $y1 - $height / 2, 0, 0, $width, $height); // 交差点に雪だるまを立たせる imagecopy($boardImg, $snowmanImg, $x2 - $width / 2, $y2 - $height, 0, 0, $width, $height); imagedestroy($snowmanImg); header('Content-Type: image/png'); imagepng($boardImg); imagedestroy($boardImg); ?>
呼び出し側。
<html> <head> <meta charset="UTF-8" /> <title>PHP:GD test</title> </head> <body> <img src="gd-test2.php" /> </body> </html>
結果はこんな感じ。
参考
直接関係はないけど、今回使った素材の作成の際に使った機能とか。
- Paint.NETを使用して、透過pngファイルを作成する。 - Symfoware
- Paint.NETで透過部分を指定する方法が分からなかったので。