canvasで色相環
canvasを使って色相環を描いてみた
http://kar.s206.xrea.com/js/colors.html
色の変化のさせかたを自分で考えるのが目的だったのでグラデーションの技は使わず1ピクセルずつ処理してる。
なのでかなり重い処理になってるので注意。
RGB各色が0〜255の256階調なので、半径256ドット、60度(π/3ラジアン)を256分割にした。
関数psetsの引数でrのみの指定がメインとなる色、r*th/255が徐々に混じる色、0が使わない色。
関数nの255-rを生かすと中央が白から始まる円、0(=255-255)にすると中央が黒から始まる円になる。
<html> <head> <title>Colors</title> <script> window.onload = function(){ c = document.getElementsByTagName('canvas')[0].getContext('2d'); for(r=0;r<256;r++) for(th=0;th<256;th+=255/r){ psets(r, -th, r, 0,r*th/255); psets(r, th, r,r*th/255, 0); psets(r, 512-th,r*th/255, r, 0); psets(r, 512+th, 0, r,r*th/255); psets(r,1024-th, 0,r*th/255, r); psets(r,1024+th,r*th/255, 0, r); } } function psets(r,th,rr,gg,bb){ x = 255.5 + r * Math.cos(th * Math.PI / 768); // 256 * 3 = 768 y = 255.5 - r * Math.sin(th * Math.PI / 768); c.strokeStyle = "rgb("+n(rr,r)+","+n(gg,r)+","+n(bb,r)+")"; c.strokeRect(x,y,1,1); c.strokeStyle = "rgb("+n(rr,255)+","+n(gg,255)+","+n(bb,255)+")"; c.strokeRect(1024-x,y,1,1); } function n(cc,r){return Math.round(cc) + 255-r} </script> </head> <body><canvas width=1024 height=512></canvas></body> </html>
縦横1ピクセルのstrokeRectで点を描いてるつもりなんだけどなぜか1ピクセル以上の幅になってしまう。
→与える座標を0.5ずらしたら解決した。なんて律儀なモデルなんだ。
線の太さが 1.0 で (3,1) から (3,5) までのパスを考えた場合、中央の図のようになります。実際に塗りつぶされる領域 (暗い青色) は中間からパスの両側のピクセルまで広がり、考えていたパスに近いものが描画されます。つまり、これらのピクセルのみが部分的に薄くされ、領域全体 (明るい青色と暗い青色) の半分が、実際に描く色として暗く塗りつぶされます。これが先のコード例の 1.0 幅の線で起こったことです。
https://developer.mozilla.org/ja/Canvas_tutorial/Applying_styles_and_colors
これを修正するには、とても正確にパスを作成しなければなりません。知ってのとおり、1.0 幅の線は線幅を単位の半分からパスの両側まで広げます。右端の図は、(3.5,1) から (3.5,5) までのパスを作成した場合の結果です。最終的に 1.0 幅の線は完成し、単一ピクセルの垂直線を正確に塗りつぶすことができました。
黄色や紫のところにうっすらと線が見えるのも気になる。境界処理をミスってるのだろうか…。