Blog | Tag | Local | Guest | Login | Write |  RSS


이번 포스팅에서는 비트맵포멧의 구조를 알아보도록 하겠습니다.
보통은 DIB를 많이 사용하기 때문에 많은 포스팅에서는 DIB와 관련된 포멧구조만 설명하는 경향이있는데,
이번 포스팅에서는 저번포스팅에서 말씀드렸던 것처럼


DDB를 무시하고 넘어갈 수 없는 이유로 DDB의 구조와 DIB의 헤더구조를 알아보도록 하겠습니다.


일단,,
Bitmap 파일포멧은 다른 파일포멧(JPG,GIF 등등)들과 달리 압축을 수행하지 않으며
헤드가 있는 여러형식의 파일중에서 헤더구조가 가장 간단합니다.
(당연할 수 밖에 없지 않나요? 압축이 되면 된만큼 헤더에는 정보가 많아야 할 테니까요~)
어렵다고 느껴지시겠지만,, 이것으로 위안삼으세요-_ㅠ 힝


DDB () - 장치에 종속적인 비트맵

 typedef struct tagBITMAP
{
LONG bmType;                 // - bmType : 비트맵 타입;;  ( 보통 0을 가지고 있습니다.)
LONG bmWidth;                // - bmWidth : 이미지의 가로크기 
LONG bmHeight;               // - bmHeight : 이미지의 세로크기
LONG bmWidthBytes;        // - bmWidthBytes : bitmap 이미지의 한줄에 표현될 바이트 수, 
                                                                 (비트맵은 word단위로 표현되므로 항상 짝수)
WORD bmPlanes;             // - bmPlanes : 색상면의 개수
WORD bmBitsPixel;           // - bmBitsPixel : 한 픽셀에 필요한 비트의 수
LPVOID bmBits;                // - bmBits : 실제 비트맵 데이터를 가르키는 포인터
                                                        (단 bmBits 는 반드시 char배열,1바이트배열의 포인터)
} BITMAP;

이러한 DDB는  CreateBitmap()  함수를 통하여 쉽게 만들 수 있습니다.
이 함수는 간단하게 DDB를 만들어 주는데,
SelectObject()함수로 DC를 선택할때 CreateBitmap()함수는 속도가 느리기 때문에
성능적인 측면을 고려한다면 이 함수는 흑백비트맵을 만들때 주로 사용하고
만약 컬러비트맵을 만들고자 한다면 CreateCompatibleBitmap() 함수를 사용하는 것이 좋습니다.


1. CreateBitmap()함수를 살펴보자면

 HBITMAP CreateBitmap(int nWidth,int nHeight,UINT cPlanes,UINT cBitsPerPel,CONST VOID *lpvBits );

- 각각에 파라미터는 헤더정보에 들어가는 structer를 채우게되고 리턴값으로 DDB핸들이 리턴됩니다.

2. CreateCompatibleBitmap() 함수를 살펴봅시다.

 HBITMAP CreateCompatibleBitmap(HDC hdc,int nWidth,int nHeight );

- 주의해서 보셔야 할 부분은 디바이스컨텍스트를 파라미터로 받는다는 것인데, 바로 SelectObject()함수를
  이용하여 비트맵을 DC로 출력할 때 빠른속도를 내기 위해서입니다.
  또 디바이스컨텍스트와 픽셀포멧,생상수가 동일한 비트맵을 만들어줍니다.
- 나머지 두 인자는 이미지의 가로세로값을 초기화시켜줍니다.
- 단 이함수는 비트맵의 각 픽셀값은 초기화 되지 않으므로 일일히 초기화해주어야 하는 단점이 있습니다..



DIB () - 장치에 독립적인 비트맵

 파일헤드(BITMAPFILEHEADER)
 영상헤드(BITMAPINFOHEADER)
 팔레트정보(RGBQURD)
 영상데이터(거꾸로 들어있음)

DIB파일은 다음과 같은 구조로 이루어져 있습니다.
일단
1. 파일자체의 정보를 가지고 있는 파일헤드 (BITMAPFILEHEADER)
2. 비트맵 영상에 대한 크기나 흑백,컬러정보, 팔레트크기정보)등을 저장하기 위한 영상헤드 (BITMAPINFOHEADER)
3. 인덱스에 의한 컬러값을 저장하기위한 팔레트정보 (RGBQURD)
4. 이미지데이터 (거꾸로 들어있습니다.)
로 이루어져있습니다.

자세히 뜯어보면 이렇습니다.

1. BITMAPFILEHEADER - 파일 자체의 정보

 typedef struct tagBITMAPFILEHEADER
{
WORD bfType;            // - bfType : 비트맵파일인지 확인 (비트맵이라면. 반드시 BM (0x42,0x4d) )
DWORD bfSize;          // - bfSize : 비트맵 파일의 크기
WORD bfReserved1;   // - bfReserved1 : 예약되어 있는 값, 보통 0
WORD bfReserved2;   // - bfReserved2 : 예약되어 있는 값, 보통 0
DWORD bfOffBits;       // 실제 비트맵 데이터 값과 헤더의 오프셋 값 ( BITMAPFILEHEADER  + BITMAPINFO )
} BITMAPFILEHEADER;
 


2. BITMAPINFOHEADER - 비트맵 영상정보

 typedef struct tag BITMAPINFOHEADER
{
DWORD biSize;              // - biSize : BITMAPINFOHEADER 구조체의 크기
LONG biWidth;               // - biWidth : 비트맵의 가로픽셀의 수
LONG biHeight;              // - biHeight : 비트맵의 세로픽셀의 수
WORD biPlanes;            // - biPlanes : 장치에 있는 색상면의 개수 (반드시 1)
WORD biBitCount;           // - biBitCount : 한 픽셀을 표현할 수 있는 비트의 수
DWORD biCompression;  // - biCompression : 압축상태를 지정
                                    //   (BI_RGB : 압축되지 않은 비트맵,BI_RLE8 : 8bit압축 ,BI_RLE4 : 4bit압축 )
DWORD biSizeImage;      // - biSizeImage : 실제 이미지의 바이트크기 (압축되지 않은경우 0 )
LONG biXPelsPerMeter;  // - biXPelsPerMeter : 미터당 가로픽셀수
LONG biYPelsPerMeter;  // - biYPelsPerMeter : 미터당 세로픽셀수
DWORD biClrUsed;         // - biClrUsed  : 색상테이블의 색상중 실제 비트맵에서 사용되는 색상수
                                   // (0 : 비트맵은 사용할 수 있는 모든색상을 사용
                                   // , 그외 : RGBQUAD구조체배열의 크기는 이 멤버의 크기만큼 만들어짐)
DWORD biClrImportant;  // - iClrImportant : 비트맵을 출력하는데 필수적인 색상수 (0 : 모든 색상이 사용되어야함)

} BITMAPINFOHEADER;



3. RGBQUAD  - 인덱스의 컬러값

 typedef struct tag RGBQUAD
{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;

} RGBQUAD;

-> 여기서 한가지 알아두어야 할 정보는 RGB 순서가아니라 BGR순서로 되어있다는 것이다 ㅋ
     rgbReserved는 그냥 예약된 숫자 ㅋ 큰 의미는 없다.



우선다음의GDI 함수를알아보고코드를살펴보자.

CreateCompatibleBitmap( ) 함수

HBITMAP CreateCompatibleBitmap(HDC hdc, int nWidth, int nHeight );

• 이 함수는디바이스 컨텍스트와 호환되는, 즉픽셀 포맷과 색 상수 등이 같은 비트맵을 만드는데 CreateBitmap( ) 함수처럼 비트맵 이미지 데이터를 초기화할 수는 없습니다. 단순히 가로와 세로 값정도만을 설정할 수 있습니다.
• 함수를사용한후에는반드시DeleteObject() 함수를 호출하여 Object를 삭제할 수 있어야 합니다. (안그러면 메모리-_ㅠ)
 
CreateCompatibleDC( ) 함수

HDC CreateCompatibleDC(HDC hdc );

• 이 함수는 장치의 디바이스 컨텍스트와 호환되는디바이스 컨텍스트, 즉 메모리디바이스 컨텍스트를만들어줍니다.
 비트맵을 디바이스 컨텍스트에 선택할 때 이 함수를 이용하여 메모리 dc를 만들어 선택합니다.
 사용한 후에 마찬가지로 반드시 DeleteDC() 함수를 호출하여 메모리누수가 없도록 방지합니다.
• hdc 인자로 null이면 기본으로  현재 디스플레이 화면의 디바이스컨텍스트와 호환되는 디바이스컨텍스트핸들을 반환합니다.

SelectObject () 함수

HGDIOBJ SelectObject(HDC hdc, HGDIOBJ hgdiobj );

• 이 함수는 디바이스 컨텍스트에GDI 객체를선택할수 있게 합니다. GDI 객체란펜이나 브러시, 폰트, 비트맵 등을 말하는데 여기에서는 비트맵을 디바이스 컨텍스트에 선택하기 위해서 사용합니다. GDI 객체는반드시 디바이스 컨텍스트에 선택되어진후
사용되기때문에GDI 객체를사용할때에는반드시이 함수를사용해야된니다. 이함수를 사용하면 반환 값으로 선택되기 전의 GDI 객체가반환되는데이 값을 받아 두었다가 GDI 객체를사용한 후, 반드시 디바이스 컨텍스트에 이전 GDI 객체를 선택하게됩니다.
 

다음 포스팅에서는 비트맵 영상의 컬러표현에 대해서 알아보겠습니다.