レシピ
プラットフォーム:HTTPサーバー
使用言語:PHP 4.0以上
GDライブラリ ver2.0以上
※サーバ・サイドで動作するものを作成する場合はHTTPサービス(Apacheなど)とPHPが動作する環境が必要です。

 前回の続きです。単純にサーバーサイドでQRコードを生成するだけでなく,透過色やサイズを指定してJPEG/PNGのほかにGIFでの出力もできるプログラムを作ります。今回の主旨は「指定オプションで画像ファイルを生成して保存する」です。動的に作成するというよりも,特定のQRコード画像を透過色などを含めて設定してファイル保存し,それを使うという方向になります。なお今回のサンプル作成前に,必ず前回「第3回 PHPでQRバーコードを作成する(その1) 」をご一読ください。QRコードそのものの生成は前回使用した「QRcode Perl/CGI & PHP scripts ver. 0.50g」をベースにしています。

画像ファイルとして保存する意味

 前回のサンプルはフォームから送信したテキスト・データから,動的にQRコードを生成して表示するというものでした。フォームからの送信は便利なんですが,外部サイトのフォームから送信されても動作してしまい,便利であればあるほど“持ち逃げ的利用”をされがちです。

 今回のサンプルは外部からフォームでデータを送って云々ということは考えず,生成されたQRコードを任意のファイル名で保存することに主眼を置いています。このプログラムで生成した画像ファイルを,直接<img>タグで呼び出したり,あるいはダウンロードして名刺などの印刷物に使用するということを考えています(図1)。

図1●透過のないJPEG画像の生成サンプル
図1●透過のないJPEG画像の生成サンプル

 前回サンプルとの相違点です。

・任意のファイル名で保存できる
・JPEG/PNGのほかにGIF形式が生成できる
・PNGとGIFでは透過色指定ができる
・任意サイズを指定できる

 QRコード生成のベースはY.Swetake氏作ライブラリ「QRcode Perl/CGI & PHP scripts ver. 0.50g」を使います。このライブラリそのものには一切手は加えず,呼び出し側プログラムの工夫で上記のような特徴をもたせます。

サンプル・コードの設置と設定

 ではソースコードです(リスト1)。make_qr.phpの名前で,QRcode Perl/CGI & PHP scriptsのqr_img.phpと同じディレクトリに配置してください。なお今回は生成した画像ファイルを,プログラムがあるディレクトリに直接生成しますので,ディレクトリのパーミッションが書き込み可能(666など)になっている必要があります。

<?php
//保存するファイル名
//拡張子は自動で付くので,qrtest.jpgなどを作成するならqrtestまで

        ・
        ・
        ・
リスト1●make_qr.php

 リスト1の冒頭部の数行は設定部です。下記項目を設定します。
・保存するファイル名
・透過色にする色の指定
・生成される画像の縦横サイズ
・画像フォーマット
・QRコードに埋め込むテキスト
・qr_img.phpのURL(ディレクトリ名まで)

 保存するファイル名は拡張子の部分を記述しません。拡張子は画像フォーマットの指定で自動的に付与されます。例えばtest.jpgというファイル名で生成したい場合は,“test”とだけ指定し,画像フォーマットの指定部で“jpg”とします。

 透過色の指定はGIFとPNG画像の場合にのみ有効です。QRコードは白黒で生成されるので,白または黒のどちらかを指定することになります。色の指定は,0から255までの数値でRGB(赤緑青)それぞれを指定する形式です。

 すべてが0だと黒に,すべてが255だと白になります。QRcode Perl/CGI & PHP scriptsが生成するQRコードは単純二値のモノクロですから,どちらか――普通は背景色の白側――を透過にすることになります。透過画像にすると,例えば背景が真っ白ではないページに画像を置いても,違和感のない表示ができます。また,生成された画像を名刺作成ソフトなど別のソフトに貼り付けたときにも,淡い背景や模様を部分的に隠すことなく表示できてスッキリすることでしょう。

図2●白い部分を透過にしたPNG/GIF画像のサンプル
図2●白い部分を透過にしたPNG/GIF画像のサンプル

図3●黒い部分を透過にしたGIF/PNG画像のサンプル
図3●黒い部分を透過にしたGIF/PNG画像のサンプル

 生成される画像サイズは縦横個別ではなく両方を同じ値とします。プログラムとしては長方形の画像にすることもできますが,QRコードそのものが正方形なので,縦横を個別に設定する意味が少ないからです。なお,ここでいう画像サイズは,QRコードの外枠の白い部分を含んでいます。バーコード部だけの縦横にならない点は注意してください。

 QRコードに埋め込むテキストは任意に指定できます。携帯電話での使用を前提とする場合は,ここの文字コード(プログラムそのものも)はシフトJISにしてください。ダブルクォートでくくられている中では,改行を入れることができます。¥nのようなメタ文字でもかまいません。

 QRコード生成のために呼び出す,qr_img.phpのURL指定も必要です。サンプル・プログラムでは,QRコード生成処理をインターネット経由(厳密にはHTTP利用なのでLAN/ローカル・マシンでも可)で呼び出します。これはちょっと無駄にも思えますが,実は生成ルーチンqr_img.phpがGET形式での引数を前提に作られていて,fopenなどのサーバー内部処理では各種引数を生成ルーチンに流し込めないからです。

処理の流れ

 サンプル・プログラムは各種設定を読み込んだあとに,まずqr_img.phpを使ってJPEG形式のQRコードを生成します。qr_img.php?d=$src_enc&t=Jという引数指定です。

 $src_encにはコード化する文字列が入っています。「t=J」というのはJPEG形式でのコード生成指定です。前回のようなサイズの指定はしません。サイズの指定といっても,qr_img.phpは元々ピクセル単位でのサイズ指定を想定していないので,ピクセル単位での生成ができないという点と,サイズ指定をしてしまった場合,JPEGの最適化処理で白と黒の境界線部分に微妙な灰色部分が混ざるようで,透過色指定に失敗しました。この教訓から,今回はサイズ指定なしという方法を採用しています。サイズの指定を行わないと,qr_img.phpは360px*360pxでQRコードを生成するようです。

$im_src = imagecreatefromjpeg($img_src);

 この行でQRコードが生成されます。生成したQRコードはメモリー上に展開されますが実体を持っていません。いったんこのQRコードは放置して,ファイルになるほうの画像イメージを作ります。

//指定サイズのQRコードを生成するための新しいイメージ・リソース
$im_dist = imagecreate($img_size,$img_size);
imagecolorallocate($im_dist,255,255,255);

 指定されたサイズを縦横とした真っ白な画像イメージです。やはりメモリー上にあって実体はありません。コピー元(ソース)のイメージをコピー先(ディスト)に転送しているのがimagecopyresized関数です。

 この関数はサムネイル画像を作るようなときにも使います。PHPの,といいますかGDライブラリの画像処理は想像以上に性能が良くて,レタッチ・ソフトと遜色のないサイズ変更をしてくれます。この段階でもまだソースもディストもメモリー上にあるイメージで,実際の画像にはなっていない点に注意してください。その後にGIFかPNGだった場合にはimagecolortransparent関数でソース側に透過色指定を行います。

 あとは保存用に設定されたファイルのファイル名を作って,imagejpeg/imagegif/imagepngの関数でファイルとして保存します。このディレクトリのパーミッションは書き込み可(666)にしておかないとエラーになります。

 このプログラムそのものはここで終了してかまわないのですが,確認のために,生成して保存したファイルを赤い背景のHTMLに<img>タグで書き出すという処理を最後に付けてあります。背景をわざわざ赤くしているのは,透過色が正しく適用されているかの確認のためです。

 ディレクトリ内に指定したファイル名で画像ファイルができているので,あとはダウンロードするなりして好きなように使ってください。もちろん,GIFとPNGの透過設定は保存されたファイルにも効いています。

フリーのライブラリからの工夫

 フリーのライブラリはとても有効ですが,できることにはやはり制限がつきます。制限の壁を越える手法は二つあります。

1. フリー・ライブラリそのものを改造する
2. プログラム的手法でライブラリを外部から拡張する

 今回は2の手法を用いました。基本的にGNUにのっとったフリーソフトは改変自由な場合がほとんどですが,本体に手を入れていくうちに挙動が怪しくなってしまうということもままあります。

 私個人としては2の手法が結構お気に入りで,自分の力で拡張が効くものはどんどん拡張してしまうということを好んでやっています。この方法ではオリジナルはオリジナルのままなので,どんなに工夫してもダメだったときには,オリジナルの機能で満足しておくという逃げ道があります。