더북(TheBook)

참고로 IppDib 클래스는 내부적으로 동적 메모리를 할당하여 DIB 구조를 저장하고 있기 때문에 복사 생성자를 따로 정의하여 동적 할당된 메모리를 복사해주어야 안전하다. 복사 생성자를 제공하기 때문에 아래와 같은 코드를 이용하여 DIB 복사본을 생성할 수 있다.

IppDib dib;               // 기본 생성자 호출
dib.Load("c:\\test.bmp"); // c:\test.bmp 파일 불러오기
IppDib cpy = dib;         // 복사 생성자 호출. cpy는 dib와 동일한 영상을 저장한다.
IppDib cpy2(dib);         // 복사 생성자 호출. 위와 동일하다.

IppDib 클래스에서 실제적인 비트맵 생성과 소멸 동작은 아래 멤버 함수들이 담당한다.

BOOL CreateGrayBitmap(LONG nWidth, LONG nHeight);
• BOOL CreateRgbBitmap(LONG nWidth, LONG nHeight);
• void DestroyBitmap();

그레이스케일 비트맵을 생성하려면 CreateGrayBitmap 함수를 사용하고, 트루컬러 비트맵을 생성할 때에는 CreateRgbBitmap 함수를 사용한다. 이 함수들은 가로 크기가 m_nWidth이고 세로 크기가 m_nHeight인 영상을 DIB 구조로 저장하기 위해 필요한 메모리 공간을 동적 할당하고, BITMAPINFOHEADER 구조체와 색상 테이블 정보를 생성한다. 그리고 픽셀 데이터는 모두 0으로 초기화한다. 사용이 끝난 비트맵은 DestroyBitmap 함수를 이용하여 동적 할당한 메모리를 해제하고 멤버 변수를 초기화할 수 있다. CreateGrayBitmap, CreateRgbBitmap, DestroyBitmap 함수의 전체 구현은 소스 4-3에 나타내었다.

소스 4-3 IppDib 클래스 - 비트맵 생성과 소멸(IppDib.cpp)
BOOL IppDib::CreateGrayBitmap(LONG nWidth, LONG nHeight)
{
    if (m_pDib)
        Destroy();

    m_nWidth = nWidth;
    m_nHeight = nHeight;
    m_nBitCount = 8;

    DWORD dwWidthStep = (m_nWidth * m_nBitCount / 8 + 3) & ~3;
    DWORD dwSizeImage = (m_nHeight * dwWidthStep);
    m_nDibSize = sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * GetPaletteNums()) + dwSizeImage;

    m_pDib = new BYTE[m_nDibSize];
    if (m_pDib == NULL)
        return FALSE;

    // BITMAPINFOHEADER 구조체 설정
    LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)m_pDib;
    lpbmi->biSize          = sizeof(BITMAPINFOHEADER);
    lpbmi->biWidth         = m_nWidth;
    lpbmi->biHeight        = m_nHeight;    
    lpbmi->biPlanes        = 1;
    lpbmi->biBitCount      = m_nBitCount;
    lpbmi->biCompression   = BI_RGB;
    lpbmi->biSizeImage     = dwSizeImage;
    lpbmi->biXPelsPerMeter = 0;
    lpbmi->biYPelsPerMeter = 0;
    lpbmi->biClrUsed       = 0;
    lpbmi->biClrImportant  = 0;

    // 그레이스케일 팔레트 설정
    RGBQUAD* pPal = (RGBQUAD*)((BYTE*)m_pDib + sizeof(BITMAPINFOHEADER));
    for (int i = 0; i < 256; i++)
    {
        pPal->rgbBlue     = (BYTE)i;
        pPal->rgbGreen    = (BYTE)i;
        pPal->rgbRed      = (BYTE)i;
        pPal->rgbReserved = 0;
        pPal++;
    }

    // 픽셀 데이터 초기화
    BYTE* pData = GetDIBitsAddr();
    memset(pData, 0, dwSizeImage);

    return TRUE;
}

BOOL IppDib::CreateRgbBitmap(LONG nWidth, LONG nHeight)
{
    if (m_pDib)
        Destroy();

    m_nWidth = nWidth;
    m_nHeight = nHeight;
    m_nBitCount = 24;

    DWORD dwWidthStep = (m_nWidth * m_nBitCount / 8 + 3) & ~3;
    DWORD dwSizeImage = (m_nHeight * dwWidthStep);
    m_nDibSize = sizeof(BITMAPINFOHEADER) + dwSizeImage;

    m_pDib = new BYTE[m_nDibSize];
    if (m_pDib == NULL)
        return FALSE;

    // BITMAPINFOHEADER 구조체 설정
    LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)m_pDib;
    lpbmi->biSize            = sizeof(BITMAPINFOHEADER);
    lpbmi->biWidth           = m_nWidth;
    lpbmi->biHeight          = m_nHeight;
    lpbmi->biPlanes          = 1;
    lpbmi->biBitCount        = m_nBitCount;
    lpbmi->biCompression     = BI_RGB;
    lpbmi->biSizeImage       = dwSizeImage;
    lpbmi->biXPelsPerMeter   = 0;
    lpbmi->biYPelsPerMeter   = 0;
    lpbmi->biClrUsed         = 0;
    lpbmi->biClrImportant    = 0;

    // 픽셀 데이터 초기화
    BYTE* pData = GetDIBitsAddr();
    memset(pData, 0, dwSizeImage);

    return TRUE;
}

void IppDib::Destroy()
{
    if (m_pDib)
    {
        delete[] m_pDib;
        m_pDib = NULL;
    }

    m_nWidth    = 0;
    m_nHeight   = 0;
    m_nBitCount = 0;
    m_nDibSize  = 0;
}
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.