==================================Outline====================================
비트맵 구조체
----------------------------------------------------------------------------
비트맵 구조체
크기가 가로 400픽셀, 세로 400픽셀인 비트맵 파일을 임의로 생성하여 비트맵파일에 대해서 알아보기로 하자.
각 픽셀이 RGB로 표현되기 때문에 이 비트맵 파일의 용량은 (400 * 400) * 3이고, 54byte는 헤더파일이다. 헤더 파일은 실제내용을 간추린 정보를 제공하는데 이것을 ‘오버 헤더’라고 한다.
비트맵 파일은 픽셀 단위로 데이터를 저장한다. 1byte(8bits)에는 한가지 색에 대한 정보를 가지고 있다. 1픽셀은 3byte로 구성되는데, 각 바이트는 빨(Red), 녹(Green), 파(Blue)로 이루어져 있다.
**빛의 3원색: 빨강, 녹색, 파랑
**색의 3원색: 자주, 노랑, 청록
** 빛은 섞을수록 밝아지고 색은 섞을수록 어두워진다.
위에서 만든 비트맵 파일을 헥사뷰를 사용하여 출력해본다. 54byte가 'FF'가 아닌 값으로 표시되고 있음을 알 수 있다.
54Byte는 비트맵 파일의 헤더부분이며 비트맵 파일에 대한 정보를 담고 있다. 비트맵 파일의 구조체를 살펴보도록 하자.
/* BITMAPFILEHEADER 구조체 */
typedef struct tagBITMAPFILEHEADER{ //bmfh
WORD bfType; // 파일의 형태, 0x42, 0x4d (BM) 이어야함
WORD bfSize; // 비트맵 파일의 크기 (Byte단위)
WORD bfReserved1; // 예약. 0으로 설정
WORD bfReserved2; // 예약2. 0으로설정
DWORD bfOffBits; // 실제 비트맵데이터까지의 오프셋값
// 실제로는 bfOffBits = BITMAPFILEHEADER크기 + BITMAPINFOHEADER크기 + RGBQUAD 구조체배열의크기 이다.
} BITMAPFILEHEADER;
/* BITMAPINFOHEADER 구조체 */
typedef struct tagBITMAPINFOHEADER{ //bmfh
DWORD biSize; // 이 구조체의 크기. 구조체 버전확인할수 있다.
LONG biWidth; // 비트맵의 가로 픽셀수
LONG biHeight; // 비트맵의 세로 픽셀수
WORD biPlanes; // 플레인의 갯수 반드시 1이어야함
WORD biBitCount; // 한 픽셀이 구성되는 비트의수
DWORD biCompression; // 압축방법. BI_RGB일땐 비압축 BI_RLE8, BI_RLE4인경우 run length encode방법으로 압축
DWORD biSizeImage; // 이미지의 크기. 압축이 안되어있을때는 0
LONG biXPelsPerMeter; // 가로 해상도
LONG biYPelsPerMeter; // 세로 해상도
DWORD biClrUsed; // 색상테이블을 사용하였을때 실제 사용되는 색상수
DWORD biClrImportant; // 비트맵을 출력하는데 필수 색상수
} BITMAPINFOHEADER;
비트맵 파일 구조체를 참고하여 구조체 멤버들을 출력해보자.
400 * 400 크기의 BMP파일의 경우 한 픽셀당 3byte를 차지하고 그 값을 red, greeb, blue의 정도는 8bit(256) 나누어 표시할 수 있다. 파일의 총 크기는 480054byte이고 54byte는 헤더파일임으로 파일의 시작점에서 54byte 떨어진 지점부터의 데이터를 조작함으로써 BMP파일을 변형시킬 수 있다.
BMP파일을 조작하여 여러 가지 색깔로 변형시켜보자.
**BMP이미지를 수정하여 원본에 덮어 쓰도록 하자.
각 색에 대한 출력 정보는 0 ~ FF로 표현된다. '0'이 가장 낮은 단계이며 'FF'가 가장 높은 단계이다. 가로 픽셀이 400, 세로 픽셀이 400인 비트맵 구조체에서 가로 한 줄의 용량은 400 * 3이다. 좌측 상단에서 우측 하단까지 'for문'을 사용하여 데이터의 값을 입력할 값을 설정해주면 된다.
각 픽셀의 첫 번째 바이트는 blue, 두 번째 바이트는 green, 세 번째 바이트는 red이다. 비트맵 파일의 정보를 수정하여 색이 어떻게 바뀌는지 출력해보자.
소스 코드는 아래와 같다.
/*** 소스 ***/
#include <stdio.h>#include <fcntl.h>
#include <windows.h>
int main(int iNum, char * cpArr[])
{
int iRtn;
int iFd;
BITMAPFILEHEADER stBFHead;
BITMAPINFOHEADER stBIHead;
char cBuf[16*16];
unsigned char * ucpBuf;
unsigned int uiCntX;
unsigned int uiCntY;
iFd = open(cpArr[1], O_RDWR|O_BINARY);
if(iFd == 0)
{
printf("파일을 열 수 없습니다.\n");
return -1;
}
iRtn = read(iFd, &stBFHead, sizeof(BITMAPFILEHEADER));
if(iRtn == 0)
{
printf("파일을 읽을 수 없습니다.\n");
close(iFd);
return -1;
}
if( 0x4D42 != (stBFHead.bfType) )
{
printf("BMP파일이 아닙니다.\n");
close(iFd);
return -1;
}
iRtn = lseek(iFd, sizeof(BITMAPFILEHEADER), SEEK_SET);
if(iRtn != sizeof(BITMAPFILEHEADER) )
{
printf("읽어들일 부분이 잘못 지정되었습니다.\n");
close(iFd);
return -1;
}
iRtn = read(iFd, &stBIHead, sizeof(BITMAPINFOHEADER));
if(iRtn == 0)
{
printf("INFO헤더가 존재하지 않습니다.\n");
close(iFd);
return -1;
}
ucpBuf = (void *)malloc(stBIHead.biSizeImage);
if(0 == ucpBuf)
{
printf("사용 가능한 메모리가 부족합니다.\n");
close(iFd);
return -1;
}
lseek(iFd, sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER), SEEK_SET);
iRtn = read(iFd, ucpBuf, stBIHead.biSizeImage);
if(iRtn == 0)
{
printf("데이터를 읽을 수 없습니다.\n");
close(iFd);
free(ucpBuf);
return -1;
}
for(uiCntY=0; uiCntY < stBIHead.biHeight; ++uiCntY)
{
for(uiCntX=0; uiCntX < stBIHead.biWidth; ++uiCntX)
{
ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 0] = 0; //blue
ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 1] = 0; //green
ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 2] = 0xFF; //red
}
}
lseek(iFd, 54, SEEK_SET);
iRtn = write(iFd, ucpBuf, stBIHead.biSizeImage);
if(iRtn == 0)
{
printf("데이터 쓰기에 실패 했습니다.\n");
close(iFd);
free(ucpBuf);
return -1;
}
lseek(iFd, 54, SEEK_SET);
iRtn = read(iFd, cBuf, 16*16);
close(iFd);
free(ucpBuf);
return 0;
}
'Busan IT > 영상처리' 카테고리의 다른 글
BMP파일 가로 크기 패딩 처리, 컬러 BMP파일 회색 변환, 명암 증가 (0) | 2015.11.09 |
---|---|
비트맵 파일 규격 규칙 (0) | 2015.11.06 |