더북(TheBook)

CreateGrayBitmapCreateRgbBitmap 함수에서 주의할 부분은 픽셀 데이터 저장을 위한 메모리 공간을 할당하는 부분이다. 소스 코드 중간에서 아래 코드를 살펴보자.

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

영상의 가로 한 줄을 표현하는 데 필요한 바이트 수는 m_nWidth * m_nBitCount / 8 형태로 계산할 수 있다. 그러나 DIB 구조에서는 영상의 가로 한 줄의 바이트 수가 4의 배수 형태가 되어야 하기 때문에 위와 같이 조금 복잡한 수식이 사용되었다. k가 임의의 정수일 때, (k+3) & ~3 형태로 코드를 작성하면 이는 k보다 큰 4의 배수를 나타내게 된다. 그러므로 DIB 구조에서 영상의 가로 한 줄을 저장하는 데 필요한 바이트 수는 (m_nWidth * m_nBitCount / 8 + 3) & ~3 형태로 계산한다. dwWidthStep 값이 정확하게 계산되면 여기에 영상의 세로 크기를 곱하여 픽셀 데이터 저장에 필요한 전체 바이트 수를 구할 수 있다. 나머지 소스 코드들은 각자 확인해보기 바란다.

Note | memset 함수

CreateGrayBitmap과 CreateRgbBitmap 함수에서 픽셀 값을 0으로 초기화하기 위하여 memset 함수를 사용하였다. memset 함수의 원형은 다음과 같다.

void *memset(void *dest, int c, size_t count);

memset 함수는 dest로 시작되는 메모리 공간에서 count 바이트만큼의 메모리 공간을 c의 값으로 설정한다. 예를 들어 픽셀 데이터 시작 주소가 pDib이고 픽셀 데이터 메모리 공간 크기가 dwSizeImage인 경우, 픽셀 데이터를 0으로 초기화하려면 memset(pDib, 0, dwSizeImage);라고 쓰면 된다.

memset 함수를 사용할 때 주의해야 할 것은 c의 자료형은 int이지만, 메모리 설정은 바이트 단위로 설정한다는 점이다. 예를 들어 아래와 같은 int 형 배열이 있을 때 이를 초기화하는 코드에 대해 알아보자.

int a[10];

배열 a의 모든 원소 값을 0으로 초기화하려면 memset(a, 0, sizeof(int)*10);과 같이 코드를 작성하면 된다. 그러나 만약 배열 a의 모든 원소 값을 1로 초기화하기 위해 memset(a, 1, sizeof(int)*10);과 같이 코드를 작성하면 배열 a의 모든 원소는 1을 갖는 것이 아니라 16843009라는 값을 갖게 된다. 이는 1이라는 값이 4바이트를 갖는 int 형의 각각의 바이트에 설정되어 16진수 0x01010101 값을 가지게 되기 때문이다. 그러므로 배열이나 특정 메모리 영역을 0이 아닌 값으로 초기화할 때는 memset 함수를 사용하면 안 된다. 대신에 for 루프 등을 사용하여 각각의 원소를 개별적으로 초기화해야 한다.

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