그러면 3차 회선 보간법을 이용한 영상의 크기 변환을 C/C++ 함수로 만들어보자. 3차 회선 보간법의 구현 함수의 이름은 IppResizeCubic을 사용하기로 하자. IppResizeCubic 함수에서는 내부적으로 cubic_interpolation이라는 함수를 사용할 것이다. 그러므로 다음 두 개의 함수 선언을 IppGeometry.h 파일에 추가하자.

    void IppResizeCubic(IppByteImage& imgSrc, IppByteImage& imgDst, int nw, int nh);
    double cubic_interpolation(double v1, double v2, double v3, double v4, double d);
    

    IppResizeCubic 함수의 인자 구성은 앞에서 살펴보았던 IppResizeNearest 또는 IppResizeBilinear 함수와 동일하다. cubic_interpolation 함수는 그림 9-13에서 설명한 4개의 픽셀 값을 이용하여 결정된 값 v를 반환하는 함수이며, 함수 인자로 사용되는 변수 명은 그림 9-13에 표기된 기호와 동일하다. cubic_interpolation 함수는 IppResizeCubic 함수 내에서 모두 5번 호출된다. IppResizeCubiccubic_interpolation 함수의 전체 구현은 소스 9-6에 나타내었다.

    소스 9-6 3차 회선 보간법을 이용한 크기 변환 구현 함수(IppGeometry.cpp)
    void IppResizeCubic(IppByteImage& imgSrc, IppByteImage& imgDst, int nw, int nh)
    {
        int w = imgSrc.GetWidth();
        int h = imgSrc.GetHeight();
    
        imgDst.CreateImage(nw, nh);
    
        BYTE** pSrc = imgSrc.GetPixels2D();
        BYTE** pDst = imgDst.GetPixels2D();
    
        int i, j, x1, x2, x3, x4, y1, y2, y3, y4;
        double v1, v2, v3, v4, v;
        double rx, ry, p, q;
    
        for (j = 0; j < nh; j++)
        for (i = 0; i < nw; i++)
        {
            rx = static_cast<double>(w - 1) * i / (nw - 1);
            ry = static_cast<double>(h - 1) * j / (nh - 1);
    
            x2 = static_cast<int>(rx);
            x1 = x2 - 1; if (x1 < 0) x1 = 0;
            x3 = x2 + 1; if (x3 >= w) x3 = w - 1;
            x4 = x2 + 2; if (x4 >= w) x4 = w - 1;
            p = rx - x2;
    
            y2 = static_cast<int>(ry);
            y1 = y2 - 1; if (y1 < 0) y1 = 0;
            y3 = y2 + 1; if (y3 >= h) y3 = h - 1;
            y4 = y2 + 2; if (y4 >= h) y4 = h - 1;
            q = ry - y2;
    
            v1 = cubic_interpolation(pSrc[y1][x1], pSrc[y1][x2], pSrc[y1][x3], pSrc[y1][x4], p);
            v2 = cubic_interpolation(pSrc[y2][x1], pSrc[y2][x2], pSrc[y2][x3], pSrc[y2][x4], p);
            v3 = cubic_interpolation(pSrc[y3][x1], pSrc[y3][x2], pSrc[y3][x3], pSrc[y3][x4], p);
            v4 = cubic_interpolation(pSrc[y4][x1], pSrc[y4][x2], pSrc[y4][x3], pSrc[y4][x4], p);
    
            v = cubic_interpolation(v1, v2, v3, v4, q);
    
            pDst[j][i] = static_cast<BYTE>(limit(v + 0.5));
        }
    }
    
    double cubic_interpolation(double v1, double v2, double v3, double v4, double d)
    {
        double v, p1, p2, p3, p4;
    
        p1 = 2 * v2;
        p2 = -v1 + v3;
        p3 = 2 * v1 - 5 * v2 + 4 * v3 - v4;
        p4 = -v1 + 3 * v2 - 3 * v3 + v4;
    
        v = (p1 + d * (p2 + d * (p3 + d * p4))) / 2.;
    
        return v;
    }
    

    소스 9-6의 IppResizeCubic 함수 내부의 정수형 변수 x1~x4, y1~y4는 3차 회선 보간법에서 사용할 16개의 점들의 가로, 세로 좌표를 저장할 변수이다. 이 좌표들을 지정할 때, 영상의 크기를 벗어난 위치의 좌표를 저장하지 않도록 신경을 써주어야 한다. 앞에서 언급한 것과 같이 cubic_interpolation 함수를 4번 호출하여 v1~v4의 값을 결정하는 것을 볼 수 있는데, 이 값들은 그림 9-11에서 설명한 삼각형에 해당하는 곳에서의 픽셀 값의 추정치이다. 그리고 v1~v4 값과 실숫값 q를 이용하여 cubic_interpolation 함수를 한 번 더 호출하여 최종적으로 보간된 값 v를 얻어냄을 볼 수 있다. 실숫값 v는 반올림하여 정수형으로 변환하고, 그 값을 결과 영상의 픽셀 값으로 지정한다.

    신간 소식 구독하기
    뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.