HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

PHPで画像合成をしてみる

ふと、画像合成をしてみようとか思ったらしい(謎)。

環境構築

とは言っても、とりあえずWindows環境で試すので、php.iniの設定を変えるだけらしい。
やることは単純で、php.iniの以下の行のコメントをはずせばよい。

;extension=php_gd2.dll

編集が終わったら、Apacheの再起動。
phpinfoの中に「gd」が有効になっている旨が記述されていればOK。

使用する素材

なんか適当に作ってみた。(まぁ、赤丸と青丸はフォーマット違いの区別つかないけどな(謎))

png
gif
jpeg



画像合成スクリプト

一つのスクリプトで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>

結果はこんな感じ。


参考

直接関係はないけど、今回使った素材の作成の際に使った機能とか。