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

## はじめに

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

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

![logo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647973/c3a7b8fc-ef38-6b1c-ff1a-9094eb0f805f.jpeg)

## 対象読者

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

## 環境

- Docker version 20.10.7
- macOS Catalina 10.15.7


## 目次

- [はじめに](#はじめに)

- [対象読者](#対象読者)

- [環境](#環境)

- [目次](#目次)

- [Dockerfile](#dockerfile)
    - [ディレクトリ構造](#ディレクトリ構造)
    - [clone する方はこちら](#clone-する方はこちら)
    - [Dockerfile の内容](#dockerfile-の内容)

- [メインプログラム](#メインプログラム)
    - [メインプログラム補足](#メインプログラム補足)

- [build](#build)

- [Docker run](#docker-run)

- [画像の生成](#画像の生成)

- [画像の確認](#画像の確認)

- [おわりに](#おわりに)

- [参考文献](#参考文献)

## Dockerfile

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

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

https://www.docker.com/products/docker-desktop

### ディレクトリ構造

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


### clone する方はこちら

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

```
git clone git@github.com:suzu12/php-gd.git
```

### Dockerfile の内容

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

```Dockerfile: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` を作成します。


```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` のフォントを指定するか以下のようなページからフォントを導入してください。

https://forest.watch.impress.co.jp/library/software/ipafont/

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



- X座標とY座標の調整

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

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

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


## build

- Docker イメージの作成

```bash
docker build .
```

## Docker run


- image ID の確認

```bash
docker images
```

- コンテナに入る

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

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

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

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


https://uxmilk.jp/27666

## 画像の生成

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

```bash:/var/www/html
php Logo.php
```

## 画像の確認

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

## おわりに

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

## 参考文献

- [PHPマニュアル(GD および Image 関数)](https://www.php.net/manual/ja/ref.image.php)
    - [imagecreatetruecolor](https://www.php.net/manual/ja/function.imagecreatetruecolor)
    - [imagejpeg](https://www.php.net/manual/ja/function.imagejpeg.php)
    - [imagedestroy](https://www.php.net/manual/ja/function.imagedestroy)
    - [imageellipse](https://www.php.net/manual/en/function.imageellipse.php)


- [PHPマニュアル(mb_convert_encoding)](https://www.php.net/manual/ja/function.mb-convert-encoding.php)

- [Linuxでのドル記号「$(...)」の意味と使い方](https://uxmilk.jp/27666)

- [IPAフォント](https://forest.watch.impress.co.jp/library/software/ipafont/)

- [GitHub(clone用リポジトリ)](https://github.com/suzu12/php-gd)