[BMP]バイリニア法(線形補間) | Assertion Failed!

[BMP]バイリニア法(線形補間)

コードとしては美しくないが、なんとかバイリニア法を実現させた。


理論は簡単だけど、実際コードにすると意外と参考にできそうなのが

みつからなかったり。



Assertion Failed!-バイリニア法
バイリニア法      ニアレストネイバー


縮小された時点でも結構わかるけど、リンク開いて拡大してみれば

尚わかる違い。


基本的なアルゴリズムは数学的要素を多分に含むが簡単に。

(アフィン変換とか行列とかが多分にでてきます。)


[バイリニア法]

画像を回転させ、回転後の座標から回転元の座標を求めることは

これまでにも数回行っている。


これまでは、上記方法で求めた座標をすぐに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