GDの画像取り扱いの注意メモ

どうも、忙しくて更新を忘れていたどころかドメインが失効しておりました。
おまけに指を怪我していてちょっとつらいです。

仕事で画像をアップロード→サムネ生成→合成
というのをやっていたんですが、なぜかエラーが出る画像とエラーが出ない画像が出て、なんじゃらほいという感じに。
メモリリークエラーの場合、PHP側の使えるメモリが8MBとかでわからんでもないんですが、
こちとら仕事で専用サーバ使ってますので当然そんなことはないと。
ただエラー内容は明らかにメモリ。
まああれです。

[warning]
Fatal error: Allowed memory size of xxxxx bytes exhausted (tried to allocate xxxxx bytes)
[/warning]

ってやつ。
FatalErrorはtryで取れないので困ったな~って感じで、挙動をチェックしていたわけなんですが。

一応考えられる原因の一番手はアップロードした画像が使用可能メモリより大きいってことなんですけど、
今回はもちろんメモリより小さく制限していたのでそんなことはないと。
フロント側のFileAPIで確認してからアップしていますし、内部でも確認しているし。アップロード上限超えたら例外だし。

それで色々やってたら、
どうやら画像自体が数kBとかでも、縦横のサイズが大きいとエラーになると。

カメラで取った写真がエラーの場合、ヘッダー情報のせいだったりするので最初それかなと思ったんですが、
そうでもなくて、
GDが圧縮されている画像を引き伸ばすのでそれでメモリが足りなくなるっぽいと。
今回は画像を複数アップさせて、同時に変更してたんですが、
3枚目までは成功してその次からエラーということで、
メモリ管理を徹底してみてようやく動いた感じです。

まあやってるうちに、そういや最初の仕様に容量はあったけどサイズはなかったなと思ったので、
サイズ制限も一応入れました。

しかしPHPの2MBのアップロード制限は最近のスマホからだとかるがると突破してしまうのでちょっとあれですね。
一応サーバ担当者に連絡すれば変更は利きますが、あまり大きなサイズもアップさせたくないし。
1枚くらいならいいんですけどね。

という感じで、GDのFatal Error(メモリ関連)の場合は、

  1. PHPが使えるメモリのサイズ/li>
  2. アップロードされた画像とPHPのメモリのサイズの比較
  3. アップロードされた画像をGDで変更する際全てメモリ上に展開していないか

なんかを確認すると幸せになると思います。

ちなみにメモリの利用量を変更して対応する方法もありますが、
レンタルサーバで確実に使えるかどうかはちょっとあれですし、アクセスが極端に多いサイトではまったく使えないので、
ソース見直しての最終手段のほうがいいかなと。