Logo
Java Web Wizardry Design Trivia Links
Wizardry > PHP & gd
PHPでグラフを作ろう!(修正版: gd ライブラリ GIFサポート復活記念)

PHP でいろいろとプログラムを作っていると、あるデータをグラフ化したくなってきます。そこで、グラフを作成するモジュールを探して使ってみることにします。

* PHPの状態と GD モジュール

PHP で、グラフを作成するのに便利なモジュールとして JpGraph, PHPlot があります。まず、これを利用するのに GD モジュールを有効にしなくてはなりません。

PHP の現在の状態を確認してください。

<?php
  phpinfo();
?>

その際、GD モジュールが enabled になっているか確認してください。有効になっていれば、以下のインストール作業は必要ありません。次のJpGraph, PHPlot の節に進んでください。

PHP で GD モジュールが有効でない場合、必要なパッケージを入手しインストールしなくてはなりません。システムを確認し、以下のリストの中で足りないものをインストールしてください。

GD Graphics Library Thomas Boutell氏の作成した、線や多角形、円を描画するためのライブラリ http://www.boutell.com/gd/
PNG graphics library PNG グラフィックスフォーマット用のライブラリ http://www.libpng.org/pub/png
zlib compression library zlib 汎用圧縮ライブラリ http://www.gzip.org/zlib/
FreeType TrueTypeフォントをレンダリングするライブラリ http://www.freetype.org/
JPEG library JPEG グラフィックスフォーマット用のライブラリ ftp://ftp.uu.net/graphics/jpeg/

インストール手順 (スーパーユーザーで作業)

  # gzip -dc zlib-1.1.4.tar.gz | tar xf -
  # cd zlib-1.1.4
  # ./configure
      (ダイナミックライブラリを作りたければコマンドラインオプション --shared を指定しておく)
  # make
  # make install
  
  # gzip -dc libpng-1.2.7.tar.gz | tar xf -
  # cd libpng-1.2.7
  # cp scripts/makefile.OS Makefile
      OS は、インストールする OS のタイプを指定:linux, solaris ...)
  # make
  # make install
  
  # gzip -dc jpegsrc.v6b.tar.gz | tar xf -
  # cd jpeg-6b
  # ./configure --enable-static
      (ダイナミックライブラリを作りたければコマンドラインオプション --enable-shared を指定)
  # make
  # make install
  
  # gzip -dc freetype-2.1.9.tar.gz | tar xf -
  # cd freetype-2.1.9
  # ./configure --enable-static
  # make
  # make install
  
  # gzip -dc gd-2.0.28.tar.gz | tar xf -
  # cd gd-2.0.28
  # ./configure --without-libiconv-prefix
      (iconv を指定したければコマンドラインオプション --with-libiconv-prefix=PATH を指定)
      (png, jpeg, freetype をきちんと指定したければコマンドラインオプション --with-????=PATH を指定)
    ...
    ** Configuration summary for gd 2.0.28:
 
       Support for PNG library:          yes
       Support for JPEG library:         yes
       Support for Freetype 2.x library: yes
       Support for Xpm library:          yes
       Support for pthreads:             yes
    ...
  # make
  # make install

PHP + Apache のインストール

基本的なインストール方法は、「PHP と PostgreSQL/MySQL で Web アプリケーションを!」を参照してください。ここでは、PHP で GD モジュールを有効にするコンフィグレーションを重点に記述します。

Apache はDSO(Dynamic Shared Object)対応でコンパイルし、インストールしてください。

PHP のソースの展開とコンパイル(DSOを作成する)

    # gzip -dc php-4.3.9.tar.gz | tar xf -
    # cd php-4.3.9
    # ./configure --with-pgsql=/usr/local/pgsql --with-mysql=/usr/local/mysql \
    > --with-apxs2=/usr/local/apache2/bin/apxs --enable-track-vars \
    > --enable-mbstring --enable-mbregex --enable-zend-multibyte \
    > --with-gd=/usr/local --with-freetype-dir=/usr/local --with-jpeg-dir=/usr/local \
    > --with-png-dir=/usr/local --with-zlib-dir=/usr/local --enable-gd-native-ttf \
    > --enable-gd-jis-conv
    # make
    # make install

コマンドラインオプションの説明(必要なもの選んでください)

--with-gd[=DIR] GD パッケージをインストールしたディレクトリを指定。DIR を指定しなかった場合、バンドルされている GD を使用。
--with-jpeg-dir[=DIR] libjpeg パッケージをインストールしたディレクトリを指定
--with-png-dir[=DIR] libpng パッケージをインストールしたディレクトリを指定
--with-zlib-dir[=DIR] libz パッケージをインストールしたディレクトリを指定
--with-xpm-dir[=DIR] libXpm パッケージをインストールしたディレクトリを指定
--with-ttf[=DIR] FreeType 1.x パッケージをインストールしたディレクトリを指定
--with-freetype-dir[=DIR] FreeType 2 パッケージをインストールしたディレクトリを指定
--with-t1lib[=DIR] T1lib パッケージをインストールしたディレクトリを指定
--enable-gd-native-ttf TrueType string function を有効にする
--enable-gd-jis-conv JIS-mapped Japanese font を有効にする

インストールが完了し、Apache を再起動したなら、PHP の現在の状態が以下のようになっていることを確認してください。

gd

 

* JpGraph, PHPlot クラス・ライブラリ

ここでは、二つのライブラリを紹介します。どのライブラリを使ったらよいかは、JpGraph は商用利用で有料ですが、PHPlot は商用での利用が可能です。しかし、PHPlot は日本語がうまく扱えません(使い方を知らないだけかも)。

● JpGraph

まず、JpGraph を使ってみましょう。 必要なモジュールをダウンロードしてインストールします。Windowsで使用したいなら「Windows版 PHP環境でグラフを作ろう!」を、Solaris 10 や PHP5 で使用したいなら「Solaris 10 に PHP5 と MySQL5 をインストール」 を参照してください。

JpGraph http://www.aditus.nu/jpgraph/
sazanami フォントを入手 http://sourceforge.jp/projects/efont/files/

JpGraph のライブラリは、どこに置いても構いませんが PHP がサーチできるパス (include_path)に置くか、インストールしたディレクトリを php.iniinclude_path に追加すると良いでしょう。 ここでは、include_path = ".:/usr/local/lib/php" となっているとして、/usr/local/lib/php/JpGraph にライブラリをインストール(コピー)します。

JpGraph 1.22 の場合: PHP5 で使用したいなら「Solaris 10 に PHP5 と MySQL5 をインストール」 を参考に。。。

JpGraph の設定は、キャッシュのディレクトリと TrueType フォントが含まれるディレクトリを指定します。デフォルトでは情報処理推進機構の日本語フォント(GRASS国際化版に付属)が指定されているためダウンロードしてインストールします。

    # gzip -dc grass5.0.3_i686-pc-linux-i18n-ipafull-gnu_bin.tar.gz | tar xf - ./fonts
    # mkdir -p /usr/local/fonts/truetype
    # cp fonts/*.ttf /usr/local/fonts/truetype/

JpGraph の設定設定(jpg-config.inc.php で、キャッシュのディレクトリと TrueType フォントが含まれるディレクトリと日本語のフォントを指定)

    # gzip -dc jpgraph-1.22.tar.gz | tar xf -
    # cp -rp jpgraph-1.22/src /usr/local/lib/php/JpGraph
    # edit  /usr/local/lib/php/JpGraph/jpg-config.inc.php
      39行目
        DEFINE("CACHE_DIR",   "/tmp/jpgraph_cache/");
        DEFINE("TTF_DIR",     "/usr/X11R6/lib/X11/fonts/truetype/");
        DEFINE("MBTTF_DIR",   "/usr/local/fonts/truetype/");
    # mkdir /tmp/jpgraph_cache
    # chmod 777 /tmp/jpgraph_cache

これで設定は完了です。

過去の設定

JpGraph の設定は、キャッシュのディレクトリと TrueType フォントが含まれるディレクトリを指定します。日本語のフォントも指定します。以下では、さざなみフォントを指定していますが、X Window などで、既に日本語の TrueType フォントを使用している場合、TrueType フォントのディレクトリの指定は X Window で使用している TrueType フォントのディレクトリを指定(TTF_DIR)してください。そのうえで、ゴシック、明朝のフォントを指定してください。X Window 利用している日本語の TrueType フォントを使用しする場合、以下のさざなみフォントを設定する作業は必要はありません。JpGraphで日本語を扱うには、文字コードをUTF-8 にする必要があります。

    # bunzip2 sazanami-20040629.tar.bz2
    # tar xf sazanami-20040629.tar
    # cd sazanami-20040629
    # mkdir /usr/local/fonts
    # mkdir /usr/local/fonts/truetype
    # cp sazanami-gothic.ttf /usr/local/fonts/truetype/sazanami-gothic.ttf
    # cp sazanami-mincho.ttf /usr/local/fonts/truetype/sazanami-mincho.ttf

JpGraph 1.16 の場合:
メインモジュールである jpgraph.php で、キャッシュのディレクトリと TrueType フォントが含まれるディレクトリと日本語のフォントを指定します。

    # gzip -dc jpgraph-1.16.tar.gz | tar xf -
    # cd jpgraph-1.16/src
    # edit jpgraph.php
      22 行目あたり
        DEFINE("CACHE_DIR", "/tmp/jpgraph_cache/");
        DEFINE("TTF_DIR",   "/usr/local/fonts/truetype/");
 
      76 行目あたり
        DEFINE("FF_CHINESE",31);
        DEFINE("FF_BIG5",31);
 
        // Japanese font
        DEFINE("FF_GOTHIC",40);
        DEFINE("FF_MINCHO",41);
 
      2615 行目あたり
        # FF_CHINESE => array(FS_NORMAL=>CHINESE_TTF_FONT, FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' )
        FF_CHINESE => array(FS_NORMAL=>CHINESE_TTF_FONT, FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' ),
        FF_GOTHIC =>  array(FS_NORMAL=>'sazanami-gothic.ttf', FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' ),
        FF_MINCHO =>  array(FS_NORMAL=>'sazanami-mincho.ttf', FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' )
    # mkdir /usr/local/lib/php/JpGraph
    # tar cf - . | (cd /usr/local/lib/php/JpGraph/; tar xf -)
    # mkdir /tmp/jpgraph_cache
    # chmod 777 /tmp/jpgraph_cahche

JpGraph 1.17 以降の場合(日本語フォント対応になり configファイルの設定で変更可能に!):
設定ファイルである jpg-config.inc で、キャッシュのディレクトリと TrueType フォントが含まれるディレクトリと日本語のフォントを指定します。ここでは、さざなみフォントを指定しています。きちんとプロポーショナルフォントを指定しなくてはいけないのだが、フォントが無いのでごまかしています。デフォルトでは情報処理推進機構の日本語フォント(GRASS国際化版に付属)が指定されているため、入手しインストールすると MBTTF_DIR の設定ぐらいで動作します。

    # gzip -dc jpgraph-1.17.tar.gz | tar xf -
    # cd jpgraph-1.17/src
    # edit jpg-config.inc
      41行目
        DEFINE("CACHE_DIR",   "/tmp/jpgraph_cache/");
        DEFINE("TTF_DIR",     "/usr/local/fonts/truetype/");
        DEFINE("MBTTF_DIR",   "/usr/local/fonts/truetype/");
        ...
      76行目
        // Japanese TrueType font used with FF_MINCHO, FF_PMINCHO, FF_GOTHIC, FF_PGOTHIC
        DEFINE('MINCHO_TTF_FONT',  'sazanami-mincho.ttf');
        DEFINE('PMINCHO_TTF_FONT', 'sazanami-mincho.ttf');
        DEFINE('GOTHIC_TTF_FONT',  'sazanami-gothic.ttf');
        DEFINE('PGOTHIC_TTF_FONT', 'sazanami-gothic.ttf');
    # mkdir /usr/local/lib/php/JpGraph
    # tar cf - . | (cd /usr/local/lib/php/JpGraph/; tar xf -)
    # mkdir /tmp/jpgraph_cache
    # chmod 777 /tmp/jpgraph_cahche

これで設定は完了です。

簡単な円グラフを作ってみましょう。以下のプログラムを適当なファイル名で Web サーバーの DocumentRoot下に置き、ブラウザーから実行すると円グラフが表示されます。JpGraph で日本語を扱うには、文字コードをUTF-8 にする必要があります。以下のサンプルでは入力漢字コードは、ギリシャ文字などを扱う場合などを考慮して eucJP-win としています(つまり、以下のサンプルは EUCで書かれているので mb_convert_encoding を利用して UTF-8 にしていますということ、サンプルが Shift-JIS で書かれていれば sjis-winUTF-8 にするようにし、UTF-8 で書かれていれば変換の必要はありません)。
※ 漢字変換を行うと、当然のことながら漢字コード特有の特殊文字や機種依存文字の変換はうまく行えません。

<?php
// 使用するグラフを読み込む
require_once("JpGraph/jpgraph.php");
require_once("JpGraph/jpgraph_pie.php");
require_once("JpGraph/jpgraph_pie3d.php");
 
// データの設定
$data_yes     = mb_convert_encoding("好き", "UTF-8", "eucJP-win");
$data_no      = mb_convert_encoding("嫌い", "UTF-8", "eucJP-win");
$data_unkown  = mb_convert_encoding("わからない", "UTF-8", "eucJP-win");
$data_none    = mb_convert_encoding("無回答", "UTF-8", "eucJP-win");
$data_legends = array($data_yes, $data_no, $data_unkown, $data_none);
$data         = array(       43,       15,           32,         10);
 
// グラフオブジェクトの生成
$graph = new PieGraph(350,300,"auto");
 
$title = mb_convert_encoding("にこにこ村について","UTF-8","eucJP-win");
$graph->title->Set($title);
$graph->title->SetFont(FF_GOTHIC, FS_NORMAL, 16);
$graph->legend->Pos(0.05, 0.95, "right", "bottom");
$graph->legend->SetFont(FF_GOTHIC, FS_NORMAL);
 
$pie = new PiePlot3D($data);
$pie->SetSize(0.4);
$pie->SetCenter(0.5,0.5);
$pie->SetLegends($data_legends);
 
$graph->Add($pie);
 
// イメージフォーマット
$graph->img->SetImgFormat('gif');
 
// グラフの表示
$graph->Stroke();
?>
円グラフ

今度は、折線グラフを作ってみましょう。以下のプログラムを適当なファイル名で Web サーバーのDocumentRoot下に置き、ブラウザーから実行すると折線グラフが表示されます。

<?php
// 使用するグラフ
require_once("JpGraph/jpgraph.php");
require_once("JpGraph/jpgraph_line.php");
require_once("JpGraph/jpgraph_canvas.php");
 
// データ
$labelx = array("1999", "2000", "2001", "2002", "2003", "2004");
$data1  = array(  1683,   1719,   1754,   1883,   1502,   1677);
$data2  = array(  1261,    996,    875,    794,    982,   1140);
$data3  = array(   101,    230,    380,    513,    827,   1843);
 
// Y軸用のコールバック関数
function yScaleCallback($aVal) {
    return number_format($aVal);
}
 
// グラフオブジェクトの生成
$graph = new Graph(500,400,"auto");
 
// 画像フォーマット
$graph->img->SetImgFormat("jpeg");
$graph->img->SetQuality(80);
// マージン left, right, top, bottom
$graph->img->SetMargin(60,40,70,40);
$graph->img->SetAntiAliasing();
$graph->SetScale("textint");
$graph->SetFrame(false);
$graph->SetColor('lightblue');
  
// タイトル
$title = mb_convert_encoding("にこにこ村交通事情","UTF-8","eucJP-win");
$graph->title->Set($title);
$graph->title->SetFont(FF_GOTHIC, FS_NORMAL, 14);
 
// X,Y軸
$graph->xaxis->SetTickLabels($labelx);
$graph->yaxis->SetLabelFormatCallback('yScaleCallback');
$graph->yaxis->SetTextLabelInterval(2);
$graph->yaxis->HideZeroLabel();
$graph->yaxis->SetTitleMargin(55);
$titley = mb_convert_encoding("人","UTF-8","eucJP-win");
$graph->yaxis->title->Set($titley);
$graph->yaxis->title->SetFont(FF_GOTHIC, FS_NORMAL);
$titlex = mb_convert_encoding("年度","UTF-8","eucJP-win");
$graph->xaxis->title->Set($titlex);
$graph->xaxis->title->SetFont(FF_GOTHIC, FS_NORMAL);
 
// グリッド
$graph->xgrid->Show(true,false);
$graph->ygrid->SetFill(true,'#EFEFFF@0.5','#DDEEFF@0.5');
 
// 凡例
$graph->legend->Pos(0.5, 0.08, "center", "top");
$graph->legend->SetLayout(LEGEND_HOR);
$graph->legend->SetFont(FF_GOTHIC, FS_NORMAL);
$graph->legend->SetShadow(false);
$graph->legend->SetLineWeight(1);
$graph->legend->SetColor('black','darkgray');
$graph->legend->SetFillColor('lightblue');
 
// 陸の交通手段
$legend1 = mb_convert_encoding("陸","UTF-8","eucJP-win");
$p1 = new LinePlot($data1);
$p1->mark->SetType(MARK_FILLEDCIRCLE);
$p1->mark->SetFillColor("blue");
$p1->mark->SetWidth(3);
$p1->SetColor("blue");
$p1->SetCenter();
$p1->SetLegend($legend1);
$graph->Add($p1);
 
// 海の交通手段
$legend2 = mb_convert_encoding("海","UTF-8","eucJP-win");
$p2 = new LinePlot($data2);
$p2->mark->SetType(MARK_SQUARE);
$p2->mark->SetFillColor("red");
$p2->mark->SetWidth(4);
$p2->SetColor("red");
$p2->SetCenter();
$p2->SetLegend($legend2);
$graph->Add($p2);
 
// 空の交通手段
$legend3 = mb_convert_encoding("空","UTF-8","eucJP-win");
$p3 = new LinePlot($data3);
$p3->mark->SetType(MARK_DIAMOND);
$p3->mark->SetFillColor("orange");
$p3->mark->SetWidth(6);
$p3->SetColor("orange");
$p3->SetCenter();
$p3->SetLegend($legend3);
$graph->Add($p3);
 
// コメント
$message = mb_convert_encoding("いろいろな交通手段","UTF-8","eucJP-win");
$t1 = new Text($message);
$t1->Pos(0.15,0.7);
$t1->SetOrientation("h");
$t1->SetFont(FF_GOTHIC, FS_NORMAL);
$t1->SetBox("white","black",'gray');
$t1->SetColor("black");
$graph->AddText($t1);
 
// グラフの描画
$graph->Stroke();
 
?>

折れ線グラフ

最後に、レーダーグラフを作ってみましょう。以下のプログラムを適当なファイル名で Web サーバーのDocumentRoot下に置き、ブラウザーから実行するとレーダーグラフが表示されます。

<?php
require_once("JpGraph/jpgraph.php");
require_once("JpGraph/jpgraph_radar.php");
 
// データ
$aryData = array(7,10,6,8,9); // 軸タイトル $aryTitle = array( mb_convert_encoding("走り", "UTF-8","eucJP-win"), mb_convert_encoding("乗り心地", "UTF-8","eucJP-win"), mb_convert_encoding("燃費", "UTF-8","eucJP-win"), mb_convert_encoding("操作性", "UTF-8","eucJP-win"), mb_convert_encoding("デザイン", "UTF-8","eucJP-win") ); // レーダーグラフの初期化 $graph = new RadarGraph(300,250,"auto"); $graph->img->SetAntiAliasing(); // 背景の設定 $graph->SetColor("white"); $graph->SetFrame(false);
// グラフの描画位置
$graph->SetCenter(0.5,0.55); // 軸の設定 $graph->axis->SetFont(FF_GOTHIC,FS_NORMAL); $graph->axis->title->SetFont(FF_GOTHIC,FS_NORMAL); $graph->axis->SetColor("#207870"); // グリッドの設定 $graph->grid->SetLineStyle("dotted"); $graph->grid->SetColor("gray"); $graph->grid->Show(); $graph->HideTickMarks(); // タイトルの設定 $graph->title->Set(mb_convert_encoding("ニコニコカー","UTF-8","eucJP-win")); $graph->title->SetFont(FF_GOTHIC,FS_NORMAL, 13); $graph->title->SetColor("#406898"); $graph->SetTitles($aryTitle); // プロットデータの作成 $plot = new RadarPlot($aryData); $plot->SetColor("#ff5588","#ffeeee"); //$plot->SetFill(false); $plot->SetLineWeight(2); // プロットデータの追加
$graph->Add($plot); // グラフの描画 $graph->Stroke(); ?>

レーダー

● PHPlot

SetUseTTF(), SetTTFPath(), SetDefaultTTFont() といったメソッドがあるので、日本語の TrueType フォントを使ってみようかと思ったのですがうまく動作しないのでまだ仮として記述します。気合を入れてチェックすればよいのですが時間が無いので適当な時期とともに以下の内容を変えていきます。

必要なモジュールをダウンロードしてインストールします。

PHPlot http://www.phplot.com/

PHPlot のライブラリは、どこに置いても構いませんが PHP がサーチできるパス (include_path)に置くか、インストールしたディレクトリを php.iniinclude_path に追加すると良いでしょう。 ここでは、include_path = ".:/usr/local/lib/php" となっているとして、/usr/local/lib/php/PHPlot にライブラリをインストール(コピー)します。

    # bunzip2 phplot-5.0rc1.tar.bz2
    # tar xf phplot-5.0rc1.tar
    # cd phplot
    # mkdir /usr/local/lib/php/PHPlot
    # cp *.php /usr/local/lib/php/PHPlot/
    # chmod 644 /usr/local/lib/php/PHPlot/*.php

これで設定は完了です。簡単な棒グラフを作ってみましょう。以下のプログラムを適当なファイル名で Web サーバーのDocumentRoot下に置き、ブラウザーから実行すると棒グラフが表示されます。

<?php
// ライブラリの読み込み
require_once('PHPlot/phplot.php');
 
// データの設定
$data = array(
array('1980', 20, 60, 45), array('1985', '', 40, 20), array('1990', 10, 55, 10), array('1995', 30, 65, 20), array('2000', 50, 50, 40), array('2005', 70, 45, 60), ); // グラフオブジェクトの生成 $graph = new PHPlot(450,280); $graph->SetDataType("text-data"); $graph->SetDataValues($data); $graph->SetXTitle("Year"); $graph->SetYTitle("Output"); $graph->SetYTickIncrement(10); $graph->SetPlotType("bars"); $graph->SetXLabelAngle(0); $graph->SetLegend(array("Japan", "USA", "EC")); $graph->SetNewPlotAreaPixels(40,100,400,240); $graph->SetPlotAreaWorld(0,0,7,80); // グラフの表示 $graph->DrawGraph(); ?>

棒グラフ

* Webページに組み込む場合の注意

グラフを出力するプログラムは、GIF, JPEG といった画像を出力します。そのままでは、Webページに画像を貼り付けられないので <img> タグを使用します。グラフを出力するプログラムが graph.php という名前だったとすると、<img src="graph.php" alt="graph"> のように <img> タグにプログラムを記述します。しかし、<img> タグで指定しているので、エラーの際はメッセージを出力して終了するのではなくエラー画像ファイルを用意しておき readfile, fpassthru 関数で出力するとよいでしょう。

<?php
// クラスの読み込みなど
require_once("JpGraph/jpgraph.php");
require_once("...");
 
define("IMG_NODATA",    "/.../images/nodata.gif");
 
// データの設定
$data = <データの取得>
 
if (データが取得できた) {
    // グラフを作成
    $graph = new Graph(500,400,"auto");
    ...
    // グラフを出力
    $graph->Stroke();
} else {
    // 用意しておいたエラー画像を出力
    $fp = fopen(IMG_NODATA, "r");
    fpassthru($fp);
    fclose($fp);
}
?>

ここで fopen でエラーだった場合どうすればよいのかということになる。そこまで信頼のおけない環境の場合、nodata.gif を base64 でエンコードしたデータを保持しておきエラーの場合にはデコードして header("Content-type: image/gif") としてプリントするといった方法をとるとよい。これならファイルをオープンするなどの処理がいらないので確実にエラー画像を出力できます(実際にJpGraph はこの方法でエラー画像を出力しています)。