読者です 読者をやめる 読者になる 読者になる

PHP+GDで自動で画像にロゴ入れする方法。

スポンサード リンク

画像等の転用防止のためにWeb上で公開する画像に対してロゴやCopyrightを挿入したい事がある。
具体的な例を挙げるなら、風俗サイト等で、コンパニオンの画像等に。
個人的には、画像加工系は、GDよりもImageMagickの方が色々やりやすい気がするのだけれど、とりあえず今回はGDにて。

サンプルの前提

ロゴを入れたい画像

ファイル名:followmanager.png
f:id:otapps:20150714024103p:plain

ロゴ

ファイル名:otapps_logo.png
f:id:otapps:20150717070522p:plain
※透過PNG

サンプル

シンプルにロゴ入れ

imagecopyの第三・第四引数でロゴのxy座標をそれぞれ指定可能だけれど、全て0としているので左上にロゴが表示される。

<?php
$logo = imagecreatefromstring(file_get_contents('otapps_logo.png'));
imagealphablending($logo, false);//imagesavealpha を有効化する場合、無効にする必要がある(らしい)
imagesavealpha($logo, true); //完全な アルファチャネル情報を保存
$base = imagecreatefromstring(file_get_contents('followmanager.png'));
$logo_x = imagesx($logo);//ロゴの幅を得る
$logo_y = imagesy($logo);//ロゴの高さを得る
imagecopy($base, $logo, 0, 0, 0, 0, $logo_x, $logo_y);
header("Content-type: image/png");
echo imagepng($base);

結果:
f:id:otapps:20150717132245p:plain

ロゴの表示位置指定

これに関しては、ImageMagickならある程度の位置指定は簡単に出来るのだけれど、GDだとざっとマニュアル見る限り、ざっくり位置指定する関数が無いようなので、自身で計算する必要があるっぽい。(他に方法あったら教えて下さい。)

画像の中心にロゴを入れる場合

画像の中心にロゴを入れたい場合は以下のような感じになる。
詳細はコメント参照。

<?php
/*
 * 画像の真ん中にロゴ入れ。
 */
$logo = imagecreatefromstring(file_get_contents('otapps_logo.png'));
imagealphablending($logo, false);//imagesavealpha を有効化する場合、無効にする必要がある(らしい)
imagesavealpha($logo, true); //完全な アルファチャネル情報を保存
$base = imagecreatefromstring(file_get_contents('followmanager.png'));
$logo_x = imagesx($logo);//ロゴの幅を得る
$logo_y = imagesy($logo);//ロゴの高さを得る
$base_x = imagesx($base);
$base_y = imagesy($base);
$x = floor(($base_x / 2) - ($logo_x / 2)); //ベース画像の横幅を2分の1したものから、ロゴ画像の横幅を2分の1した数を引いたものがロゴの開始x座標になる。
$y = floor(($base_y / 2) - ($logo_y / 2)); //上記をyに置き換えただけ。
imagecopy($base, $logo, $x, $y, 0, 0, $logo_x, $logo_y);//上記の座標を指定してやる。
header("Content-type: image/png");
echo imagepng($base);


みたいな感じで、ロゴ入れしたい場所の座標計算をする必要がある。

結果:
f:id:otapps:20150717134651p:plain



そのまま出力するわけではなくファイルとして出力(保存する場合)

header("Content-type: image/png");
echo imagepng($base);

imagepng($base,ファイル名);

とするだけ。
勿論、ファイル出力先に書き込み権限が必要


補足

入力画像タイプが固定の場合、

$logo = imagecreatefromstring(file_get_contents('otapps_logo.png'));

などとせずに、

  • imagecreatefromgif
  • imagecreatefromjpeg
  • imagecreatefrompng

等で決め打ちしても良いけれど、複数の画像タイプを処理する可能性がある場合は 画像タイプ毎にswitch等での振り分けをするよりは、imagecreatefromstring を利用した方が早い。
フォームから送信した画像をそのまま渡せるし。*1


元画像の縦横サイズが固定されてない場合、元画像のサイズに合わせて、ロゴ画像のサイズも縮小するなりの処理を加えた方がいい。*2

サンプルではimagecopyを使っているけれど、透過率を指定してコピー可能なimagecopymergeが便利な場合もあるかもしれない。

実際に使う場合

動的に出力するにしても、一旦ファイルとして出力するにしても、元画像(ロゴ無し)へ、直接アクセス出来ては意味が無いので、元画像は外部からアクセス不可能な場所に配置する。

実行タイミングは、ユーザ(冒頭の例で言うなら風俗店関係者)がファイルをアップロードした時にロゴ入り画像のキャッシュを生成するとか、ファイルが呼び出された時に動的に画像を出力するなり、どっちでも良いと思う。
サーバの負荷を考えれば前者。

*1:サンプルでは、既に画像が存在する前提なのでfile_get_contents している。

*2:例えば、ベース画像の縦横幅/2 をロゴ画像の縦横幅がオーバーしている場合は、ロゴ画像を2分の1に縮小するとか。