このサイトはPHPを独習する際に作成したスクリプトを基に、プログラム言語初心者のための入門講座として作成しました。PHPは初心者に親しみやすく、解りやすいプログラム言語です。これからプログラムを学ぶ人の参考になればと思います。
美しい画像掲示板
「掲示板はCGIのものが数多く出回っているので、何も今更PHPで作らなくても・・・」と思っていたのですが、作って見る事にしたのです。 それならば、他にはない豪華な掲示板を作りたいと思い、作業に入ったのですが意外にも、結構難しいのですね。その途中、画像の処理をするところで、先ずは画像掲示板を完成させました。 「こんなこと・・・」のアップロ−ダが基本なのですが、2次元配列やイメージ関数など、これまでに使用していないものがいろいろと出てきます。
画像の配置について
「こんなこと・・・」のアップロ−ダはただ、画像をアップして表示させているのですが、画像というのはタテヨコがさまざまで、横幅を同じに変更してテーブルに並べてもまるで綺麗じゃないですね。まずはこれを何とかしたいと考えました。 そこで、ヨコに5枚の写真を並べ、全幅を固定した上で、高さを同じに変更したのです。つまり・・・
 こんな美しくない並びを
 こう並べると美しい!
拡大と縮小を計算式で考える
目分量でそろえるのは結構大変です。これを計算で出すには?? 5枚の画像の高さを同じにする 5枚の画像の横幅を足すと一定の数になる 画像番号を1〜5とする hとwがオリジナルの画像のタテとヨコとする a〜eは各画像に対する倍率 Wは5枚分のヨコの長さ これを元に方程式を作ると、 1ha=2hb=3hc=4hd=5he W=1wa+2wb+3wc+4wd+5wd このままでは、計算できないので、これを次のように解きます。 a=W/(1w+2w*1h/2h+3w*1h/3h+4w*1h/4h+5w*1h/5h) b=1ha/2h c=1ha/3h d=1ha/4h e=1ha/5h という良く解らない式ができる。(合ってないかも知れない!) a〜eは各画像のオリジナルのタテヨコに対する倍率です。 これにそれぞれのヨコ幅を掛けると、表示用の横幅がわかります。 1のヨコ=1w*a 2のヨコ=2w*b 3のヨコ=3w*c 4のヨコ=4w*d 5のヨコ=5w*e このとき1〜5のヨコを足すと規定の数値になり、各画像の高さは同じになるのです。 これを上手く利用すれば「美しい画像掲示板ができるに違いない!」 そして、完成したのが今回のスクリプトです。(苦労しました)
スクリプトの構成
スクリプトの記述の流れを順にあげていくと、次のようになります。 1、画像の送信と受取 2、画像の名前とサイズのチェック 3、画像の名前の変更 4、画像名を配列に読込む 5、規定の枚数を超えた場合、ファイルを削除 6、5枚の画像のタテヨコのサイズデータを取得する 7、各表示画像のヨコ幅を取得するための計算 8、画像テーブルの表示 9、次の5枚のデータを取得、後は繰り返し 10、1ページの表示が終了したら、次のページを作るための処理
ファイル名の変更
画像のアップロードは「こんなこと・・・」のアップロ−ダ3とまったく同じもので、そのまま使っています。しかし、これでは大きな問題があるのです。 1、同じ名前のファイルをアップすると前の画像が上書されてしまう。 2、画像の読み込みはファイル名によるので、新しい画像から順に表示はされない。 そのためには、画像の名前を変えてしまうのが一番です。
rename($oldname, $new_name);
これだけなのですが、アップする画像は属性の「読み取り専用」を解除していないといけません。(windowsの場合は右クリックでプロパティ)実際の記述では rename("$updir$filename", "$updir$new_name"); となっています。$updir はフォルダですが、このように変数を2つ並べるときは""ダブルクォーテイションが必要でした。 名前は数値の小さなものから表示させたいので、ちょっと厄介な方法です。アップした時間のタイムスタンプを取得して、2037年の12月のタイムスタンプから引いています。これで新しい画像が最も小さな数値となります。
ファイルの読み込み
画像のアップロードと読み込みは完全に独立しています。ブラウザからアップせず、フォルダに直接画像を入れてもファイル名の順に表示できるようになっています。 画像の読み込みも基本は「こんなこと・・・」のアップロ−ダ3とまったく同じですが、再びファイル名のチェックを行っています。これは画像以外(この場合はjpgとgifのみ)のファイルを無視するためです。読込んだファイル名は配列に入れます。 この時、画像以外のファイルがあると、配列のキーに中抜けが起こるのです。 $filename[0] = 画像1 $filename[1] = 画像2 $filename[2] = バックアップファイル(例えば) $filename[3] = 画像3 $filename[4] = 画像4 これをソートすることで解決しています。 $filename[0] = 画像1 $filename[1] = 画像2 $filename[2] = 画像3 $filename[3] = 画像4 さらにここで保存設定枚数を超えた場合の画像ファイル削除も行います。
$delete = 53; //画像最大枚数 if($filenames[$delete] != null){ unlink("$updir$filenames[$delete]"); array_pop($filenames); //配列の最後、つまり指定番号のファイル名も削除 }
画像データの取得
新しく登場するのがイメージ関数の getimagesize です。
$f_data = getimagesize("$updir$filenames[$f_cnt]");
これで、$filenames[$f_cnt] つまり画像$f_cnt番のデータが取得できるのです。そのデータは配列に入れられるので、これを表示させると・・・
$f_data[0] => 473 画像の幅 $f_data[1] => 426 画像の高さ $f_data[2] => 2 画像の種類 $f_data[3] => width="473" height="426" タグで直接利用できる文字列 $f_data[bits] => 8 カラーの数 $f_data[channels] => 3 RGB画像は3、CMYK画像は4 $f_data[mime] => image/jpeg 画像のMIMEタイプ
画像の種類は→ 1 = GIF, 2 = JPG, 3 =PNG, 4 = SWF, 5 = PSD, 6 = BMP, 7 = TIFF(intel byte order), 8 = TIFF(motorola byte order), 9 = JPC, 10 = JP2, 11 = JPX, 12 = JB2, 13 = SWC, 14 = IFF, 15 = WBMP, 16 = XBM
こうなります。このうち使用するのはもちろん0番と1番です。
2次元配列
5枚の写真を綺麗に並べるためには毎回計算を行わなければなりません。whileを使って1行分を表示させ、さらにそれをwhileで数行分のテーブルを表示させています。 このとき画像の名前は配列に入っていますから、順に表示できます。その番号とデータの入った配列をシンクロさせるわけです。 しかし、1枚の画像データは1つの配列に入っているので、データの配列は画像の枚数と同じだけ必要になるのです。これではシンクロは無理なのです。 そこで登場するのが2次元配列です。これはその名のとおり配列が二重になっているのです。
$f_data[0][0];
このようにキーを2つ並べるだけで、2次元配列を表示できます。
$f_data[0][0] 画像0番の横幅 $f_data[0][1] 画像0番の高さ $f_data[0][2] 画像0番の種類 $f_data[1][0] 画像1番の横幅 $f_data[1][1] 画像1番の高さ $f_data[1][2] 画像1番の種類
となるのです。
$f_data[$f_cnt] = getimagesize("$updir$filenames[$f_cnt]");
配列である$f_dataに、配列である画像データを格納しているので、この時点で$f_dataが2次元配列になるのです。
画像の表示、テーブルの繰返しとページ
画像のヨコ枚数は5枚で固定ですが、タテに何段並べるかは変更できます。1行を表示させる部分をさらにwhileで行数分繰り返しているので、画像番号の表示が複雑になっています。同時に2ページ目の場合も画像番号が増えるので
$pgplus = $col*5*($page_num-1); $f_cnt = 0+$times*5+$pgplus;
$f_cnt が画像番号なのですが、2行目は5の倍数($times*5)を追加し、2ページ目は1ページで表示した画像の枚数($pgplus)を加えて画像番号としているのです。 複雑なスクリプトになってしまいました。もっと良い方法があるかもしれませんが今後も模索を続けたいと考えています。 画像がそのまま縮小なので、本来はサムネイルを自動作成できるようにするともっと良いと思うのですが、今回は見送りです。
⇒こんな感じ |