PHP 画像にロゴを入れる
追記:090702
はてブのコメントでこのエントリの別案タイトルを頂きました。その名も「PHPのGDライブラリをつかったウォーターマークの入れ方!」(ryuzi_kambeさん、ありがとうございます)こういうのってウォーターマークっていうんだなーと。そういえばなんか聞いたことありました(多分)。普段は「透かし」とか言ってたよ・・・。
ブログを利用してご自身で日々の情報やら画像やらを更新してくださってるクライアントさんから「アップする写真にうちのロゴを入れたいんだけど」というお願いがきた。(画像パクられたくない的な感じ)画像加工のソフト使えばーとか思ったけど、最近放置気味だったPHPの勉強再開のいいタイミングかなーということで、PHPを利用してできないかやってみた。
やりたい事
- 画像ファイルの右下辺りにロゴを入れたい。
- 後で「この写真のロゴの入ってない元データを無くした。元データを返してくれ」とか言われる予感がしないでもないので、ロゴを入れる前の元データはサーバーの任意のフォルダにバックアップとして保存しておきたい。
- ロゴを入れた画像のバックアップは特に必要なし。1回使い切り。
- 使用する元画像の形式はJpegのみ想定。
- ロゴは透過したpng。
- 画像のサイズは元データと同じでオッケー。
そんでもって、前々からPHPで画像っていうと「GDライブラリ」っていう言葉が至る場所で出てきて、それがグラフィクス動的生成ライブラリというものだということは分かったけど「で?」っていう段階なので、せっかくなのでそれ使う方向で勉強してみる。正直全然理解してないけどやってみたら分かるんじゃないかとか、そういう心意気で。
マニュアル熟読
とりあえずまずはマニュアルを読む。
種類いっぱいあって圧倒された。挫折しそうとおもいきや、めっちゃいいサンプルページがあったので、それ見ながらやる!
↑このページのUser Contributed Notesの中に「/* Put logo on low right jpeg image */ 」っていう例見つけた。もうね、これ。これドンピシャ。でも変だ。imagecopymerge関数のページなのにこのサンプルにはimagecopymergeが使われてないという。・・・細かいことはいいか。
使用する関数
まずは上記ページのサンプルで使われてる関数をチェック。
- imagecreatefromjpeg — ファイル又は URL から新規 JPEG 画像を作成する
- imagecreatefrompng — ファイルまたは URL から新規 PNG 画像を作成する
- imagesx — 画像の幅を取得する
- imagesy — 画像の高さを取得する
- imagecreatetruecolor — TrueColor イメージを新規に作成する
- imagecopyresampled — 再サンプリングを行いイメージの一部をコピー、伸縮する
- imagecopy — 画像の一部をコピーする
- imagejpeg — 画像をブラウザまたはファイルに出力する
何をするものかはとりあえず把握した。流れとしてはこんな感じらしい。
- ロゴ画像と元画像と最終的にロゴをはめ込んだ後のファイルを指定。
- 元画像からimagecreatefromjpegでjpg画像作る。
- 作ったjpg画像の幅と高さを取得。
- ロゴ画像も同様にimagecreatefrompngでpng画像を作って幅と高さ取得。
- 最終的にロゴ入り画像用にimagecreatetruecolorでイメージを新規作成。幅と高さは元画像のものと同じに指定。
- 右下にロゴが配置されるように元画像幅 - ロゴ画像幅で幅の座標を決める。高さも同様に。
- imagecopyresampledで再サンプリング。
- imagecopyでそこにロゴをコピーする。
- imagejpegでそのjpeg画像を保存。
で、上のサンプルと今から作りたいものの違いは元画像の方をアップロードさせてバックアップ用に保存したいっていう点。頑張る。
下ごしらえ
ロゴの用意
サンプル用にここのサイトタイトルの画像を使う。透過してあるpng画像を用意しました。
※IE6で↑この画像見ると変になってるけどそこはスルーで。
フォームの用意
画像をアップするためのフォーム。
画像のアップロード~元データの保存
まず画像のエラーチェック用の関数。前に書いたこの辺りの使いまわし。エラーがあれば「$error」にエラー内容を代入。前にこれ使ったときはファイルの形式のチェックを「if(!(($image_type == "jpg") || ($image_type == "gif") || ($image_type == "png")))」ってしてたけど、今回は絶対jpegしか使わないので「if(!($image_type == "jpg"))」とした。
これまた以前にPHP ファイルのアップロード 勉強メモというエントリを書いたときのサンプルを流用してアップした時の日付と時刻をファイル名として元データを/dataという場所に保存しておく流れ。
まずバックアップを残す保管場所の指定。
次にアップロードボタンが押されたら「$submit」に$_POST["submit"]を入れる。ボタンが押されてなかったらNULL。もし「$submit」の中身がなかったら「画像を選択してアップロードしてください。」と表示。そうでなかったらエラーチェック。エラーがなければ、アップされた画像に日付と時刻を繋げたファイル名を付けて最初に指定した保管場所へコピーという流れ。
それぞれの画像の幅・高さ取得~位置決定
さっき保存した/dataの中の「$copy_file」を新しいjpegイメージとする。んで、imagesxとimagesyで幅・高さを取得。
最初これって「$new_image = "./data/{$copy_file}"」だったらあかんのー?と思ってやってみたらエラーが出た。よくよくマニュアルを見てみるとimagesxやimagesyのパラメータには「画像作成関数が返す画像リソース。
」ってちゃんと書いてあった。
なんかこう・・・一旦私達専用の新しいインスタンス作ってからでないと言うこと聞けないわよーみたいな感じと理解した。違うかもしれんけど。なんせ一旦imagecreatefromjpeg等を使わないと幅や高さは取得できないセットの人々と覚えとく。あぁ、そりゃそうよね。分類がGDの一族だものね。
ロゴも同じようにimagecreatefrompngで新しいイメージ作って幅・高さを取得。(上のソースには入ってないけど、ロゴは予めソースの上の方で「$logo = "logo.png";」ってファイルを指定しておいた。)
次に位置と余白の設定だけどサンプルページでは「-5」っていうのは入ってなかったんだけど、元画像の幅・高さからロゴの幅・高さを引いた数だとビタで右下になるのでちょっとだけ余白を確保した。それが「-5」。
いよいよロゴを入れる段階
最終的にロゴを入れた画像は「result.jpg」という名前にして/dataの中に保存することにする。これは元画像のバックアップ用とは違って使いきりでいいので同じ名前で上書きして最新のものだけ保存されればいい。
imagecreatetruecolorでとりあえず画像を作る。幅は元画像と同じ「$image_W」と「$image_Y」。それを「$result_image」に代入。とりあえずそのサイズで黒背景のフレームだけ作っておく感じ。Dreamweaverのイメージプレースホルダー的な。
次にimagecopyresampled。このパラメータがややこしくて気絶するかと思った。とりあえずこれを今回のケースに当てはめて日本語にするところから。
bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )
最終的にロゴ入り画像になるイメージ「$result_image」を「画像1」、さっき imagecreatefromjpegを使って元画像から作った新しいイメージ「$new_image」を「画像2」として置き換える。
imagecopyresampled( 画像1 , 画像2 , 画像1のX座標 , 画像1のY座標 , 画像2のX座標 , 画像2のY座標 , 画像1の幅 , 画像1の高さ , 画像2の幅 , 画像2の高さ )
このimagecopyresampledでimagecreatetruecolorで作ったフレームに元画像をはめ込んでる感じ。(はめ込んでるって変な言い方だけど私的にサイズを合わせてピタっと上からはめましたみたいなイメージ。上に書いたDWのイメージプレスホルダーで言うと、本番用の画像と差替えましたよ、みたいな。これも間違ってるんかもしれんけど。)
次にimagecopy部分。やっとここでロゴ登場。とりあえずまた今回のケースに当てはめて翻訳。
bool imagecopy ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h )
さっきの「$result_image」を画像1、ロゴ画像はそのままロゴ画像とする。
imagecopy( 画像1 , ロゴ画像 , 画像1の上にロゴをコピーする部分のX座標 , 画像1の上にロゴをコピーする部分のY座標 , ロゴ画像のX座標 , ロゴ画像のY座標 , ロゴ画像の幅 , ロゴ画像の高さ )
これでやっと元画像の上にロゴ画像をのせることができた。で、それをimagejpegを使って「result.jpg」という名前で保存。
それで、よく分からない点が・・・。今回参考にしたサンプルには書いてなかったのだけれど、他のサンプルを見てると、imagedestroyを使ってメモリを開放するというくだりが目に入って、どれもこれもメモリを開放せよ、みたいな感じで書かれているのだけれど、どうしたらいいのだろう。とりあえずこれはアレか?imagecreateと名の付くものを使用した後は必ずimagedestroyで開放せよ!みたいなお約束ごとなのだろうか。ということで、サンプルにはついてないけどビビりなので一応追加。
画像をブラウザに表示させる
フォームの下にロゴを挿入した画像と元画像を表示させる。見た目はこんな感じ。上がロゴ入り画像。右下にひっそりと画像が入ってる。下は元画像。(えらく長くなるので途中で切ったけど)
まぁそういうことで今年の阪神タイガースはもう少し頑張って欲しいと思っている今日この頃です。
ソース全文
需要はないと思いますが、一応ソースの全文置いておきます。
<< PHP ランダム表示機能付きバナーリンク集 | PHP 添付ファイル付メール送信 勉強メモ >>
トラックバック
このエントリーのトラックバックURL:
http://redline.hippy.jp/cgi/mt/mt-tb.cgi/242
PHP 画像にロゴを入れる へのトラックバック一覧
» MT4 @ ダイナミックで動く画像リサイズ . プラグイン 送信元 wed@
【現在進行中の記事です】ちょっと作ってみる事にする。GDを使ったリサイズの例(グ...
Trackback time : 2010.01.31
コメント (2)
参考になりました^^
投稿者: popcorn | 2009年07月01日 14:44
>popcornさん
少しでもお役に立ててよかったです(n' ω 'n)
投稿者: Red | 2009年07月08日 09:03