Bitmap 파일 구조

디바이스에 독립적인 영상파일을 저장하는 표준규격

JPEG, GIF, BMP, TIFF, PCX, PGM 등이 존재

보통 영상데이터는 정보량이 크기 때문에 압축을 통해 작은 크기로 변환하여 저장한다.

BMP파일 포맷은 압축을 수행하지 않으며 헤드가 있는 여러 형식의 파일 중에서

구조가 가장 간단하다.

파일 헤더

BITMAPFILEHEAER라는 구조체에 정의

사용자는 단지 구조체 변수를 선언해서 사용만 하면 된다.

현재의 파일 포맷이 정말 BMP인지에 대한 정보

BMP파일의 확장자 : *.BMP로 정의

다른 파일이 XX.BMP라고 썼을 수 있으므로, BMP디코더가 이를 분석

세가지 분석방법이 존재.

Bitmap 의 종류

DDB(Device-Dependent Bitmap) -> 장치종속 Bitmap

DIB(Device-Independent Bitmap) -> 장치독립 Bitmap

DIB 구조

BITMAPFILEHEADER	-> File이 Bitmap File인지 구별하는 구조체.

BITMAPINFO               -> Bitmap의 정보와 팔레트에 대한 정보를 제공하는 구조체.

BITMAPINFOHEADER	-> Bitmap의 정보에 관한 구조체.

RGBQUAD                 -> 이미지의 색상 정보 구조체.

Image Data                -> 실제자료가 pixel 로 구성되어 있음.

DIB 구조체

type struct tagBITMAPFILEHEADER

{

WORD        bfType;	// Bitmap파일을 나타내는 "BM" 문자의 ASCII값을 취함.

DWORD      bfSize;	// Bitmap파일의 크기

WORD        bfReserved1;  // 사용하지 않은 확장 예약변수

WORD        bfReserved2;  // 사용하지 않은 확장 예약변수

DWORD      bfOffbits;	// 실질 데이터(pixel)의 시작좌표를 나타냅니다.

}BITMAPFILEHEADER;

1. 파일의 첫 2바이트가 BM으로 시작하는가.

2. 바이트 단위의 정확한 파일크기와 헤더내의 bfSize가 있어야할 값과 일치하는가.

3. bfReserved1과 bfReserved2가 있어야 할 위치에 0값이 있는가.

세가지를 모두 체크, bmp파일 여부를 판명

디코더의 크기를 줄이기 위해, 첫 번째것만 체크하는 경우

파일의 헤더의 역할

포맷의 명확성을 표시

파일 내에 있어서 실질 데이터(pixel data)의 주소값을 나타내줍니다.

다시말해, 실질데이터의 파일 내 위치를 정의해 주는 역할

type struct tabBITMAPINFO

{

BITMAPINFOHEADER    bmiHeader;

RGBQUAD                    bmicolors[1];

} BITMAPINFO;

type struct tagBITMAPINFOHEADER

{

DWORD    biSize;

LONG    biWidth;                    //이미지의 가로 길이.

LONG    biHeight;                   //이미지의 세로 길이.

WORD    biPlanes;	//플레인수

WORD    biBitCount;                // 이미지의 컬러 비트수.

예) 8 이면 2의 8승이 되어 256컬러임을 알수 있음.

DWORD    biCompression;	// 압축 유무

DWORD    biSizeImage;	// 이미지 크기

LONG    biXPelsPerMeter;	// 미터당 가로 픽셀

LONG    biYPelsPerMeter;	// 미터당 세로 픽셀

DWORD    biClrUsed;	// 컬러 사용 유무

DWORD    biClrImportant;	// 중요하게 사용하는 색

} BITMAPINFOHEADER;

typedef struct tagRGBQUAD

{

BYTE    rgbblue;           // 파란색값

BYTE    rgbGreen;	// 녹색값

BYTE    rgbRed;	// 빨간색값

BYTE    rgbReserved;	// 항상 0

} RGBQUAD;

1. 팔레트는 인덱스에 의한 컬러값을 저장하기 위한 구조체.

2. 이 구조체를 사용하여 팔레트의 수 만큼 배열을 할당하여 저장.

3. 256컬러모드의 영상은 팔레트의배열 크기가 256개

4. 16비트 컬러영상은 팔레트 크기가 2의 16승개이다. biClrUsed변수를 참조하면 된다.

이미지는 모든색을 사용하는 것이 아니라 특정 색만을 사용한다.

예를 들어 8비트 Bitmap 이미지는 256색만을 사용한다.

Bitmap 이미지의 color정보를 이미지를 로드할 때마다 시스템에서 얻어오는 것보다 Bitmap 파일 안에 color 정보를 가지고, 그곳에서 얻어오는 것이 속도면에서 많은 이득이 있기 때문에 RGBQUAD 구조체를 사용하여 Bitmap 이미지의 color 정보를 저장한다.

이러한 color정보들의 모임을 다른 말로 '팔레트(Palette)라고 한다.

8비트 Bitmap이미지에서는 256개 color에 해당하는 256개의 RGBQUAD 배열, 즉 이미지 파일내에 팔레트가 존재하게 된다.

여기서는 문제점이 있는데 만약 Bitmap 이미지가 16비트 이상의 color 이미지이면 문제가 발생한다. 16비트 Bitmap 이미지는 컬러 수가 65536색 이며, 이것을 Bitmap 파일 내에 팔레트를 둔다면 65536개의 RGBQUAD배열을 만들어야 한다.

이는 배보다 배꼽이 큰 경우가 되기 때문에 조금 느리더라도 16비트 이상의 Bitmap 이미지에서는 내부 팔레트를 사용하지 않고, 시스템에서 제공하는 시스템 팔레트를 사용한다.

이미지의 저장 상태

이미지를 보는 그림과는 다르게 Image Data에는 상하가 뒤집어진 상태로 저장되어 있다.

이 때문에 Surface에 이미지를 로드 할 때 주의를 해야 한다.

이미지를 저장하거나 로드할 때는 항상 width, 즉 가로길이를 4의 배수로 맞추어야 한다.

예를 들어 이미지가 30 * 30 크기의 이미지이면 한 줄 읽을 때는 32byte를 읽어야 한다.

Bitmap 이미지는 항상 가로길이가 4의 배수이기 때문에 30byte는 이미지 data이고 나머지 2byte는 길이를 맞추기 위해 채워져야 한다.

이것을 모르고 그냥 이미지를 물러오면 이미지가 화면에 제대로 출력되지 않는다.