더북(TheBook)

IppDibToImage 함수에서 for 루프 코드를 좀 더 자세히 살펴보자.

for (int i = 0; i < h; i++)
{
    memcpy(pixels[i], &pDIBits[(h - 1 - i) * ws], w);
}

위에서 pixels[i]IppByteImagei번째 행의 픽셀 데이터 시작 주소를 나타낸다. pDIBits는 DIB 구조에서 픽셀 데이터의 시작 위치를 나타낸다. ws 변수는 DIB 구조에서 영상의 가로 한 줄을 저장하기 위해 필요한 바이트 수를 나타내며, 4의 배수 형태를 갖는다. DIB 구조에서 픽셀 데이터는 상하가 뒤집힌 형태로 저장되기 때문에 실제 영상에서 i번째 행의 시작 위치는 pDIBits [(h - 1 - i) * ws] 형태로 구할 수 있다. 그리고 ws 바이트 중에서 실제 의미 있는 픽셀 데이터는 w 바이트이므로 memcpy 함수에서 w 바이트만 복사하도록 설정하였다.

IppImage 클래스를 IppDib로 변환하는 IppImageToDib 함수도 IppDibToImage 함수와 동일한 구조로 구현할 수 있다. 세 가지 타입의 IppImage 클래스에 대한 변환 함수를 소스 4-17에 나타내었다.

소스 4-17 IppImageToDib 함수 구현(IppConvert.cpp)
void IppImageToDib(IppByteImage& img, IppDib& dib)
{
    assert(img.IsValid());

    int w = img.GetWidth();
    int h = img.GetHeight();
    int ws = (w + 3) & ~3;
    BYTE** pixels = img.GetPixels2D();

    dib.CreateGrayBitmap(w, h);
    BYTE* pDIBits = dib.GetDIBitsAddr();

    for (int i = 0; i < h; i++)
    {
        memcpy(&pDIBits[(h - 1 - i) * ws], pixels[i], w);
    }
}

void IppImageToDib(IppFloatImage& img, IppDib& dib)
{
    assert(img.IsValid());

    int w = img.GetWidth();
    int h = img.GetHeight();
    int ws = (w + 3) & ~3;
    float** pixels = img.GetPixels2D();

    dib.CreateGrayBitmap(w, h);
    BYTE* pDIBits = dib.GetDIBitsAddr();

    int i, j;
    for (j = 0; j < h; j++)
    for (i = 0; i < w; i++)
    {
        pDIBits[(h - 1 - j) * ws + i] = static_cast<BYTE>(limit(pixels[j][i] + 0.5f));
    }
}

void IppImageToDib(IppRgbImage& img, IppDib& dib)
{
    assert(img.IsValid());

    int w = img.GetWidth();
    int h = img.GetHeight();
    int ws = (w * 3 + 3) & ~3;
    RGBBYTE** pixels = img.GetPixels2D();

    dib.CreateRgbBitmap(w, h);
    BYTE* pDIBits = dib.GetDIBitsAddr();

    for (int i = 0; i < h; i++)
    {
        memcpy(&pDIBits[(h - 1 - i) * ws], pixels[i], w * 3);
    }
}
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.