サムネイル
2022-03-07
2023-06-22

タイトルのとおりです。
ブログを作ったはいい、作るの楽しくなって体裁を整えたのもいい、文章書くのもまあそれが目的だからいい、でもサムネイル画像を毎回用意するのクソだるい… って思ったので、PHP で投稿内容に基づいてサムネを作っちゃえば No Image 貼りまくるよりは見栄えいいよね、ってやつです。

PHPでの画像出力をしたことがなかったので勉強がてらに。

環境

  • Ubuntu 20.04.4 LTS
  • nginx/1.18.0 (Ubuntu)
  • PHP 7.4.3
  • GD 2.2.5

Imagick は脆弱性やらなんやらが怖いので使いません。わたしは弱いので…
やりたいことに対してオーバーパワーな気がするし。

コーディング

今回はこのブログのサムネイルを作成するので、横幅 400px, 縦幅 220px(16:9)で大きさが固定の画像を作ります。
GETで値を渡したりしてサイズを可変にすることは簡単なのでそこら辺はご自由に。

背景を設定して、そこに投稿のタグを # 始めで書く、という形で作ろうと思います。

まず、背景は単色でもいいのですがどうせなのでいい感じのものを用意します。

絵が描けなくても幾何学模様は簡単だから助かる

フォントの設定

GD で文字列を出力する関数には imagestring と imagefttext の2つがありますが、このうち imagestring は日本語の出力に対応していません。imagefttext は ttf ファイルでフォントを指定してあげる必要があります。

今回は日本語で出力、また好きなフォントで出力できることを目指すため imagefttext を用います。

フォントはこのサイトの平文と同じ Noto Sans JP にすることにします。Google Fonts からダウンロードしてきて、ttf に変換して使えばいいのですが、そのままだと使えませんでした。

詳しくはこちらを参照したのですが、ttf のファイルサイズを小さくするためにサブセット化をする必要があります。

サブセット化済みの ttf ファイルを配布してくださっている方がいましたので、そちらを使わせて頂いて無事に読み込むことができました。

ソースコード

コード自体は簡単なのであまり解説することもないです。表示する文字列は GET で t という変数にカンマ区切りで入れて渡します。

<?php
// 画像を生成
$img = imagecreatefrompng('./assets/base.png');

// パラメータ設定
$fontsize = 25;
$lineheight = 2.2;
$word_max = 10;
$text_full = isset( $_GET['t'] ) ? $_GET['t'] : '';
$text_arr = explode( ',', $text_full );
$text_x = 22;
$font = './assets/NotoSansCJKjp-Regular.ttf';

// 色を指定
$text_color = imagecolorallocate($img, 255, 255, 255); 

// 3行まで
if ( count( $text_arr ) > 3 ) $text_arr = array_slice( $text_arr, 0, 3 );

// 文字列出力
foreach ( $text_arr as $i => $text ) {
    $text_y = imagesy( $img ) / 2 + ( $i - ( count( $text_arr ) - 1 ) / 2 ) * $fontsize * $lineheight + 10;
    $text = mb_strlen( $text,'UTF-8' ) > $word_max ? str_replace('\n', '', mb_substr( strip_tags( $text ), 0, $word_max - 1, 'UTF-8' ) ).'…' : str_replace( '\n', '', strip_tags( $text ) );
    if ( $text != '' ) imagefttext( $img, $fontsize, 0, $text_x, $text_y, $text_color, $font, '# '.$text );
}

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

自動で改行などはしてくれるはずもなく、処理をいれるのも面倒なので幅が画像に対していい感じになるよう最大文字数を設定して、それ以上のときは replace してしまいます。縦幅も面倒なので3行以上にはしません。

完成品がこちらです。
https://app.shoalwave.net/thumbnail-generator/?t=さむねいる

t= の後の部分を書き換えてもらうと文字列が書き換わります。, で区切ることで2行以上になります。

後はブログ側で画像を表示する処理はお好きにどうぞ。

こんなのでもとりあえず webアプリケーションって言えるのかな。

おわり。