●前回まで
[画像処理](x1,y1,x2,y2) vs (x,y,width,height)
[画像処理](x1,y1,x2,y2) vs (x,y,width,height) その2
[画像処理](x1,y1,x2,y2) vs (x,y,width,height) その3
[画像処理](x1,y1,x2,y2) vs (x,y,width,height) その4
※以下PnPとPnSは私の造語です。
PnP・・・Point and Point。座標2つで矩形領域を表す方式
PnS・・・Point and Size。座標1つと領域のサイズで矩形領域を表す方式
前回はGDIとGDI+の矩形描画の仕組みを私なりに書いてみました。
しかし色々と調査してみると
GDIの「内接する矩形を描画している」という解釈はどうやら不正解のようです。
●線分描画アルゴリズムからの考察
説明のために縦の辺についてだけ抜き出します。
前回説明を省きましたが緑が仮想座標上の辺、
青が実際のディスプレイに表示されるピクセルです。
内接すると仮定すると図1(A)のようになります。
緑の線に対して青のピクセル位置を求めようとすると、
左右のそれぞれ別の(線分描画の)計算が必要となります。
果たして縦線を2通りの計算で求めるなどわざわざやるか?という問題です。
その可能性は0では無いでしょうが、どの縦線も同じ計算で求めていると考えた方が自然ではないでしょうか?
そしてその場合は図1(B)のようになります。
するとこれはRightは-1した値を用いて計算するという事になります。
あるいはLeftを+1する説も考えられますが数学の世界で上限を未満で表現する体系がありますのでRight-1という解釈の方が妥当だろうと思います。
ここにきて「GDIは右下座標を用いない。左上以上、右下未満で範囲指定する」
という俗説がやっぱり正解なんだなあとわかります。
なんとか別の説をひねり出したかったのですが今日の所はあきらめます。
●線幅について
前回の最後で考慮がもれていると書いたアレは線幅でした。
線幅をテストできるように実験プログラムを修正しました。
http://myugaru.wankuma.com/GDIvsGDIplus.zip
見やすいようにグリッドも表示しています。
GDIの矩形(塗潰し)Left=2,Top=2,Right=8,Bottom=8を線幅1~3で表示すると次のようになります。
こうしてみると線幅2の時は緑の線が青の中心を通っています。
線幅1や3の場合には中心がピクセル中央となってしまいますので、
誤差の0.5だけ右下方向へずらして描画しているようです。
すでにGDIの矩形は内接矩形の描画では無いだろうと書きましたが、
線幅2以上の矩形の図の説明を内接矩形でするとかなり無理が生じます。
そういう意味でもやはり内接矩形論は正しくないのだろうと考えられます。
●GDI+の線幅2以上はどうか
GDI+について線幅2以上で書くとGDIと全く同じ考え方になっているとわかります。
つまり線幅が偶数の場合は緑の線が青の中心を通り、
線幅が奇数の場合は緑の線の右下へ0.5ずれるという仕様です。
●まとめ
GDIもGDI+もどちらも上の緑の線で表現されるような仮想図形を想定しており、
ディスプレイのピクセルで表現する際に誤差が生じているのだとわかりました。
ディスプレイ主体で考えると色々な疑問が生じるのはそのせいです。
また矩形描画について実験した結果はGDIもGDI+もどうやら誤差の扱い方は同じだということもわかりました。
またGDIは右下を使用しないという仕様を再確認できました。
●次回
このシリーズは私は結構おもしろいと思ってやっていますが、
読んでる人はそろそろ飽きて来たのではないかと思っています。
昨日書いたリバースエンジニアリングの話にしてもいいかなと思ったり、
あるいはUMLの勉強で序章が終わりましたので、
ゲーム製作の方を進展させるのもいいかなと思っています。