[PHP]ひらがな・カタカナをローマ字に変換する

カタカナやひらがなをローマ字に変換するプログラムを作ってみました。
結構力技ですのでもう少し改良ができると思います。

<?php
mb_internal_encoding('utf-8');
$kana2romaji = new Kana2Romaji;

$str = "これは、ローマじへんかんのじっけんです";

$result = $kana2romaji->convert($str);
header("Content-type: text/html;charset=utf8");

echo $result;

class Kana2Romaji{
	function convert($str)
	{
		$str = mb_convert_kana($str, 'cHV', 'utf-8');

		$kana = array(
			'きゃ', 'きぃ', 'きゅ', 'きぇ', 'きょ',
			'ぎゃ', 'ぎぃ', 'ぎゅ', 'ぎぇ', 'ぎょ',
			'くぁ', 'くぃ', 'くぅ', 'くぇ', 'くぉ',
			'ぐぁ', 'ぐぃ', 'ぐぅ', 'ぐぇ', 'ぐぉ',
			'しゃ', 'しぃ', 'しゅ', 'しぇ', 'しょ',
			'じゃ', 'じぃ', 'じゅ', 'じぇ', 'じょ',
			'ちゃ', 'ちぃ', 'ちゅ', 'ちぇ', 'ちょ',
			'ぢゃ', 'ぢぃ', 'ぢゅ', 'ぢぇ', 'ぢょ',
			'つぁ', 'つぃ', 'つぇ', 'つぉ',
			'てゃ', 'てぃ', 'てゅ', 'てぇ', 'てょ',
			'でゃ', 'でぃ', 'でぅ', 'でぇ', 'でょ',
			'とぁ', 'とぃ', 'とぅ', 'とぇ', 'とぉ',
			'にゃ', 'にぃ', 'にゅ', 'にぇ', 'にょ',
			'ヴぁ', 'ヴぃ', 'ヴぇ', 'ヴぉ',
			'ひゃ', 'ひぃ', 'ひゅ', 'ひぇ', 'ひょ',
			'ふぁ', 'ふぃ', 'ふぇ', 'ふぉ',
			'ふゃ', 'ふゅ', 'ふょ',
			'びゃ', 'びぃ', 'びゅ', 'びぇ', 'びょ',
			'ヴゃ', 'ヴぃ', 'ヴゅ', 'ヴぇ', 'ヴょ',	
			'ぴゃ', 'ぴぃ', 'ぴゅ', 'ぴぇ', 'ぴょ',
			'みゃ', 'みぃ', 'みゅ', 'みぇ', 'みょ',	
			'りゃ', 'りぃ', 'りゅ', 'りぇ', 'りょ',
			'うぃ', 'うぇ', 'いぇ'
		);
		
		$romaji	 = array(
			'kya', 'kyi', 'kyu', 'kye', 'kyo',
			'gya', 'gyi', 'gyu', 'gye', 'gyo',
			'qwa', 'qwi', 'qwu', 'qwe', 'qwo',
			'gwa', 'gwi', 'gwu', 'gwe', 'gwo',
			'sya', 'syi', 'syu', 'sye', 'syo',
			'ja', 'jyi', 'ju', 'je', 'jo',
			'cha', 'cyi', 'chu', 'che', 'cho',
			'dya', 'dyi', 'dyu', 'dye', 'dyo',
			'tsa', 'tsi', 'tse', 'tso',
			'tha', 'ti', 'thu', 'the', 'tho',
			'dha', 'di', 'dhu', 'dhe', 'dho',
			'twa', 'twi', 'twu', 'twe', 'two',
			'nya', 'nyi', 'nyu', 'nye', 'nyo',
			'va', 'vi', 've', 'vo',
			'hya', 'hyi', 'hyu', 'hye', 'hyo',
			'fa', 'fi', 'fe', 'fo',
			'fya', 'fyu', 'fyo',
			'bya', 'byi', 'byu', 'bye', 'byo',
			'vya', 'vyi', 'vyu', 'vye', 'vyo',
			'pya', 'pyi', 'pyu', 'pye', 'pyo',
			'mya', 'myi', 'myu', 'mye', 'myo',
			'rya', 'ryi', 'ryu', 'rye', 'ryo',
			'wi', 'we', 'ye'
		);
		
		$str = $this->kana_replace($str, $kana, $romaji);

		$kana = array(
			'あ', 'い', 'う', 'え', 'お',
			'か', 'き', 'く', 'け', 'こ',
			'さ', 'し', 'す', 'せ', 'そ',
			'た', 'ち', 'つ', 'て', 'と',
			'な', 'に', 'ぬ', 'ね', 'の',
			'は', 'ひ', 'ふ', 'へ', 'ほ',
			'ま', 'み', 'む', 'め', 'も',
			'や', 'ゆ', 'よ',
			'ら', 'り', 'る', 'れ', 'ろ',
			'わ', 'ゐ', 'ゑ', 'を', 'ん',
			'が', 'ぎ', 'ぐ', 'げ', 'ご',
			'ざ', 'じ', 'ず', 'ぜ', 'ぞ',
			'だ', 'ぢ', 'づ', 'で', 'ど',
			'ば', 'び', 'ぶ', 'べ', 'ぼ',
			'ぱ', 'ぴ', 'ぷ', 'ぺ', 'ぽ'
		);
		
		$romaji = array(
			'a', 'i', 'u', 'e', 'o',
			'ka', 'ki', 'ku', 'ke', 'ko',
			'sa', 'shi', 'su', 'se', 'so',
			'ta', 'chi', 'tsu', 'te', 'to',
			'na', 'ni', 'nu', 'ne', 'no',
			'ha', 'hi', 'fu', 'he', 'ho',
			'ma', 'mi', 'mu', 'me', 'mo',
			'ya', 'yu', 'yo',
			'ra', 'ri', 'ru', 're', 'ro',
			'wa', 'wyi', 'wye', 'wo', 'n',
			'ga', 'gi', 'gu', 'ge', 'go',
			'za', 'ji', 'zu', 'ze', 'zo',
			'da', 'ji', 'du', 'de', 'do',
			'ba', 'bi', 'bu', 'be', 'bo',
			'pa', 'pi', 'pu', 'pe', 'po'
		);
		
		$str = $this->kana_replace($str, $kana, $romaji);
		
		$str = preg_replace('/(っ$|っ[^a-z])/u', "xtu", $str);
		$res = preg_match_all('/(っ)(.)/u', $str, $matches);
		if(!empty($res)){
			for($i=0;isset($matches[0][$i]);$i++){
				if($matches[0][$i] == 'っc') $matches[2][$i] = 't';
				$str = preg_replace('/' . $matches[1][$i] . '/u', $matches[2][$i], $str, 1);
			}
		}
		
		$kana = array(
			'ぁ', 'ぃ', 'ぅ', 'ぇ', 'ぉ',
			'ヵ', 'ヶ', 'っ', 'ゃ', 'ゅ', 'ょ', 'ゎ', '、', '。', ' '
		);
		
		$romaji = array(
			'a', 'i', 'u', 'e', 'o',
			'ka', 'ke', 'xtu', 'xya', 'xyu', 'xyo', 'xwa', ', ', '.', ' '
		);
		$str = $this->kana_replace($str, $kana, $romaji);
		
		$str = preg_replace('/^ー|[^a-z]ー/u', '', $str);
		$res = preg_match_all('/(.)(ー)/u', $str, $matches);

		if($res){
			for($i=0;isset($matches[0][$i]);$i++){
				if( $matches[1][$i] == "a" ){ $replace = 'â'; }
				else if( $matches[1][$i] == "i" ){ $replace = 'î'; }
				else if( $matches[1][$i] == "u" ){ $replace = 'û'; }
				else if( $matches[1][$i] == "e" ){ $replace = 'ê'; }
				else if( $matches[1][$i] == "o" ){ $replace = 'ô'; }
				else { $replace = ""; }
				
				$str = preg_replace('/' . $matches[0][$i] . '/u', $replace, $str, 1);
			}
		}
		
		return $str;
	}

	function kana_replace($str, $kana, $romaji)
	{
		$patterns = array();
		foreach($kana as $value){
			$patterns[] = '/' . $value . '/';
		}
		
		$str = preg_replace($patterns, $romaji, $str);
		return $str;
	}
}

結果:

koreha, rômajihenkannojikkendesu

今回「高速道路」などは「kosokudoro」とせずに「kousokudouro」と変換してあります。
ローマ字の表記は個人の判断によるところが多く、ここでは「じ」を「ji」、「ち」を「chi」にするなど、一部原則から外れています。
あくまで慣用的な書き方なので重要な場面では使用しないで下さい。

基本的な文字はカバーしているものの、「ぶゎ」「いぃ」など未対応のものは「buxwa」「ixi」のようになります。
必要に応じて「bwa」「yi」などを書き足してください。

人名などで、苗字と名前の頭文字を大文字にしたい場合は、標準関数 ucwords() を使えば簡単に出来ます。

[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/