[BMP]バイリニア法(線形補間)
コードとしては美しくないが、なんとかバイリニア法を実現させた。
理論は簡単だけど、実際コードにすると意外と参考にできそうなのが
みつからなかったり。
縮小された時点でも結構わかるけど、リンク開いて拡大してみれば
尚わかる違い。
基本的なアルゴリズムは数学的要素を多分に含むが簡単に。
(アフィン変換とか行列とかが多分にでてきます。)
[バイリニア法]
画像を回転させ、回転後の座標から回転元の座標を求めることは
これまでにも数回行っている。
これまでは、上記方法で求めた座標をすぐにintキャストして
(つまり最も近い座標を使う、ニアレストネイバー法)いたが。
今回は小数点となっている座標と、それを囲む直近4座標との
距離から色の濃度を求めるというものである。
その求められた色をニアレストネイバー法で求められる座標に
当てはめる。
実現した際のコードは、前回 のコードのfor文をいじっただけですんだ。
(実際はもっと関数化など美しくすべきだけど、めんどかった。。)
for(int dstY = 0; dstY < dstHeight; dstY++)
{
for(int dstX = 0; dstX < dstWidth; dstX++)
{
// 求める座標①
double dsrcX = ((dstX - dtX) * dcos - (dstY - dtY) * dsin);
double dsrcY = ((dstX - dtX) * dsin + (dstY - dtY) * dcos);
// 求める座標から小数点を切り捨てた座標②
int isrcX = static_cast<int>(dsrcX);
int isrcY = static_cast<int>(dsrcY);
// ①と②の距離
double dx = dsrcX - isrcX;
double dy = dsrcY - isrcY;
// 元画像の座標
int srcX = static_cast<int>(dsrcX + 0.5);
int srcY = static_cast<int>(dsrcY + 0.5);
if((0 <= isrcX) && (isrcX < nSrcWidth) && (0 <= isrcY) && (isrcY < nSrcHeight))
{
// 直近4座標の色データを取得する
RGBTRIPLE rtLB, rtRB, rtLT, rtRT;
memcpy(&rtLB, &m_pSrcData[isrcX*3 + isrcY*srcLength],3);
memcpy(&rtRB, &m_pSrcData[(isrcX+1)*3 + isrcY*srcLength],3);
memcpy(&rtLT, &m_pSrcData[isrcX*3 + (isrcY+1)*srcLength],3);
memcpy(&rtRT, &m_pSrcData[(isrcX+1)*3 + (isrcY+1)*srcLength],3);
pDstData[dstX * 3 + dstY * dstLength] =
(BYTE)((1-dy) * ((1-dx) * rtLB.rgbtBlue + dx * rtRB.rgbtBlue) +
dy * ((1-dx) * rtLT.rgbtBlue + dx * rtRT.rgbtBlue) + 0.5);
pDstData[dstX * 3 + dstY * dstLength + 1] =
(BYTE)((1-dy) * ((1-dx) * rtLB.rgbtGreen + dx * rtRB.rgbtGreen) +
dy * ((1-dx) * rtLT.rgbtGreen + dx * rtRT.rgbtGreen) + 0.5);
pDstData[dstX * 3 + dstY * dstLength + 2] =
(BYTE)((1-dy) * ((1-dx) * rtLB.rgbtRed + dx * rtRB.rgbtRed) +
dy * ((1-dx) * rtLT.rgbtRed + dx * rtRT.rgbtRed) + 0.5);
}
}
}
ただし、上記コードは画面端(前回赤線引いたところ)にごみが入っており
完璧ではない。
どこかに条件文いれないといけないが、どうすればいいのかはまだ未検討。
- 詳解 画像処理プログラミング C言語で実装する画像処理アルゴリズムのすべて/昌達 慶仁
- ¥3,990
- Amazon.co.jp