2010年1月30日土曜日

やっと色相環、完成。

望みがやっと達成されました。
綺麗に色相環が実現できました。
imagefilledarcとimagefilledellipseの両方を使って実現。
ありがたや。。。

<?php
    $img = imagecreatetruecolor(400, 400);
    $bg=imagecolorallocate($img,0,0,0);
    $r2=150;
    $s=1;$v=1;

function toH($a){
    $result=round((round($a,3)*255));
    return $result;
}
for($h=0;$h<360;$h++){
    $y0=$r2*(sin(deg2rad($h)));
    $x0=$r2*(cos(deg2rad($h)));
    $y=$y0+200;
    $x=$x0+200;
    
$hi = ( $h / 60 ) % 6;
$f = ( $h / 60 ) - $hi;
$p = $v * ( 1 - $s );
$q = $v * ( 1 - $f * $s );
$t = $v * ( 1 - ( 1 - $f ) * $s );

if($hi == 0){$r = $v;$g = $t;$b = $p;}
elseif($hi == 1){$r = $q;$g = $v;$b = $p;}
elseif($hi == 2){$r = $p;$g = $v;$b = $t;}
elseif($hi == 3){$r = $p;$g = $q;$b = $v;}
elseif($hi == 4){$r = $t;$g = $p;$b = $v;}
elseif($hi == 5){$r = $v;$g = $p;$b = $q;}
//else{$r = $v;$g = $v;$b = $v;}
$col=imagecolorallocate($img,toH($r),toH($g),toH($b));    
$col0=imagecolorallocate($img,0,0,0);    
imagefilledarc($img,200,200,300,300,$h,$h+1,$col
    ,IMG_ARC_PIE);
imagefilledellipse($img,200,200,200,200,$col0);

}
    header("Content-Type: image/png");
    imagepng($img);

?>

■今後の課題としては、色相環はできたので、
明度を下げてだんだん中心に向かってフェードさせる、
といったことを実現したいな、と。

IMG_ARC_NOFILLというstyle指定があって、淵だけが描かれるので、
それをつかって、中心に向かってだんだん明度Vを下げていこうかな、と。

外に向かっても少しずつ下げていくと綺麗かな。。

imagefilledarc()にて、色相環。

imagefilledarc($img,200,200,300,300,$h,$h+1,$col,IMG_ARC_PIE);
ということで、弧をつくってやると、また綺麗になりました。

第2、第3引数は、円の中心x.y座標。
第4、第5引数は、幅と高さ。
第6、第7引数は、開始角と終了角。
第8は、色。
第9は、どのような法則で描画させるかのオプションでした。
該当PHPマニュアルページ)

色相環、完成!

とうとう色相環が出来ました!(^^)!
ずっとエラーが出ていて、悩みました。
$rという変数を半径にしていたのですが、
$rはredの値を格納する変数にもしていたので、
バッティングしていたのに気づけませんでした。。

ともあれ、とりあえず完成です。

でも、filledellipseで360個の円をHSVの値を変えて表現しているので、
赤い円が最後にオレンジを食ってます。

これを、弧で実現すればたぶん行けると思うんですが、とりあえず今日は終了。




<?php
    $img = imagecreatetruecolor(400, 400);
    $bg=imagecolorallocate($img,0,0,0);
    $r2=150;
    $s=1;$v=1;

function toH($a){
    $result=round((round($a,3)*255));
    return $result;
}
for($h=0;$h<360;$h++){
    $y0=$r2*(sin(deg2rad($h)));
    $x0=$r2*(cos(deg2rad($h)));
    $y=$y0+200;
    $x=$x0+200;
    
$hi = ( $h / 60 ) % 6;
$f = ( $h / 60 ) - $hi;
$p = $v * ( 1 - $s );
$q = $v * ( 1 - $f * $s );
$t = $v * ( 1 - ( 1 - $f ) * $s );

if($hi == 0){$r = $v;$g = $t;$b = $p;}
elseif($hi == 1){$r = $q;$g = $v;$b = $p;}
elseif($hi == 2){$r = $p;$g = $v;$b = $t;}
elseif($hi == 3){$r = $p;$g = $q;$b = $v;}
elseif($hi == 4){$r = $t;$g = $p;$b = $v;}
elseif($hi == 5){$r = $v;$g = $p;$b = $q;}
//else{$r = $v;$g = $v;$b = $v;}
$col=imagecolorallocate($img,toH($r),toH($g),toH($b));    
imagefilledellipse($img, $x, $y, 50, 50, $col);
}
    header("Content-Type: image/png");
    imagepng($img);

?>

2010年1月29日金曜日

HSVからRGBに変換した値の表示。

一応、H=0~359の色相におけるRGBの値を256階層でテーブル表示させるコードが出来ました。
ずらっと長いテーブルが生成されます(^^;。

これを次は、GDででも色付けしてPNG化です。
楽しみなり。

その後、sin(),cos()あたりで色相環の完成か。
楽しみっす。。。
<?php

echo "<table cellpadding='1' border='1'>";
echo "<tr><th>H</th><th>R</th><th>G</th><th>B</th></tr>";
for($h=0;$h<360;$h++){
$s=1;$v=1;
$hi = ( $h / 60 ) % 6;
$f = ( $h / 60 ) - $hi;
$p = $v * ( 1 - $s );
$q = $v * ( 1 - $f * $s );
$t = $v * ( 1 - ( 1 - $f ) * $s );

if($hi == 0){
$r = $v;$g = $t;$b = $p;
}
elseif($hi == 1){
$r = $q;$g = $v;$b = $p;
}
elseif($hi == 2){
$r = $p;$g = $v;$b = $t;
}
elseif($hi == 3){
$r = $p;$g = $q;$b = $v;
}
elseif($hi == 4){
$r = $t;$g = $p;$b = $v;
}
elseif($hi == 5){
$r = $v;$g = $p;$b = $q;
}
else{
$r = $v;$g = $v;$b = $v;
}
echo "<tr><th>".$h."</th><td>".toHex($r)
."</td><td>",toHex($g),"</td><td>"
.toHex($b)."</td></td>";
}
echo "</table>";
function toHex($a){
    $result=round((round($a,3)*255));
    return $result;
}
?>
参考にさせていただいたページ。
http://movingahead.seesaa.net/article/139081151.html
感謝。

■後日に書いた追記です。
各度と円の6区分とRGB値と、x、y座標などを一覧表示させたテーブルページへのリンクをはっておきます。
 http://labo.web-do.com/php/colors/hsv_show.php
ちょっとRGBの背景色がいけてないんですが、眺めていると色々勉強になります。。

HSV色空間についてのメモ

最近、色相環をPHPで実現したいと思って、時々「どうしたら実現できるかなあ。。360度の6つの領域の色の変化を、各6領域でRGBをそれぞれ条件に沿って変化させるか。」などと考えていました。

が、ふと「HSV色空間」のことを知り、どうもその方向で実現できそうだとわかりました。
何事にも、先達のあらまほしきことなり。
やはり先賢は賢いなあ、と。


http://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93
wikipediaの「HSV色空間」へのリンク。
http://movingahead.seesaa.net/article/139081151.html
PHPで実現されたようであるかたのページリンク。
http://ja.wikipedia.org/wiki/%E5%90%88%E5%90%8C%E5%BC%8F
360を60で割って、その剰余を求める、ということが6領域をスマートに割り出す鍵であることが分かり、「mod」について勉強した際のwikipediaリンク。

少し理解できてきたので(まだかなり怪しいですが。。)、
GDでも使って色相環を実現したいな、と。

なんか、ずっと色相環を実現したかったんですよね~
憧れのような(笑)

がんばろっと。

(色々やることあるのに、何をやってるんだか、という突っ込みを自分に入れつつ。。)

2010年1月22日金曜日

やっと円が描けました。。

PHP+GDを使って円を描こうと思い、やっと描けました。
まだ、味も素っ気もねえですが。。(^^;
サインとコサインを使っての演習、ということで。

これから進化してゆきます。時計の文字盤とか、色をとりどりにするとか。RGBをいろいろ使って。。。



<?php

header('Content-type: image/png');

$image=imagecreate(400,400);
imagecolorallocate($image,200,200,200);
$color=imagecolorallocate($image,0,0,0);
for($i=0;$i<361;$i++){
        imagesetpixel($image,(200+(100*round(cos(deg2rad($i)),3))),(200+(100*round(sin(deg2rad($i)),3))),$color);
}
imagepng($image);
imagedestroy($image);

sinとcosを表にしてみました。(数学学習のため。。)

sinとcosの関係を理解したくて、ちょっとコードを書いてみました。
高校時代、意味不明でしたが、コードを書いているとわかってきました。

僕が関わる子供たちと、sin,cosの話をして、「どうやったら、わかるようになるかなあ。。」と考えていたので、こういうのはいいかな、と。
echo "<table border='1' cellspacing='0'>";
echo "<thead bgcolor='orange'><tr><th>角度</th><td>cos</td><td>sin</td></tr></thead>";
for($i=0;$i<361;$i=$i+30){
    echo "<tr><th align='right'>{$i}</th><td>".round(cos(deg2rad($i)),3)."</td><td>".round(sin(deg2rad($i)),3)."</td></tr>";
}
echo "</table>";

で、表示結果はこんな感じです。(round関数で、小数点以下3桁まで表示)




数学を簡単なプログラミングを通して学ぶと、一番効果的なんじゃないかと思うこのごろです。。

そのために一番子供たちに簡単に触れられるプログラミング言語はなんでしょうね。。。PHPは手軽ですが、ローカルに環境を作るのが難しいですし。。
探してみませんと。。

ラジアン値のこと、やっと理解。。

ラジアン値ってなんだろう?と思い、
角度からラジアン値を算出する関数deg2rad()を使って調べて、やっと理解しました。

echo deg2rad(45)."<br />";
echo deg2rad(180)."<br />";
echo deg2rad(270)."<br />";
の値はそれぞれ、
0.785398163397
3.14159265359
4.71238898038
です。

要するに「180度」が円周率の値なんですね。
半径の長さに等しい弧に対する中心角の大きさを一ラジアン
という文を見つけましたが、そういうことなんですね。
なるほど。。

昔ならったような気もしますが、完全に失念していました。

でも、これを使えばプログラムを使って円周上に点を置いていくような座標の計算がとても楽になる、とわかって、俄然理解への意欲がわきました。

必要こそ、理解の母ですね。

M_PI(円周率の定数)、便利。

PHPで(他の言語でものようですが)、円周率がM_PIという定数で定義されていて、便利でした。

echo M_PI."<br />";
echo (M_PI/8)."<br />";
echo M_PI_4."<br />";
echo M_PI_2;
の結果は、
3.14159265359
0.392699081699
0.785398163397
1.57079632679
みたいな感じで。

ありがたや。。

2010年1月20日水曜日

正規表現でかっこ()に囲まれた部分を全部削除したかった(解決)

正規表現で、ある文章からかっこ()に囲まれた部分を全部なくしたい、と思い、色々試してやっと実現できたので、メモです。
とにかく何でもいい文字の連続を表現するには、「.*」(ピリオドアスタリスク)でいけるんですね。
preg_replace("/(\(|().*(\)|))/","変えたよ",$str)
要するに、かっこの半角と全角の両方を|で認識させるようにして、半角かっこはもちろんバックスラッシュでエスケープして、それを半角かっこでくくってグループ化し、そのあとに閉じかっこも開きかっこと同様にグループ化して指定して、その間に.*を入れてカッコ内にどんな文字があってもOKになった、と。


やや時間がかかりました。。解決して嬉しいです(笑)
参考になったページはここ。とてもよく分かりましたm(_ _)m「サルにもわかる正規表現入門」。
http://www.mnet.ne.jp/~nakama/

::::::::::::::::::::::::::::::::::::::::::

■追記:この方法に弱点を発見しました。。
いくつもの()に囲まれた部分が、同一文内にあると、一番最初の開きかっこから、一番最後の閉じかっこまでがくくられて、ひとつと認識されてしまい、途中の文章が全部ずっぱり消えてしまいます。。
.*は可能な限り最後までつなげられる、という法則があるからですね。。

さて、困りました。どうしようかな。。

■追記2:一応解決です。応急策。
preg_replace("/(\(|().{5,30}(\)|))/","OK",$str);
みたいに、間にある文字数をだいたい指定してやれば、まあまあいけそうです。ちょっとアナログちっく。

■追記3:指定した文字数がマルチバイトの文字数じゃないので、どうしよう、とおもったら、pregはuというutf-8オプションがあったので、uを追加してやると日本語を一文字として認識してくれたようです。ありがたや。。
preg_replace("/(\(|().{5,10}(\)|))/u","OK",$str);

2010年1月18日月曜日

pos()という関数名はすでにあった。。

自前の関数をつくってpos()と名付けたら、既に予約されてました。
こういうシンプルなのは避けないとだめですね。

遥かなる脱初心者の道。。

関数の引数にあてる変数名は同じの方がいい様子。

自前の関数を作ったらエラーが出るので悩みました。
 syntax error, unexpected '$'

function pretrim($pretrim,$keyword){
中略
}
みたいなのをつくって、

pretrim($answer,$word)として使おうとしていたのが駄目だったようです。

function pretrim($answer,$word){}として引数を同じ変数名にしてやるとOKでした。
よかった。

2010年1月16日土曜日

printf()とsprintf()の違いがわかりました。。

printf()とsprintf()の違いがよくわかりませんでした。が、やっとわかりました。

printf()は出力して、sprintf()は値を返す(変数に代入できる)、ということなんですね。
printf()の中に引数を入れて変数に代入してみたり、
sprintf()でecho()のように出力させようとしてみたりして、うまくいかず、
やっと意味が分かりました。。

mb_strposやmb_strlenで文字数がおかしかった(解決)

mb_strlen()などでマルチバイトの文字数がちゃんと計算されないので悩みました。
"utf-8"を引数で設定したらOKでしたが、面倒です。。

phpinfoで調べたら、php.iniで設定しているはずなのに、 mb関連がno-valueとか書いてありました。。

原因は、xamppの1.6.8を使っていて、php/php.iniを変更していたのがまずかったようで、apache/bin/php.iniの方を設定すれば直りました。。。

1.7.1からphpディレクトリ配下のphp.iniが生きるようになってるんですね。。。

2010年1月14日木曜日

session学習開始

sessionの学習を開始しました。

POSTとGETでは、あるページからあるページへのデータの受け渡しだけでしたが、
SESSIONを使うと、ブラウザを開いている間ずっと(設定すれば閉じたのちも)、データを保持して渡してゆける、というのはとても便利。

ありがたい仕組みです。。。

2010年1月7日木曜日

RGBテーブルその二

RGBのテーブルをまたつくりました。
サイトのバックグラウンドを作ろうとしています。

超コードがひよっこですが、ご照覧を。。。
(知り合いの方からsprintfを使えば、%xで16進数としてとれる、ということを教わりました。その方が断然簡単ですね!)



<html><head><style type="text/css"><!--table {font-size:0.8em;}-->
</style><body >
<?php
function deg2sixteen($deg){//10~15までをa~fに変換
    switch($deg){case 10:$deg="a";break;case 11:$deg="b";break;case 12:$deg="c";break;case 13:$deg="d";break;case 14:$deg="e";break;case 15:$deg="f";break;}//i switch end
    return $deg;}
echo "<table border='0' cellspacing='0' cellpadding='0'><tr>";//sell-paddingの値を0にする必要があった。
for($n=0;$n<4;$n++){//RGBそれぞれ2色ずつのテーブルをつくるループ
    echo"<td><table border='0' cellspacing='0' cellpadding='0'>";
        for($y=0;$y<16;$y++){//第一のカラーを0~15まで推移させる。
        echo"<tr>\n";
        if($n<2){$y2=15-$y;$yc=deg2sixteen($y2);}//この二行で上下を逆に。
        else{$yc=deg2sixteen($y);}
            for($x=0;$x<16;$x++){//第二のカラーを0~15まで推移させる。
                if($n%2==0){$xa=15-$x;$xc=deg2sixteen($xa);}//この二行で左右を逆に。
                else{$xc=deg2sixteen($x);}
                $y2=$yc."0";$x2=$xc."0";$z2="00";//ここで二ケタに変換
                switch($n){//ここでRGBから二色を選ぶ振り分け。
                    case 0:echo"<td bgcolor='#".$z2.$y2.$x2."'>#0".$yc.$xc."</td>\n";break;
                    case 1:echo"<td bgcolor='#".$x2.$y2.$z2."'>#0".$yc.$xc."</td>\n";break;
                    case 2:echo"<td bgcolor='#".$y2.$z2.$x2."'>#".$yc."0".$xc."</td>\n";break;
                    case 3:echo"<td bgcolor='#".$y2.$z2.$x2."'>#".$yc."0".$xc."</td>\n";break;
                }//$n switch end
            }//j for end
        echo"</tr>\n";
        }//i for end
    echo"</table></td>";
    if($n%2==1){echo"</tr><tr>";}
}//for n end
echo"</tr></table>";
echo "<table border='0' cellspacing='0' cellpadding='0'><tr>";//sell-paddingの値を0にする必要があった。
for($n=0;$n<4;$n++){//RGBそれぞれ2色ずつのテーブルをつくるループ
    echo"<td><table border='0' cellspacing='0' cellpadding='0'>";
        for($y=0;$y<16;$y++){//第一のカラーを0~15まで推移させる。
        echo"<tr>\n";
        if($n<2){$y2=15-$y;$yc=deg2sixteen($y2);}//この二行で上下を逆に。
        else{$yc=deg2sixteen($y);}
            for($x=0;$x<16;$x++){//第二のカラーを0~15まで推移させる。
                if($n%2==0){$xa=15-$x;$xc=deg2sixteen($xa);}//この二行で左右を逆に。
                else{$xc=deg2sixteen($x);}
                $y2=$yc."0";$x2=$xc."0";$z2="00";//ここで二ケタに変換
                switch($n){//ここでRGBから二色を選ぶ振り分け。
                    case 0:echo"<td bgcolor='#".$y2.$z2.$x2."'>#".$yc."0".$xc."</td>\n";break;
                    case 1:echo"<td bgcolor='#".$y2.$z2.$x2."'>#".$yc."0".$xc."</td>\n";break;
                    case 2:echo"<td bgcolor='#".$z2.$y2.$x2."'>#0".$yc.$xc."</td>\n";break;
                    case 3:echo"<td bgcolor='#".$z2.$y2.$x2."'>#0".$yc.$xc."</td>\n";break;
                }//$n switch end
            }//j for end
        echo"</tr>\n";
        }//i for end
    echo"</table></td>";
    if($n%2==1){echo"</tr><tr>";}
}//for n end
echo"</tr></table>";
?>
</body>
</html>

2010年1月6日水曜日

mb_convert_kana()で変換できなかった。("utf-8"が必要だった)

http://life1204.blogspot.com/2008/07/mbconvertkana.html

mb_convert_kana()で全角半角が変換できず悩んでいたら、上記のサイトを見つけ、無事解決。

第三引数に"utf-8"を入れてやればOKなんですね。
$str=mb_convert_kana($str,"an","utf-8");
みたいに。

全角文字、数字を、これで無事変換できるのはありがたい。。

2010年1月4日月曜日

RGBの色相をテーブル表示

RGBの色相階調を16進数表記させながらテーブルで表示させるプログラムを書いてみました。

最初、<td>のbgcolorの値に、”#F00”といった三桁の省略形で書いていたので、黒い背景になってしまい、しばし悩みました。6桁でちゃんと書かないといけないのですね。(ですので、画像にある3ケタ表示は簡略表示しているだけですのであしからず。)

なんか、簡単なプログラムでとても美しいものになったので、ちょっと嬉しくなって投稿してみました。
初心者なコードで笑われるかもしれませんが、一応コードもアップしておきます。

自己ログも兼ねまして。。

<?php

function deg2sixteen($deg){//10~15までをa~fに変換
    switch($deg){
        case 10:$deg="a";break;
        case 11:$deg="b";break;
        case 12:$deg="c";break;
        case 13:$deg="d";break;
        case 14:$deg="e";break;
        case 15:$deg="f";break;
    }//i switch end
    return $deg;
}
for($n=0;$n<3;$n++){//RGBそれぞれに色ずつのテーブルをつくるループ
switch($n){
    case 0:echo"赤Rと緑Gの混色図";break;
    case 1:echo"緑Gと青Bの混色図";break;
    case 2:echo"赤Rと青Bの混色図";break;
}

echo "<table border='0' cellspacing='0'>";
echo "<tr>";
for($i=0;$i<16;$i++){//第一のカラーを0~15まで推移させる。
    $ic=$i;
    $ic=deg2sixteen($ic);
    echo"<tr>";
    for($j=0;$j<16;$j++){//第二のカラーを0~15まで推移させる。
        $jc=$j;
        $jc=deg2sixteen($jc);
        $ic2=$ic.$ic;$jc2=$jc.$jc;$zero="00";//ここで二ケタに変換
switch($n){//ここでRGBから二色を選ぶ振り分け。
    case 0:echo"<td bgcolor='#".$ic2.$jc2.$zero."'>#".$ic.$jc."0</td>";break;
    case 1:echo"<td bgcolor='#".$zero.$ic2.$jc2."'>#0".$ic.$jc."</td>";break;
    case 2:echo"<td bgcolor='#".$ic2.$zero.$jc2."'>#".$ic."0".$jc."</td>";break;
    }//$n switch end
    }//j for end
    echo"</tr>";
}//i for end
echo"</table><br>";
}//for n end

?> 

■追記:deg2sixteen()という自前の関数を作って、
10~15までの数字をa~fまでの英字に返還させるようにしたのですが、
Fatal error: Can't redeclare already declared function
のエラーが最初出て困りました。
要するに関数を複数回宣言している、ということなので考えてみたら、
for文の中で宣言していました。。(^^;
for文の外で宣言してやると、無事いけました。

ああ、初心者(笑)

SIN,COSの使い道。(GDで円形に図形を配置)

GDを使って、複数の円を、円状に描きだす、ということの必要があって取り組みました。

「どうやったらx座標,y座標を割り当てていけるだろう?」としばし悩み、高校時代に挫折したsin,cosをふと思い出しました。
さっそく調べると、PHPにはsin(),cos()という便利な関数があり、ネットで少々勉強したら、かなり便利なものと判明。
高校時代の挫折は、sin,cosの使い道が分からないことに大きな原因があったんだな、としみじみ。。。
今回、sin,cosでY座標、X座標を取得したい、という理由がはっきりしていたので、

やっとsin,cosの使い道が分かりました(笑)。


色々試して、以下のようなコードで、実験作第一号は無事表示。
ありがたや。。

そういえば、deg2rad()関数が必須でした。数値の角度からラジアン値に変換してくれるすぐれもの。この関数でやっと、30度ずつ描画、といった均等配置が実現しました。ありがたや。。


<?php

    $r=100;
    $img = imagecreate(500, 500);
    $bg=imagecolorallocate($img,0,0,0);

for($i=0;$i<12;$i++){
   $rad=deg2rad($i*30-90);
    $c=$i*20+15;
    $c2=255-$c;
    $y=$r*sin($rad);
    $x=$r*cos($rad);
    $y2=$y+200;
    $x2=$x+200;    
    $col=imagecolorallocate($img, $c2,$c, 0);    
    imagefilledellipse($img, $x2, $y2, 20, 20, $col);
} 

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

?>

GDで複数図形の描画でのつまづき

GDを使って、for文で複数の円を描画させようとしたら、一個しか描画されず悩みました。
理由は簡単でした。    imagepng($img); でPNG画像を排出する部分を、for文の中に入れていたからでした。。(^^;
複数の画像を描画するにしても、描きだすPNGファイルは一枚だけ、ということで、for文に入れ込んではいけませんでした。