【PHP】GDライブラリでロゴみたいなやつをつくってみた


はじめに

PHPのGDライブラリを使用することで図形を描いて画像( .png.jpg など)を
作成することができる機能があるので簡単なロゴみたいなものを作成してみました。

こんな感じのです…!( 「え、ロゴ??」 と思った方すみません。タイトルでロゴとか言っていますけどロゴ「みたいな」やつなのでご愛嬌ということで)

対象読者

  • PHP のGDライブラリでなにか作ってみたいという方
  • GDライブラリの使用を考えているがどのように使えばよいか悩んでいる方
  • docker x php でなにか作ってみたい!という方

環境

  • Docker version 20.10.7
  • macOS Catalina 10.15.7

目次

Dockerfile

ここの手順を飛ばす方はコードを GitHub にあげているので clone して使用してください。
また、本題は GD ライブラリの使用なので Docker についての説明は部分的にしていきます。

(※ Docker を導入されていない方は以下のページから導入をお願いします。)

ディレクトリ構造

.
├── fonts
│   └── *.ttf(自身が好きなフォント) 
├── .gitignore
├── Dockerfile
├── logo.jpg(作成した画像)
└── Logo.php
# (※ 今回は php の環境だけあればよかったので `docker-compose.yml` は使用していません。)

clone する方はこちら

今回のプロジェクトで使用するディレクトリを用意し以下のコマンドでリポジトリを clone してください。

git clone [email protected]:suzu12/php-gd.git

Dockerfile の内容

ファイルをいくつか作成するので今回のプロジェクトで使用するディレクトリを用意し Dockerfile を作成してください。
下の2行が Docker環境GD を導入する記述です。

Dockerfile
# php のイメージ
FROM php:7.4-fpm

# コマンド実行ディレクトリ
WORKDIR /var/www/html

# パッケージインストール
# ※ 必要最低限の構成です
RUN apt-get update \
  && apt-get install -y \
  git \
  libfreetype6-dev \
  libjpeg62-turbo-dev \
  libonig-dev \
  libzip-dev \
  && docker-php-ext-configure gd --with-freetype --with-jpeg \
  && docker-php-ext-install -j$(nproc) gd

メインプログラム

ディレクトリ構造に従って Logo.php を作成します。

Logo.php
<?php

class Logo
{
    private const LOGO_WIDTH = 200;
    private const LOGO_HIGHT = 100;
    private const DESTINATION = 'logo.jpg';
    private const QUALITY = 100;
    private const FONT_SIZE = 40;
    private const FONT_X = 44;
    private const FONT_Y = 65;
    private const ANGLE = 0;

    // フォント(.ttf)のパス
    // install したり PC に入っているものを使用することができる
    private const FONT_TYPE = __DIR__ . '/fonts/ipaexm.ttf';

    // 背景(白で塗りつぶしたいのでXとYの終点は LOGO_WIDTH, LOGO_HIGHT と同じになる)
    private const BACKGROUND_START_COORDINATE = 0;

    private const ELLIPSE_CENTER_X = 100;
    private const ELLIPSE_CENTER_Y = 50;
    private const ELLIPSE_WIDTH = 180;
    private const ELLIPSE_HIGHT = 90;

    public function createLogo(string $text)
    {
        header("Content-type: image/jpeg");

        // 画像オブジェクトを生成
        $image = imagecreatetruecolor(
            self::LOGO_WIDTH,
            self::LOGO_HIGHT
        );

        // 画像オブジェクト生成時は背景が黒いので白くする
        $white = imagecolorallocate($image, 255, 255, 255); // R, G, Bで色を指定
        $this->fillWhitelyBackground($image, $white);

        // 好きな色で塗りつぶす(今回は青)
        $blue = imagecolorallocate($image, 65, 105, 225);
        $this->makeEllipse($image, $blue);

        // テキストを挿入
        $this->insetText($image, $white, $text);
        // 文字化けする場合は encoding が必要
        // $this->insetText($image, $white, mb_convert_encoding($text, "UTF-8", "auto"));

        // GDImageを .jpg で第2引数で指定したパスへ保存する。
        imagejpeg($image, self::DESTINATION, self::QUALITY);

        // 画像を破棄する -> メモリの開放
        imagedestroy($image);
    }

    private function fillWhitelyBackground($image, int $color)
    {
        imagefilledrectangle(
            $image,                             // GdImage
            self::BACKGROUND_START_COORDINATE,  // x 座標のはじまり
            self::BACKGROUND_START_COORDINATE,  // y 座標のはじまり
            self::LOGO_WIDTH,                   // x 座標のおわり
            self::LOGO_HIGHT,                   // y 座標のおわり
            $color                              // 指定した色
        );
    }

    private function makeEllipse($image, int $color)
    {
        imagefilledellipse(
            $image,                 // GdImage
            self::ELLIPSE_CENTER_X, // 中心の x 座標
            self::ELLIPSE_CENTER_Y, // 中心の y 座標
            self::ELLIPSE_WIDTH,    // 円の幅
            self::ELLIPSE_HIGHT,    // 円の高さ
            $color                  // 指定した色
        );
    }

    private function insetText($image, int $color, string $text)
    {
        imagettftext(
            $image,             // GdImage
            self::FONT_SIZE,    // フォントサイズ
            self::ANGLE,        // 角度
            self::FONT_X,       // x 座標
            self::FONT_Y,       // y 座標
            $color,             // 指定した色
            self::FONT_TYPE,    // フォントを指定
            $text               // 文字
        );
    }
}

$text = "suzu";
$logo = new Logo();
$logo->createLogo($text);

メインプログラム補足

ある程度の情報はコメントアウトして書いていますが補足をしていきます。

  • font(.ttf)の指定

現状のプログラムだと以下の記述でフォントを指定しています。

private const FONT_TYPE = __DIR__.'/fonts/ipaexm.ttf';

これは自分の環境にはありますが、みなさんには入っていないかと思います。
パスの指定を変更し、自身のPCに入っている .ttf のフォントを指定するか以下のようなページからフォントを導入してください。

また、自分の書いたプログラムの場合 fontsディレクトリ配下にフォントが来るようにしているので必要に応じて fonts ディレクトリを作成するなどしてください。

  • X座標とY座標の調整

X座標とY座標を数値で指定し、図形や文字列の位置を決めています。

そのため、人によっては文字がずれてしまうと思います。(現状は suzu という文字列で調整しています。)

必要に応じて調整などをお願いします。

build

  • Docker イメージの作成
docker build .

Docker run

  • image ID の確認
docker images
  • コンテナに入る

プロジェクトのルート(DockerfileLogo.phpと同じ階層)でコマンドを打ちます。

docker run -it -v $(pwd):/var/www/html [イメージID] bash

イメージとしては
run でコンテナを作成・実行し -v でホストのファイルシステムを共有、bashでシェルを起動]
という感じです。

また、$(pwd) でカレントディレクトリの絶対パスを入れています。
直接絶対パスを指定していただいても構いません。

画像の生成

画像を生成するためにコンテナ内で以下のコマンドを使用します。

/var/www/html
php Logo.php

画像の確認

ホスト側でもlogo.jpg という画像ファイルが作成されているかと思います。

おわりに

.jpg 以外にも .png などもサポートされているのでお試ししてみてはどうでしょうか。

参考文献