前回の「携帯絵文字変換スクリプトの改良版 (PHP・SSI対応版)を作りました」の記事や
過去の記事においてもたびたびご質問があったケースについてここで一度回答したいと思います。
ご質問いただいた方ありがとうございました。
質問の内容は、
「ドコモの絵文字がすべて白黒で表示されてしまう」
という問題です。当ブログで配布している携帯絵文字変換スクリプトに限らず、
ある指定をHTMLにしていると、ドコモの絵文字がすべて黒で表示されてしまいます。
その条件とは、
①HTMLで、BODYタグ内の属性においてページ全体の文字色を指定しているケース
例: <body text="#000000">…
どちらの場合の例でも、ページ全体の文字色を黒に指定していますが、②XHTMLまたはHTMLでBODYタグ内のstyle属性でCSSでページ全体の文字色を指定しているケース
例: <body style="color:#000;">…
ドコモ端末の場合に限り、この指定をしてしまうと、
絵文字の色もすべてテキストと同じ色になってしまいます。
これは、結論から言ってしまうとドコモの仕様であり、
ドコモの絵文字が平滑な2Dのピクトグラムであるためです。
他のキャリアではそもそも絵文字がソリッド感のある3Dのドットイメージのため、
絵文字自体に多くの色が使われており、その色自体を変更することはできません。
このドコモの仕様がいいのやら悪いのやら…
まぁそこは利点でもあり欠点でもあるので、この仕様を理解した上で、
うまく使いこなすことをオススメします。
ちなみに、ドコモのデフォルトの絵文字色を変更する場合は、
とし、HTMLでは
<font color="#******">絵文字</font>
とします。XHTMLまたはHTMLでは
<span style="color:#******;"></span>
P.S 書籍「携帯サイト コーディング&デザイン」の増刷(第3刷り)がまたまた決定しました!
ご購入いただいた方々本当にありがとうございます。

今回はその改良版です。今まで、こちらの携帯絵文字変換スクリプトを使用していた方で、
どうやっても動作しないよ!と悩んでいた方はこちらに変えてみてください。
改良点は以下の通り。
・もちろん
・PHPとSSI両方に対応
・安定動作のため、Unicode数値参照方式(\\\\;)に変更
・PHPは4と5で動作
・PCで閲覧した場合にも絵文字が表示される
・ドコモの絵文字を基準とするのはそのまま
以前の携帯絵文字変換スクリプトはドコモの絵文字においてShift-JISの2バイトコードを
絵文字の変換テーブルに用いていたため、サーバー環境によっては文字化けが起きたり、
XHTMLとHTMLで動作が異なったりしていましたが、今回は全キャリアが対応している
Unicodeという数値参照方式を採用しているのため、絵文字の出力が安定的
(サーバーの環境に依存しにくい)です。
では、まず、サンプルから。
■PHPで動作させる場合
■SSIで動作させる場合
サンプルソースはこちらからダウンロードできます。
ファイル構成は以下の通り。[ ]はフォルダ。
------------------------------------
[public_html]
├[include]
├[emoji]
├[images]--***.gif (PC絵文字用の画像)
└table.tsv (絵文字変換テーブル)
├commons.php (共通ファイル読み込み)
├emoji_trans.php (絵文字変換スクリプト)
└user_agent_carrier.php (キャリア判別)
├.htaccess (SSIをHTMLで動作させるためのファイル)
├test_emoji.php (絵文字をPHPから読み出す場合のサンプルファイル)
└test_emoji_ssi.html (絵文字をSSIから読み出す場合のサンプルファイル)
------------------------------------
※includeフォルダ以下の構成は変えない方が良いです。
では一つづつ解説していきます。
■table.tsv (絵文字変換テーブル)
絵文字 (Unicode)の変換テーブルです。1~3列目でドコモ、au、ソフトバンクの順番。
各キャリア絵文字をUnicodeで入力する場合は「\\\\;」となりますが、この「\\\\」の部分のみ
このファイルに書いてあります。なお、Unicodeで絵文字を入力する場合、
ドコモではiモードHTML4.0以上となっているので、これ以上の機種が対応となります。
■commons.php (共通ファイル読み込み)
絵文字変換スクリプトに必要なファイルを読み込むためのファイルです。
includeフォルダ以下の構成を変えない限り特に変える部分はありません。
■emoji_trans.php (絵文字変換スクリプト)
この部分が絵文字変換の肝となるスクリプトです。
以下の部分を必要に応じて変えます。
絵文字変換テーブルの場所を指定します。このファイルからの相対パスで記述します。○12行目
//絵文字変換テーブル(相対パス)
$emoji_data = "/emoji/table.tsv";
通常はそのままでOK。
PC絵文字用のGIFファイルが格納されているフォルダの場所を、○15行目 (重要!)
//PC用絵文字格納フォルダ(トップディレクトリからの相対パス)
$emoji_img_dir = "/include/emoji/images/";
トップディレクトリからの相対パスで指定します。その他の部分は、すべてそのファイルからの
相対パスですが、この部分はトップディレクトリからの相対パスにしてください。
つまり、[include]以下のフォルダの場所(階層)によってこの部分は書き換える必要があります。
○18行目 (重要!)
PHPから読み出す場合は「0」に、SSIから読み出す場合は「1」に設定します。//動作モード(PHPから呼び出す場合は0、SSIなら1)
$mode = 0;
SSIで動作させる場合にこの部分が「0」のままだと正しく動作しません。
■user_agent_carrier.php (キャリア判別)
携帯端末のキャリアを判定する関数。
ここも通常はこのまま。
■.htaccess (SSIをHTMLで動作させるためのファイル)
HTMLでSSIを動作可能にするためのおまじないファイルです。
「AddHandler server-parsed html」とするのがミソ。(それ以外の部分は関係ありません)
HTMLと同じフォルダに設置します。ただし、htaccessが設置可能なサーバーに限ります。
また、SSIで動作させない場合はこのファイルは必要ありません。
■test_emoji.php (絵文字をPHPから読み出す場合のサンプルファイル)
まず、上の共通ファイルである「commons.php」をincludeする文を冒頭で指定。
相対パスで指定すればOKです。
あとは、絵文字番号を以下のように指定して、絵文字を表示させたい部分に書けばOK。
絵文字番号表はこちらに掲載しています。<?php emoji('1');?>
■test_emoji_ssi.html (絵文字をSSIから読み出す場合のサンプルファイル)
SSIから読み出す場合は、ちょっと気をつける点があります。こちらも絵文字番号を指定するだけでOK。
<!--#include virtual="/include/emoji_trans.php?emoji=1"-->
まず、「virtual」でSSIは読み出さないと、「?」以下の「emoji」という引数が渡されないため、
このようにします。「exec」では引数が渡されないためNG。
従って、SSIの読み出しで「virtual」が不可となっているサーバーでは使用できないので注意してください。
また、パスはトップディレクトリからの相対パスで「emoji_trans.php」がある場所を指定します。
絵文字番号はPHPから読み出す場合と同じです。
以上です。

そこで指定すべきコンテンツMIMEタイプはどのようにしなければならないか。
これはこのブログや書籍をご購入いただいた方はすでにご存じかと思いますが、
ドコモの仕様に合わせて「application/xhtml+xml」を指定するということでした。
再度説明するとドコモがXHTMLモードになる条件は
①サーバーが出力するHTTPヘッダーを「application/xhtml+xml」とする。
②metaタグの「content」を「application/xhtml+xml」とする。
ことでした。しかし、この方法では、
1. 古い機種によってはエラーになってしまう可能性があること。
2. auやソフトバンクはMIMEタイプを「text/html」としてもXHTMLで動作すること。
3. 「application/xhtml+xml」としなければならないのはドコモのFOMAだけであるということ。
を鑑みると、仕様上「must」でなければならないFOMAを除いては「text/html」でもよい。
という考えもありかと思っています。
そこで、ドコモのFOMAのみ「application/xhtml+xml」を出力するPHPで動作する
プログラムを作ってみました。
■USER AGENT DOCOMO SWITCH FUNCTION (user_agent_docomo.php)
まず、ドコモ端末においてmovaとFOMAを判断するプログラムを関数化しました。
以下がソースコード。
ユーザエージェントはmovaが「DoCoMo/1.0…」、FOMAが「DoCoMo/2.0…」です。
user_agent_docomo( )関数にユーザエージェントを投げると、
「foma」 or 「mova」という文字列を返します。
このあたりはPEARライブラリのNet_UserAgent_Mobileを使ってもよいでしょう。
<?php
//┌─────────────────────────────────
//│ [ USER AGENT DOCOMO SWITCH FUNCTION Ver1.0]
//│ user_agent_docomo.php - 2009/01/27
//│ Copyright (C) DSPT.NET
//│ http://www.dspt.net/
//└─────────────────────────────────
//携帯端末のユーザエージェントを判定(ドコモのみmovaとFOMAの判別あり)
function user_agent_docomo($data){
if(preg_match("/^DoCoMo\/1\.0/i", $data))
{
return "mova"; // mova
}
if(preg_match("/^DoCoMo\/2\.0/i", $data))
{
return "foma"; // FOMA
}
else {
return "unknown"; // unknown
}
}
?>
■CONTENTS MIME TYPE SWITCH FUNCTION (mime_type.php)
この結果を受け取り、ドコモのFOMAのみ「application/xhtml+xml」の
コンテンツMIMEタイプを返すプログラムの関数は以下。
以下で指定するmime_type( )関数において、fomaが投げられた場合、
「application/xhtml+xml」という文字列を返します。
<?php
//┌─────────────────────────────────
//│ [ CONTENTS MIME TYPE SWITCH FUNCTION Ver1.0]
//│ mime_type.php - 2009/01/27
//│ Copyright (C) DSPT.NET
//│ http://www.dspt.net/
//└─────────────────────────────────
//ドコモのFOMAのみ適切なコンテンツMIMEタイプを出力する
function mime_type($data) {
if($data == 'foma') {
return "application/xhtml+xml";
}
else {
return "text/html";
}
}
?>
以上で必要なプログラムはおしまい。
あとはこのファイルをインクルードして、以下のようなサンプルPHPとして動作させれば、
適正なコンテンツMIMEが指定されたHTMLとなります。
■テストプログラム (test_mime_type.php) テストURL
<?php
include ('include/user_agent_docomo.php'); // USER AGENT DOCOMO SWITCH
include ('include/mime_type.php'); // MIME TYPE
include ('include/cache_control.php'); // CACHE CONTROL
//携帯UA取得
$agent = user_agent_docomo($_SERVER["HTTP_USER_AGENT"]);
//HTTPヘッダー
header("Content-Type: ".mime_type($agent));
echo "<?xml version=\"1.0\" encoding=\"Shift_JIS\"?>\n";
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<meta http-equiv="Content-Type" content="<?php echo mime_type($agent);?>; charset=Shift_JIS" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<?php echo cache_control('on','xhtml');?>
<meta name="description" content=" " />
<meta name="keywords" content=" " />
<meta name="robots" content="index,follow" />
<title>MIME TYPE</title>
</head>
<body>
<!--WRAPPER-->
<div style="font-size:x-small;">
UA : <?php echo $_SERVER["HTTP_USER_AGENT"];?><br />
Content-Type: <?php echo mime_type($agent);?><br />
</div>
<!--WRAPPER END-->
</body>
</html>
$_SERVER["HTTP_USER_AGENTにより携帯端末からユーザエージェントを抜き取り、
先ほど2つの関数が書かれたファイルをインクルードします。
あとはHTTPヘッダーとmetaタグのコンテンツMIMEタイプを指定する部分に、
mime_type関数より適正なMIMEタイプを出力します。
■CACHE CONTROL SWITCH FUNCTION (cache_control.php)
ちなみに、「cache_control」という関数は、キャッシュコントロールを制御するための
metaタグを適正に出力するというものでおまけ。「include」で読んでいる「cache_control.php」は
以下のようなソースコードになっています。
キャッシュOFFとONの切り替えができるのと、HTMLとXHTMLのmetaタグの切り替え機能がついています。
cache_control('on','xhtml')とすると、キャッシュオフのmetaタグを出力するとともに、
XHTML用のmetaタグを出力します。cache_control('on','html')とすれば、HTML用のmeta
タグを出力します。cache_control('off','***')とすれば、
キャッシュオフのmetaタグを出力しないというよりmetaタグそのものを出力しません。
<?php
//┌─────────────────────────────────
//│ [ CACHE CONTROL SWITCH FUNCTION Ver1.0]
//│ cache_control.php - 2009/01/27
//│ Copyright (C) DSPT.NET
//│ http://www.dspt.net/
//└─────────────────────────────────
//キャッシュコントロール制御
function cache_control($data,$html) {
$meta_line1 = "<meta http-equiv=\"pragma\" content=\"no-cache\"";
$meta_line2 = "<meta http-equiv=\"cache-control\" content=\"no-cache\"";
$meta_line3 = "<meta http-equiv=\"expires\" content=\"-1\"";
if($data == 'on') {
if ($html == 'xhtml') {
$out = $meta_line1." />\n".$meta_line2." />\n".$meta_line3." />\n";
}
else {
$out = $meta_line1.">\n".$meta_line2.">\n".$meta_line3.">\n";
}
return $out;
}
else {
return "";
}
}
?>
なお、ソースコードを保存するのが面倒という方は、
こちらからダウンロードできますので。

各社どのように対応するか詳しく挙動を調べてみたのでメモ。
|
※画像はbackground-imageで指定するが、ドコモではbodyタグのみ。
ソース例
合成形はあまり指定することはないですが、<body style="background:url(./image.gif) no-repeat; background-position:30px;">
<!--WRAPPER-->
<div style="font-size:xx-small;">
<div style="background:navy;color:white;text-align:center;"><background-position></div>
<br />
<!--文字-->
background-positionの挙動<br />
body要素に適用<br />
</div>
<!--WRAPPER END-->
</body>
auでは対応してないようです。

ドコモ iモードサイト作成時のHTML DOCTYPEまとめ
(http://dspt.blog59.fc2.com/blog-entry-37.html)
について書きましたが、今読み返すとあまりに適当な気がして、
読者の方に誤解を招くのは申し訳ないので、携帯サイトを制作する際に、
DOCTYPEはどのように記述すべきかもう一度考えてみます。
現在、各キャリアが推奨しているDOCTYPEは、
Kamitani79-メロンとバナナとブログさんに書かれているように、各社独自に定めています。
が、しかし実際のところは、3キャリア共通のXHTMLを書く場合には、
XHTML Mobile Profileに従って記述するほうが、各社のXHTMLの仕様を見ても、
一番合っている気がします。
ただ、XHTML Mobile Profileはかの有名なW3Cが勧告したものではなく、
携帯端末の特性に合わせて、WAP Forumが仕様化したもの。
PCのようにW3Cに合わせるべきだという論調に従うのであれば、
W3Cがモバイル用に定めた、XHTML Basicに合わせる方がよいのでは?という意見もあります。
ただし、XHTML Basicではstyle属性によるCSSの指定ができません。
PCサイトを制作してきた人にとっては、今更style属性なんて。
と思われるかもしれませんが、携帯サイトでCSSを使う場合、
ドコモではstyle属性でしかできません。
ということで、どっちみち3キャリア対応とするならば、
XHTML Mobile ProfileかXHTML 1.0 Transitionalあたりを使うほかない気がします。
検索エンジンへのフォローという意味では、
GoogleはDOCTYPEにXHTML Basicを
それでいいの?という疑問符がつきます。
もちろん、検索エンジンのロボットはこのDOCTYPEだけで、携帯サイトを認識するのではなく、
例えば「絵文字が含まれているか」とか「半角カナが使われているか」、「ページ容量はどのくらいか」というように複合的に判断しているらしいので、
ということで、私は以下のDOCTYPEがよいのでは?という考えで、サイトを制作しています。
■XHTML Mobile Profile 1.0
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
"http://www.wapforum.org/DTD/xhtml-mobile10.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml">
■XHTML 1.0 Transitional
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
※2008年12月9日 追記
はてなブックマークで以下のコメントをいただきました。
「XHTMLBasic 1.1」でXHTML Mobile Profileは統合された…
こちらのミツエーリンクスさんの情報では、
XHTML BasicにXHTML Mobile Profileが統合されるようXHTML Basic1.1が「勧告候補」となった。
と記されています。あくまで勧告なので、日本を始めメーカー、キャリアが今後この勧告を受け入れていけば、標準化(統一化)されていくでしょう。
ただし、現状ではドコモやauなどでも、XHTML Basic1.1には対応していません。
今後に期待されます。

豊富な表現が可能になっています。(ドコモはダメ)
ただし、auとソフトバンク端末に搭載されているブラウザは種類が異なるので、
3キャリア対応のサイトを1枚のHTMLで作る場合は、文字サイズなどの違いがどうしてもでてきてしまいます。これに対処するためには、auとソフトバンク端末で読み込む外部CSSを切り替えてあげる方法があります。
そこで、今回はauとソフトバンクで外部CSSを切り替えるスクリプトをご紹介します。
まず、どのような設計にするかというと、
・au用の外部CSS「css_au.css」とソフトバンク用の外部CSS「css_sb.css」を用意する。
・au端末でアクセスしてきたら、「css_au.css」を読み込むようにlinkタグを発行する。
・同様に、ソフトバンク携帯には「css_sb.css」を読み込むようなlinkタグを発行する。
・それ以外のドコモ端末やPCでのアクセスには「dummy.css(空)」を読み込ませる。
・HTMLとXHTML用のlinkタグを発行できる。
・SSIを利用する。
のようになっています。
では以下スクリプトです。
ソース:http://www.dspt.net/data/css_switcher/css.txt
<?php
//┌─────────────────────────────────
//│ [ MOBILE CSS SWITCHER Ver1.0]
//│ css.php - 2008/08/21
//│ Copyright (C) DSPT.NET
//│ http://www.dspt.net/
//└─────────────────────────────────
/********************** 初期設定 ***********************/
//au,softbank用のCSS格納フォルダ(トップディレクトリから相対指定)
$css_dir = '/data/css/';
//CSS命名規則(末尾に付ける名前)
$au = "_au.css"; //au
$sb = "_sb.css"; //softbank
//HTMLの種類(0:HTML 1:XHTML)
$html_type = 1;
/********************** 以下からは改変しないほうが無難 ***********************/
//文字エンコード変換
function encode($data) {
$data = mb_convert_encoding($data, "SJIS", "auto");
return $data;
}
//共通CSS名を取得
$filename = encode($_GET["file"]);
$au_file = $filename.$au;
$sb_file = $filename.$sb;
//HTMLの種類によって出力するヘッダ末尾
function html($data) {
if ($data == 1) {
$out = " />";
} else {
$out = ">";
}
return $out;
}
//携帯UA取得
$agent = $_SERVER["HTTP_USER_AGENT"];
//携帯端末のユーザエージェントを判定
function mobile($data){
if(preg_match("/^DoCoMo\/[12]\.0/i", $data))
{
return "i";// i-mode
}
elseif(preg_match("/^(J\-PHONE|Vodafone|MOT\-[CV]980|SoftBank)\//i", $data))
{
return "s";// softbank
}
elseif(preg_match("/^KDDI\-/i", $data) || preg_match("/UP\.Browser/i", $data))
{
return "e";// ezweb
}
elseif(preg_match("/^PDXGW/i", $data) || preg_match("/(DDIPOCKET|WILLCOM);/i", $data))
{
return "w";// willcom
}
elseif(preg_match("/^L\-mode/i", $data))
{
return "l";// l-mode
}
else {
return "p";// pc
}
}
//携帯UA判定後の値を取得
$flag = mobile($agent);
//キャリアによってCSSを振り分ける処理
function switch_css($data) {
global $css_dir,$au_file,$sb_file,$html_type;
if ($data == "e" ) {
$file_out = $css_dir.$au_file;
$out = "<link rel=\"stylesheet\" href=\"".$file_out."\" type=\"text/css\"".html($html_type);
}
elseif ($data == "s" ) {
$file_out = $css_dir.$sb_file;
$out = "<link rel=\"stylesheet\" href=\"".$file_out."\" type=\"text/css\"".html($html_type);
} else {
$file_out = $css_dir."dummy.css";
$out = "<link rel=\"stylesheet\" href=\"".$file_out."\" type=\"text/css\"".html($html_type);
}
echo $out;
}
//処理
switch_css($flag);
?>
結構作りは単純です。
まず、それぞれのCSSを保存しておくフォルダを指定します。
本スクリプトではトップディレクトリからの相対パスで指定するようになっています。
SSIでは以下のように書いてスクリプトを読み込みます。
<!--#include virtual="/data/css_switch/css.php?file=css"-->
file=のところで、CSSの共通ファイル名(拡張子抜き)を指定します。
上記例ではcssというファイル名が渡されます。
スクリプトの命名規則のところで指定した通りに、末尾が追加されるので、
例えば、au用ではcss + _au + .cssで「css_au.css」となります。
後は、アクセスした端末のユーザエージェントを判断して、
それぞれの外部CSSを読み込むlinkタグを発行します。
例えばソフトバンクなら、以下のようなリンクタグを発行します。
<link rel="stylesheet" href="/data/css/css_sb.css" type="text/css" />
linkタグはHTMLの場合とXHTMLの場合で書き方が異なりますから、(といっても最後のスラッシュ/)
正確を期すためにスクリプト上部で指定したとおりにlinkタグを発行するようになっています。
出力先のファイルがHTMLなら「$html_type」のところを「0」に、XHTMLなら「1」にします。
このスクリプトを使って、どのような使い方ができるかというと、
例えば、DIVタグ内の背景色をキャリア別(ドコモはnavy、auはorange、ソフトバンクはgray)に変えて、さらにauとソフトバンクのみ行間を120%にしたい場合を考えます。
まず、HTML内には以下のように記述します。
<div style="background-color;navy;">
<div class="line">
文字文字文字文字文字文字文字文字
</div>
</div>
行間を変えたいCSSプロパティは外部CSSが読めるauとソフトバンクで共通ですから、
共通用のCSS(mobile.css)を作って、普通にlinkタグをHTMLのヘッダーにべた打ちします。
その下にCSSを切り替えるSSIを記述します。
<link rel="stylesheet" href="/data/css/mobile.css" type="text/css" />
<!--#include virtual="/data/css_switch/css.php?file=css"-->
そして、mobile.cssには以下のように記述します。
.line {
line-height:120%;
}
また、au用のCSS(css_au.css)には以下のように記述します。
.line {
background-color;orange;
}
一方、ソフトバンク用のCSS(css_sb.css)には
.line {
background-color;gray;
}
と記述します。
こうすることで、まず共通用のmobile.cssが読めるauとソフトバンク携帯は、行間が120%になる一方で、すでにstyle属性でbackgroud-colorプロパティが指定されていて、外部CSSの読めないドコモ端末はnavy色で背景が表示されます。さらに、auではスクリプトによって切り替えられたCSSを追加で読み込み、すでにstyle属性で指定されているbackground-colorプロパティをorangeに上書きします。同様な方法で、ソフトバンク携帯では背景色をgrayに上書きします。
このようにすれば、1枚のHTMLで3キャリア別々のスタイルを適用することができます。

前回の記事「モバゲーのような携帯サイトを作るための12のTips」が予想以上の大反響で少々びっくりしてます。はてブの数とか半端ないです。こんなブックマークが付く記事を書いたことがありません。笑
いといろとコメントくださった方ありがとうございます。
おかげさまで、この記事以来、怒濤のように仕事が舞い込んできており、
多忙の毎日を送っています。
さて、今回は前回の記事のコメントでいただいた、
ソフトバンクのVGA端末でのサイト内画像の出力に関するお話です。
前回の記事で、ソフトバンクの高解像度(横240ピクセル以上)VGA端末では、ロゴなどの画像を他のキャリアに合わせて横240ピクセルで作成した画像を表示すると、高解像度のまま小さく表示されてしまう(けっこうかっこ悪い…)という問題がでてきてしまうという点について触れました。
ちなみに、ソフトバンク以外のキャリアの端末では高解像端末でも、画像の自動拡大縮小機能がブラウザについているので、画面ぴったりに表示されます。ちょうど以下のような感じ。
確かにソフトバンクの端末は挙動としては最も正しいのですが、このサイトの方針のように3キャリア対応で作成するとなると、やはりこの問題は無視できません。画像のwidth属性を100%で指定すれば、とりあえず画面いっぱいに表示されますが、これだと画像が拡大され粗が目立ってしまってかっこ悪い。
そこで、今回は他とは違ったアプローチでこの問題を簡易的に解決する方法を考えました。
結論から言うと、今回も絵文字のときと同じようにスクリプトに頼るのですが、
今回もコーダー視点で作成し、導入の敷居は低く設定してます。このブログのターゲットやサイト規模とかも考えて、MobaSiFのようなフレームワークを導入するほどじゃないんだけど…って人結構多いですからね。
今回のスクリプトの設計はというと、
・1枚のオリジナル画像(横480ピクセル×縦自由のJPG)を3キャリアで共有する。
・ソフトバンク端末のVGA機種(正確には横400ピクセル以上の端末)のみ、オリジナル画像をそのまま表示する。
・その他のキャリアは画像をサーバー側で縮小(GDを利用)し、横240ピクセルに縮小した画像を出力する。
・HTMLからの読み出しはSSIを使用する。
ただこれだけです。本来は、端末から機種名を読み出し(画像サイズを端末から読み出せないキャリアもあるため)、画像サイズのデータベースと照らし合わせ、適切な画像サイズに加工してから最適なサイズで出力する。といったスクリプトが一番良いのですが、そこまで対応させる労力はありません。すみません。
ではスクリプトです。
サンプルURL:http://www.dspt.net/data/imagetrans/
ソース:http://www.dspt.net/data/imagetrans/trans.txt
<?php
//┌─────────────────────────────────
//│ [ IMG TRANS Ver1.0]
//│ trans.php - 2008/08/13
//│ Copyright (C) DSPT.NET
//│ http://www.dspt.net/
//└─────────────────────────────────
/********************** 初期設定 ***********************/
//リサイズ後の画像保存先ディレクトリ(相対パス)
$img_dir = 'images/';
/********************** 以下からは改変しないほうが無難 ***********************/
//対象画像のファイル名を取得
$img_file = $_GET["file"];
//エンコード変換(オプション)
function encode($data) {
$data = mb_convert_encoding($data, "SJIS", "auto");
return $data;
}
//携帯UA取得
$agent = $_SERVER["HTTP_USER_AGENT"];
//携帯端末のユーザエージェントを判定
function mobile($data){
if(preg_match("/^DoCoMo\/[12]\.0/i", $data))
{
return "i";// i-mode
}
elseif(preg_match("/^(J\-PHONE|Vodafone|MOT\-[CV]980|SoftBank)\//i", $data))
{
return "s";// softbank
}
elseif(preg_match("/^KDDI\-/i", $data) || preg_match("/UP\.Browser/i", $data))
{
return "e";// ezweb
}
elseif(preg_match("/^PDXGW/i", $data) || preg_match("/(DDIPOCKET|WILLCOM);/i", $data))
{
return "w";// willcom
}
elseif(preg_match("/^L\-mode/i", $data))
{
return "l";// l-mode
}
else {
return "p";// pc
}
}
//横240ピクセル用の画像を作成(GD利用)
$img_240 = ImageCreateFromJPEG($img_file);
$width = ImageSx($img_240);
$height = ImageSy($img_240);
$resize_width = $width/2;
$resize_height = $height/2;
$out = ImageCreateTrueColor($resize_width, $resize_height);
$base = basename ($img_file,".jpg");
$img_filename = $img_dir.$base."_240.jpg";
ImageCopyResampled($out, $img_240, 0, 0, 0, 0, $resize_width, $resize_height, $width, $height);
ImageJPEG($out, $img_filename, 100);
//パス取得
$path = dirname($HTTP_SERVER_VARS['PHP_SELF'])."/".$img_filename;
$path_s = dirname($HTTP_SERVER_VARS['PHP_SELF'])."/".$img_file;
//ソフトバンク携帯の場合
if (mobile($agent) == "s") {
//ソフトバンク携帯の画面サイズ取得
$softbank_display = $_SERVER["HTTP_X_JPHONE_DISPLAY"];
$display = array();
$display = explode("*", $softbank_display);
//縦横それぞれ取得
$softbank_display_width = $display[0];
$softbank_display_height = $display[1];
}
//携帯キャリアに合わせて画像タグを出力
function img_tag() {
global $agent,$img_file,$path,$path_s,$width,$height,
$resize_width,$resize_height,$softbank_display_width;
switch(mobile($agent)){
case "i";
$put = "<img src=\"".$path."\" width=\"".$resize_width."\" height=\"".$resize_height."\" alt=\" \" /><br />";
break;
case "e";
$put = "<img src=\"".$path."\" width=\"".$resize_width."\" height=\"".$resize_height."\" alt=\" \" /><br />";
break;
case "s";
if ($softbank_display_width > 400) {
$put = "<img src=\"".$path_s."\" width=\"".$width."\" height=\"".$height."\" alt=\" \" /><br />";
} else {
$put = "<img src=\"".$path."\" width=\"".$resize_width."\" height=\"".$resize_height."\" alt=\" \" /><br />";
}
break;
case "p";
$put = "<img src=\"".$path."\" width=\"".$resize_width."\" height=\"".$resize_height."\" alt=\" \" /><br />";
break;
}
echo $put;
}
//処理
img_tag();
?>
このスクリプトの仕組みは、まず、対象となる画像を以下のようにHTML側でSSIで指定し、本PHPを読み出します。
<!--#include virtual="/data/imagetrans/trans.php?file=test.jpg"-->
赤字の部分で読み出したい画像のファイル名を「file=ファイル名」で指定します。
オリジナルとなる画像(test.jpg)はPHPスクリプトと同じディレクトリに置く必要があります。
今回もPHPの場所はトップディレクトリから相対パスで指定します。
スクリプトはSSIで指定された画像を読み出し、とりあえず縮小版(横240ピクセル)をGDを使って作成し、スクリプト冒頭で指定したフォルダ(実行権限を707等にすること)に「_240」をつけて保存(test_240.jpg)します。
例によって、SSIをHTMLで読み出してやらなければなりませんから、.htaccess等に
以下の一文を追加し、PHPと同じディレクトリに置きます。
AddHandler server-parsed html
GDについては、サーバー側にインストールされている必要がありますが、たぶんたいていは大丈夫かと。不安であれは<?php phpinfo(); ?>でGDの項を見て「enable」になっていればOKかと思います。XREAサーバーで動作確認しました。
後は、携帯のユーザエージェントを判断して、ソフトバンクVGA端末以外は縮小画像を表示するHTMLタグを出力し、ソフトバンク端末のみ「HTTP_X_JPHONE_DISPLAY」というHTTPヘッダーから画面サイズを取得し、横が400以上の端末はオリジナル画像を表示するHTMLタグを出力する仕組みです。
このスクリプトはとりあえず付け焼き刃的なものなので、いったん縮小画像を作ってからも
毎回GDを起動してしまったりと若干効率が悪いです。この辺はファイルの存在を確認する一文を入れたほうがいいかも。時期を見計らってまた更新します。
本日は以上です。
