imagettftext() の中央寄せ、右寄せ

imagettftext() には中央寄せや右寄せなどの位置合わせの機能がないため、中央寄せや右寄せをするには imagettfbbox() で取得できる座標を利用して自力で調整する必要があります。

imagettfbox() の座標

imagettfbbox() で取得できる座標の配列 (0~7の8つの座標) は下記のような意味になっています。

imagettftext() で指定する x, y の原点は左下で imagettfbbox() もその前提になっているため、imagettfbbox() の [0], [1], [3] が 0 に近く、[5], [7] が負の値になっていることがよくあります。

位置の計算

上記の imagettfbox() の座標からテキストの幅・高さを算出して、指定エリアの座標をもとに位置を算出します。

下記は angle が 0 の場合の例です。また、矩形座標の原点は左上を前提としています。
  • テキスト幅 = imagettfbbox()[2 または 4] - imagettfbbox()[0 または 6]
  • テキスト高さ = imagettfbbox()[1 または 3] - imagettfbbox()[5 または 7]
  • 中央寄せ
    • x = 矩形座標x1 + ((矩形座標x2 - 矩形座標x1 - テキスト幅) / 2)
    • y = 矩形座標y1 + ((矩形座標y2 - 矩形座標y1 - テキスト高さ) / 2) - imagettfbbox()[5 または 7];
  • 右寄せ
    • x = 矩形座標x2 - テキスト幅

サンプルコード (9点対応)

左上、上、右上、左、中央、右、左下、下、右下 の 9点に対応した例です。 フォントにより (日本語など) 少しずれる場合があり、その場合は個別に調整が必要になるかもしれません。

<?php
// 位置定数
define('IMAGETTFTEXT_ALIGN_TOPLEFT'     , 1); // 左上
define('IMAGETTFTEXT_ALIGN_TOPCENTER'   , 2); // 上
define('IMAGETTFTEXT_ALIGN_TOPRIGHT'    , 3); // 右上
define('IMAGETTFTEXT_ALIGN_MIDDLELEFT'  , 4); // 左
define('IMAGETTFTEXT_ALIGN_MIDDLECENTER', 5); // 中央
define('IMAGETTFTEXT_ALIGN_MIDDLERIGHT' , 6); // 右
define('IMAGETTFTEXT_ALIGN_BOTTOMLEFT'  , 7); // 左下
define('IMAGETTFTEXT_ALIGN_BOTTOMCENTER', 8); // 下
define('IMAGETTFTEXT_ALIGN_BOTTOMRIGHT' , 9); // 右下

/**
 * TrueType フォントを使用して、指定されたエリア(矩形座標)の範囲にテキストを書き込みます。
 * ($angle は基本的に 0 を想定しています。細かい挙動の調整等はしていません)
 *
 * @param resource $image  画像リソース (imagettftext() と同じ)
 * @param float $size      ポイント数単位のフォントサイズ (同上)
 * @param float $angle     度で表される角度 (同上)
 * @param int $x1          矩形の左上の X 座標 (imagettftext() は左下のため注意してください)
 * @param int $y1          矩形の左上の Y 座標 (同上)
 * @param int $x2          矩形の右下の X 座標
 * @param int $y2          矩形の右下の Y 座標
 * @param int $color       カラーインデックス (imagettftext() と同じ)
 * @param string $fontfile 使用したい TrueType フォントへのパス (同上)
 * @param string $text     テキスト文字列 (同上)
 * @param int $pos         
 * @return void
 */
function imagettftext_align($image, $size, $angle, $x1, $y1, $x2, $y2, $color, $fontfile, $text, $pos = IMAGETTFTEXT_ALIGN_MIDDLECENTER) {
    $box = imageftbbox($size, $angle, $fontfile, $text); // テキストのバウンディングボックス
    $textWidth = $box[4] - $box[0]; // テキスト幅
    $textHeight = $box[1] - $box[5]; // テキスト高さ

    // Y 座標算出
    switch ($pos) {
        // 上
        case IMAGETTFTEXT_ALIGN_TOPLEFT:
        case IMAGETTFTEXT_ALIGN_TOPCENTER:
        case IMAGETTFTEXT_ALIGN_TOPRIGHT:
            $y = $y1 - $box[5];
            break;
        // 中央
        case IMAGETTFTEXT_ALIGN_MIDDLELEFT:
        case IMAGETTFTEXT_ALIGN_MIDDLECENTER:
        case IMAGETTFTEXT_ALIGN_MIDDLERIGHT:
            $y = $y1 + (($y2 - $y1 - $textHeight) / 2) - $box[5];
            break;
        // 下
        case IMAGETTFTEXT_ALIGN_BOTTOMLEFT:
        case IMAGETTFTEXT_ALIGN_BOTTOMCENTER:
        case IMAGETTFTEXT_ALIGN_BOTTOMRIGHT:
            $y = $y2 - $textHeight - $box[5];
            break;
    }
    // X 座標算出
    switch ($pos) {
        // 左
        case IMAGETTFTEXT_ALIGN_TOPLEFT:
        case IMAGETTFTEXT_ALIGN_MIDDLELEFT:
        case IMAGETTFTEXT_ALIGN_BOTTOMLEFT:
            $x = $x1;
            break;
        // 中央
        case IMAGETTFTEXT_ALIGN_TOPCENTER:
        case IMAGETTFTEXT_ALIGN_MIDDLECENTER:
        case IMAGETTFTEXT_ALIGN_BOTTOMCENTER:
            $x = $x1 + (($x2 - $x1 - $textWidth) / 2);
            break;
        // 右
        case IMAGETTFTEXT_ALIGN_TOPRIGHT:
        case IMAGETTFTEXT_ALIGN_MIDDLERIGHT:
        case IMAGETTFTEXT_ALIGN_BOTTOMRIGHT:
            $x = $x2 - $textWidth;
            break;
    }
    imagettftext($image, $size, $angle, $x, $y, $color, $fontfile, $text);
}

// -- テスト --

$width = 600; // 画像幅
$height = 300; // 画像高さ
$x1 = 0; // テキスト矩形 X 座標
$y1 = 0; // テキスト矩形 Y 座標
$x2 = $width - 1; // テキスト矩形 X 座標 2
$y2 = $height - 1; // テキスト矩形 Y 座標 2
$size = 30; // フォントサイズ
$text = 'ABCDE'; // テキスト
$fontfile = 'GenShinGothic-Normal.ttf'; // フォント (例では http://jikasei.me/font/genshin/ の源真ゴシック)

$image = imagecreatetruecolor($width, $height); // 画像リソース
$color = imagecolorallocate($image, 0x00, 0x00, 0x00); // 文字色
$back = imagecolorallocate($image, 0xff, 0xff, 0xff); // 背景色

imagefilledrectangle($image, 0, 0, $width, $height, $back); // 背景描画
imagerectangle($image, $x1, $y1, $x2, $y2, $color); // ガイド線描画
imagerectangle($image, $x1, $y1 / 2, $x2, $y2 / 2, $color); // 同上
imagerectangle($image, $x1 / 2, $y1, $x2 / 2, $y2, $color); // 同上

// 文字描画
imagettftext_align($image, $size, 0, $x1, $y1, $x2, $y2, $color, $fontfile, $text, IMAGETTFTEXT_ALIGN_TOPLEFT); // 左上
imagettftext_align($image, $size, 0, $x1, $y1, $x2, $y2, $color, $fontfile, $text, IMAGETTFTEXT_ALIGN_TOPCENTER); // 上
imagettftext_align($image, $size, 0, $x1, $y1, $x2, $y2, $color, $fontfile, $text, IMAGETTFTEXT_ALIGN_TOPRIGHT); // 右上
imagettftext_align($image, $size, 0, $x1, $y1, $x2, $y2, $color, $fontfile, $text, IMAGETTFTEXT_ALIGN_MIDDLELEFT); // 左
imagettftext_align($image, $size, 0, $x1, $y1, $x2, $y2, $color, $fontfile, $text, IMAGETTFTEXT_ALIGN_MIDDLECENTER); // 中央
imagettftext_align($image, $size, 0, $x1, $y1, $x2, $y2, $color, $fontfile, $text, IMAGETTFTEXT_ALIGN_MIDDLERIGHT); // 右
imagettftext_align($image, $size, 0, $x1, $y1, $x2, $y2, $color, $fontfile, $text, IMAGETTFTEXT_ALIGN_BOTTOMLEFT); // 左下
imagettftext_align($image, $size, 0, $x1, $y1, $x2, $y2, $color, $fontfile, $text, IMAGETTFTEXT_ALIGN_BOTTOMCENTER); // 下
imagettftext_align($image, $size, 0, $x1, $y1, $x2, $y2, $color, $fontfile, $text, IMAGETTFTEXT_ALIGN_BOTTOMRIGHT); // 右下

// 画像出力
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);

結果

結果

参考