[PHP]GDでアンチエイリアスのかかった綺麗な楕円を描く

PHP で正円・楕円を描画する場合、通常は GD の imageellipse() で描くことになるのですが、imageantialias() を使ってもアンチエイリアスがかからないため、ジャギーのあるギザギザした線になってしまいます。

アンチエイリアスのかかった直線を描くアルゴリズムの一つに Xiaolin Wu Line Algorithm というものがあり、そちらを応用する形で楕円を描くという手法を用いるとかなり綺麗な円を描くことができます。

wu_ellipsewu_ellipse2

様々な方法による円の描画を比較した記事 Drawing Antialiased Circles and Ellipses (by Stephan Brumme) を参考に imageellipse() と同じ使い方ができるように関数化してみました。

<?php
function wu_ellipse($image, $cx, $cy, $width, $height, $color){
	$rx = $width / 2;
	$ry = $height / 2;
	$rx2 = $rx * $rx;
	$ry2 = $ry * $ry;
	
	$quarter = round($rx2 / sqrt($rx2 + $ry2));
	for ($x = 0; $x <= $quarter; $x++)
	{
		$y = $ry * sqrt(1 - $x*$x / $rx2);
		$error = $y - floor($y);
		$transparency = round($error * 0x7F);
		$alpha  = $color | ($transparency << 24);
		$alpha2 = $color | ((0x7F - $transparency) << 24);
		plot4points($image, $cx, $cy, $x, floor($y),   $alpha);
		plot4points($image, $cx, $cy, $x, floor($y)+1, $alpha2);
	}
	
	$quarter = round($ry2 / sqrt($rx2 + $ry2));
	for ($y = 0; $y <= $quarter; $y++)
	{
		$x = $rx * sqrt(1 - $y*$y / $ry2);
		$error = $x - floor($x);
		$transparency = round($error * 0x7F);
		$alpha  = $color | ($transparency << 24);
		$alpha2 = $color | ((0x7F - $transparency) << 24);
		plot4points($image, $cx, $cy, floor($x),   $y, $alpha);
		plot4points($image, $cx, $cy, floor($x)+1, $y, $alpha2);
	}
}

function plot4points($image, $cx, $cy, $dx, $dy, $color)
{
	imagesetpixel($image, $cx + $dx, $cy + $dy, $color);
	imagesetpixel($image, $cx - $dx, $cy + $dy, $color);
	imagesetpixel($image, $cx + $dx, $cy - $dy, $color);
	imagesetpixel($image, $cx - $dx, $cy - $dy, $color);
}


$image = imagecreatetruecolor(300, 300);
$color = imagecolorallocate($image, 0x33, 0x33, 0x33);
$bg = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
imagefill ($image, 0, 0, $bg);

$width  = 240;
$height = 240;
$cx = 150;
$cy = 150;

wu_ellipse($image, $cx, $cy, $width, $height, $color);

header("Content-type: image/png");
imagepng($image);

【参考】
Fast, Antialiased Circles and Ellipses from Xiaolin Wu’s concepts
Drawing Antialiased Circles and Ellipses

[PHP]キーワードとなる文字列が何文字目にあるかを全て取得

文章中からキーワードの現れる最初の位置を調べるなら mb_strpos() が使えますが、取得できるのは一つだけなので、同じキーワードが複数回出現している場合でも最初に見つかった一つしか得られません。
そこで、語句が出現する全ての位置を取得して配列の形で返す関数を作ってみました。

<?php
mb_internal_encoding('utf-8');

$needle = 'テスト';
$haystack = 'これはテストです。二箇所目のテストです。三箇所目のテストです';

$result = mb_strpos_all($haystack, $needle);

print_r($result);

function mb_strpos_all($haystack, $needle, $offset=0, $encoding=null, $result=array() ){
	if( empty($encoding) ) $encoding = mb_internal_encoding();
	$pos = mb_strpos($haystack, $needle, $offset, $encoding);
	if($pos !== false){
		$result[] = $pos;
		return mb_strpos_all($haystack, $needle, $pos + 1, $encoding, $result);
	} else {
		return $result;
	}
}
出力結果: 
Array
(
    [0] => 3
    [1] => 14
    [2] => 25
)

キーワードとなる語句は 3 回使われているので結果の配列も 3 つです。数値は何文字目に現れるかを示しており、3 文字目、14 文字目、25 文字目に単語が存在することがわかります。

上記の例では再帰処理を行いましたが単純に下のようにしても同じ結果が得られます。

<?php
mb_internal_encoding('utf-8');

$needle = 'テスト';
$haystack = 'これはテストです。二箇所目のテストです。三箇所目のテストです';

$offset = 0;
$result = array();
while(true){
	$pos = mb_strpos($haystack, $needle, $offset);
	if($pos === false){
		break;
	} else {
		$result[] = $pos;
		$offset = $pos + 1;
	}
}

print_r($result);

[PHP]file_get_contents()でWebページのステータスコードを取得する

HTTP で Web ページの内容を取得するには file_get_contents() で可能ですが、サーバーが 404 などのエラーコードを返しても通常の file_get_contents() は false を返すだけでエラーの内容がわかりません。

そこで、stream_context_create() を使って ignore_errors を true にセットするとエラー時であっても取得することができます。

<?php
$url = 'http://example.com';

$options = array(
	'http' => array('ignore_errors' => true)
);
$context = stream_context_create($options);

$result = @file_get_contents($url, false, $context);

$code = 0;
if($result){
	$pattern='#\AHTTP/\d+\.\d+ (\d+) (.*)\E#';
	preg_match($pattern, $http_response_header[0], $matches);
	if(isset($matches[1])) $code = (int)$matches[1];
}

echo $code;

結果:

200

取得したヘッダーは $http_response_header という配列変数に自動的に格納されます。
上の例では正規表現でレスポンスコードの数字を取り出して出力しています。
URL 自体が誤っていてサーバーに辿りつけない場合は file_get_contents は false を返すので「@」を使って Warning エラーを抑制しています。

参考:
http://php.net/manual/ja/function.file-get-contents.php
http://php.net/manual/ja/function.stream-context-create.php