ロリポップで画像をWebPに変換したい

2020/4/27にWebPが公式にサポートされました:tada:[^webp-official]よって、今となっては以下にあるような面倒なことをする必要はなくなりました。

[^webp-official]: [PHP7.3において、サイトの高速化に効果のある「WebP」形式の画像ファイルに対応しました！ - ロリポップ](https://lolipop.jp/info/news/6594/)

---

ロリポップのレンタルサーバーで、JPEGやPNGの画像をWebP形式に変換したくてなんとかした話です。スタンダードプラン以上（SSH接続ができる）を前提としています。

## ロリポップのPHPは`imagewebp`関数をサポートしていない
WebP変換？[`imagewebp`](https://www.php.net/manual/ja/function.imagewebp.php)関数使えば楽勝でしょ:thumbsup:と思っていたら...

```Fatal error: Uncaught Error: Call to undefined function imagewebp()```

で動きませんでした。`phpinfo()`で確認すると
![lolipop-phpinfo-gd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617255/ef6cf73a-d685-a14d-af51-d727606969eb.png)
ロリポップはWebPをサポートしていないことが分かりました。[^webp-support]
[^webp-support]: サポートに問い合わせてみたところ、現時点(2019.03.26)でWebP対応の予定はないとのお返事でした。~~今後に期待したいところです。~~

## 自前でWebPに変換できる環境を構築する
`cwebp`コマンドラインツールを利用することで、画像をWebP形式に変換することができます（[A new image format for the Web | WebP | Google Developers](https://developers.google.com/speed/webp)）。つまり、`cwebp`をロリポップのサーバーで利用できるようにすれば解決です。

### 方針
ロリポップと同様の環境でビルドした`cwebp`コマンドラインツールと必要なライブラリをロリポップのサーバーにコピーします。ロリポップのレンタルサーバーでは`make`はおろか`gcc`も利用できない（[使用可能コマンド一覧 - ロリポップ](https://lolipop.jp/manual/user/ssh/#p-command)）ため、レンタルサーバー上でビルドするのは不可能です。

### ビルド環境の構築
ロリポップのレンタルサーバーと同様の環境をVirtualBoxで構築します。ポイントは**[glibc](https://www.gnu.org/software/libc/)のバージョンを合わせる**ことです。[^glibc]
[^glibc]: 試しに[Precompiled WebP utilities](https://developers.google.com/speed/webp/download)をダウンロードしてロリポップサーバーで動かすと、``cwebp: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by cwebp)``となって動かないことが分かります。[^glibc2]
[^glibc2]: レンタルサーバーでglibcのバージョンを変えれば...と思う人もいるかもしれませんが、多くのプログラムがglibcに依存しているため不可能です。無理にやるとあらゆるコマンドが無効になり詰みかけます（参考: [[Solved] relocation error: /lib64/libc.so.6: symbol _dl_starting_up 解決法 - Qiita](/sachiotomita/items/ef29520c55fc168191d8)）。

#### ロリポップサーバーのglibcのバージョンを確認
レンタルサーバーで

```shell
/lib64/libc.so*
```

を実行すると、

```
GNU C Library stable release version 2.12, by Roland McGrath et al.
```

のようにバージョンが表示されます（私の環境では2.12でした）。

#### CentOS 6のインストール
glibcのバージョンが2.12であるCentOS 6(64bit)環境をVirtualBoxで構築します。レンタルサーバーがCentOSである[^server-spec]ためOSもそれに合わせます。

VirtualBoxでの環境構築の方法はここでは詳述しません。かなりざっくりと説明すると

1. VirtualBoxのインストール
2. [Download - CentOS](https://wiki.centos.org/Download#Base_Distribution)のx86_64のリンクからCentOS 6.10(64bit)をダウンロード（
[aria2](https://aria2.github.io/)を使うと高速にダウンロードできるのでおすすめです[^aria2-qiita]。）
3. ダウンロードしたISOでCentOSをインストール

という流れです。私はGUIなしでSSHを有効にして利用しました。

[^server-spec]: [サーバーの仕様 - ロリポップ](https://lolipop.jp/service/server-spec/)
[^aria2-qiita]: 参考: [curlやwgetの数倍速い 爆速ダウンローダー aria2を使う - Qiita](/TokyoMickey/items/cb51805a19dcee416151)

### `cwebp`のビルド
VirtualBoxのCentOSでビルドを行います。だいたいのことは[Compiling the Utilities | WebP | Google Developers](https://developers.google.com/speed/webp/docs/compiling)に書いてあります。

#### 必要なパッケージのインストール
これがないとビルドしても入力画像が読み込めません。

```shell
sudo yum install libjpeg-devel libpng-devel
```

#### ソースのダウンロード・展開
`libwebp-1.0.3.tar.gz`を[downloads list](https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html)からダウンロードして下記で展開

```shell
tar xvzf libwebp-1.0.3.tar.gz
```

#### ビルド
後でレンタルサーバーにアップロードする際の手間を考慮し、ホームディレクトリ（`~/bin/libwebp-1.0.3`）にインストールします。

```shell
cd libwebp-1.0.3
./configure --prefix=$HOME/bin/libwebp-1.0.3
make
make install
```

### ロリポップサーバーで実行できるようにする

#### 必要なファイルのコピー
下記のファイルをレンタルサーバーのホームディレクトリにコピーします。

| ローカル（VirtualBox） |  | レンタルサーバー |
| :-- | :--: | :-- |
| `~/bin/libwebp-1.0.3/bin/cwebp` | → | `~/usr/bin/cwebp` |
| `~/bin/libwebp-1.0.3/lib/libwebp.so.7.1.0` | → | `~/usr/lib/libwebp.so.7.1.0` |
| `~/bin/libwebp-1.0.3/lib/libwebpdemux.so.2.0.6` | → | `~/usr/lib/libwebpdemux.so.2.0.6` |

#### シンボリックリンクの作成
ライブラリのシンボリックリンクを作成します。

```shell
cd ~/usr/lib
ln -s libwebp.so.7.1.0 libwebp.so.7
ln -s libwebpdemux.so.2.0.6 libwebpdemux.so.2
```

#### 環境変数の設定
`cwebp`と、それが利用するライブラリを見つけられるようにパスを通します。

```shell
cd ~
vi .bash_profile
```

`Insert`キーで挿入モードに入り、下記の内容を追加します。

```shell:~/.bash_profile
export PATH=~/usr/bin:$PATH
export LD_LIBRARY_PATH=~/usr/lib:$LD_LIBRARY_PATH
```

編集後、`Esc`キーでコマンドモードに入り`:wq`で保存して終了します。下記コマンドで`.bash_profile`を再読み込みすることでパスが通った状態になります。今後は、SSHでログインすれば自動的にパスが通ります。

```shell
source ~/.bash_profile
```

試しに`cwebp`を実行して下記のような表示になっていればOKです。

```
Usage:

   cwebp [options] -q quality input.png -o output.webp

where quality is between 0 (poor) to 100 (very good).
Typical value is around 80.

Try -longhelp for an exhaustive list of advanced options.
```

もしライブラリが見つからない旨のエラーが出た場合は、ローカル環境の`~/bin/libwebp-1.0.3/lib/`を参考にしてレンタルサーバーにライブラリをコピーすればよいでしょう。

## PHPからの利用
PHPから利用する場合も、`~/.bash_profile`と同様に環境変数をセットする必要があることに注意してください。環境変数は`~/bin/...`ではなく、ルートからの絶対パス（`/home/users/...`のようなパス、`pwd`コマンドで確認できます）で指定します。