[PHP]円グラフを表示する(GD)

piegraph

円グラフを PHP で作るには GD に含まれる imagefilledarc() を使うのが便利です。
この関数は塗りつぶした楕円弧を描くためのものです

<?php
//値
$values = array(30, 40, 60, 80, 20);

//グラフに使う色
$colorset = array(
	'ff3b3b', 'bc3bff', '44aeff', 'aeff3b', 'ffa53b'
);

$width	 = 240;
$height	 = 240;

$cx = round( $width / 2 );
$cy = round( $height / 2 );

$image = imagecreatetruecolor($width, $height);

//背景
$bg		 = imagecolorallocate( $image, 255, 255, 255 );
imagefill($image, 0, 0, $bg);

list($red, $green, $blue) = parse_color($colorset[0]);

rsort($values);
$scale = 360 / array_sum($values);
$count = count($values);

$start = -90;
$end = $start;

foreach($values as $key => $value){
	list($red, $green, $blue) = parse_color( current($colorset) );
	$start = $end;
	$end = ($key === $count - 1) ? 270 : $end = $value * $scale + $start;
	$color = imagecolorallocate($image, $red, $green, $blue);
	imagefilledarc($image, $cx, $cy, $width, $height, $start, $end, $color, IMG_ARC_PIE);
	$res = next($colorset);
	if($res === false) reset($colorset);
}

// 画像を出力します
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);

function parse_color($rgb){
	$res = str_split($rgb, 2);
	$red	 = intval($res[0], 16);
	$green	 = intval($res[1], 16);
	$blue	 = intval($res[2], 16);
	return array( $red, $green, $blue );
}

配列の数値を大きいものから順に並び替え、360 度で表せるように倍率を調整しています。
丸め誤差によりぴったりと円が閉じないことがあるので最後の値の時は確実に閉じるように処理を加えてあります。

この関数の 0 度は 3 時方向からスタートするので、12 時方向からスタートさせるために -90 度させています。

グラフに使う色は 16 進数で指定できるようにしました。直接 RGB の数値をそれぞれ入力させてもいいのですが馴染みやすいのでこの表示を使っています。
カラーセットで用意した色数よりも多い値が与えられても、繰り返し使用するので色が不足することはありませんが、数によっては開始の色と最後の値の色が同じになってしまうので、値が奇数個の時と偶数個の時でカラーセットの数を調整する仕組みをつけたほうがいいと思います。

[PHP]複数の画像をランダムに敷き詰めて一枚の画像に合成

random

フォルダに入った大量の写真をランダムなタイル状に並べて一枚の画像にしてみました。

画像をタイル一枚の最低サイズを満たすようにリサイズし、座標を shuffle でランダムにしています。
全種類並べ終えたらもう一度シャッフルして並べているので、画像のバリエーションが少なくても
すべての領域を埋め尽くすことができます。ちなみに例では25種類使っています。

<?php
//画像全体のサイズ
$width = 600;
$height = 600;

//タイル一枚の最低サイズ
$block_size = 100;

//画像ディレクトリ
$dir = "image/";

$list = scandir($dir);
$images = array();

foreach($list as $value){
	if(!is_file ($dir . $value)) continue;
	$images[] = load_image( $dir . $value, $block_size );
}

$max_x = ceil($width / $block_size);
$max_y = ceil($height / $block_size);

shuffle($images);

$x_range = range(0, $max_x);
$y_range = range(0, $max_y);

shuffle($x_range);
shuffle($y_range);

$points = array();

foreach($x_range as $x){
	foreach($y_range as $y){
		$points[] = array("x" => $x, "y" => $y);
	}
}

$canvas = imagecreatetruecolor($width, $height);

foreach($points as $point){
	$x = $point['x'];
	$y = $point['y'];
		$current = current($images);
		imagecopy(
			$canvas, $current['resource'],
			$x * $block_size - ( round($current['width'] / 2) ),
			$y * $block_size - ( round($current['height'] / 2) ), 
			0, 0, $current['width'], $current['height']
		);
		$res = next($images);
		if($res === false) shuffle($images);
}


header("Content-type:image/jpeg");
imagejpeg($canvas, null, 80);
imagedestroy($canvas);

foreach($images as &$image){
	imagedestroy($image['resource']);
}

exit;

function load_image($filepath, $block_size){
	$checkimg = getimagesize($filepath);
	$width = $checkimg[0];
	$height = $checkimg[1];
 
	if($checkimg['mime'] == "image/jpeg" || $checkimg['mime'] == "image/pjpeg"){
		$extension = "jpg";
	} else if ($checkimg['mime'] == "image/gif"){
		$extension = "gif";
	} else if ($checkimg['mime'] == "image/png" || $checkimg['mime'] == "image/x-png"){
		$extension = "png";
	} else {
		exit;
	}
 
	if($extension == 'jpg'){$image = ImageCreateFromJPEG($filepath);}
	if($extension == 'gif'){$image = ImageCreateFromGIF($filepath);}
	if($extension == 'png'){$image = ImageCreateFromPNG($filepath);}
	 
	
	$scale = $block_size / min($width, $height);
	$thumb_width  = $width * $scale;
	$thumb_height = $height * $scale;
	
	$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
	imagecopyresampled($thumb, $image, 0, 0, 0, 0, $thumb_width, $thumb_height, $width, $height);
	 
	$info = array();
	$info['resource']	 = $thumb;
	$info['width']		 = $thumb_width;
	$info['height']		 = $thumb_height;
	$info['extension']	 = $extension;
	
	imagedestroy($image);
	
	return $info;
}

写真素材 足成 http://www.ashinari.com/

[PHP]str_replaceで複数置換する際に気をつけること

関数 str_replace() は、検索語句に配列を指定すると、複数の単語を一括で置換することができます。
しかし、この動作には少し癖があるので間違えると予期していない結果になることがあります。

仮に「AB」という文字と、「DC」という文字を全て「D」に置き換えたいときに、
次のようなコードを書いたとします。

<?php
$data = "ABC";
echo str_replace(array("AB", "DC"), "D", $data);
結果: D

期待される結果は「DC」となる予定でしたが、実際の結果は「D」だけになります。
まず「AB」が「D」に置き換えられ、文字列は「DC」になり、「DC」は「D」に置き換えられるので結局「D」だけが残ります。
要するに str_replace で複数の検索語句を指定した場合、最初から順番に置換を実行していくので、全て同時に置換するわけでは無いということです。
この動作は次のように書いた時と同じです。

<?php
$data = "ABC";
$data = str_replace("AB", "D", $data);
$data = str_replace("DC", "D", $data);
echo $data;
結果: D

元々の文字列には「DC」という単語はないにもかかわらず、最初の置換が実行された結果「DC」という単語ができてしまい、欲しい結果が得られません。
それを回避するには preg_replace を使うのが簡単です。

<?php
$data = "ABC";
echo preg_replace("/AB|DC/", "D", $data);
結果: DC