RAW file, BMP file
- BMP: bit map
- RAW파일과 BMP파일의 비교
BMP
- 장치 독립성
1. DDB(device dependant bitmap) 한 픽셀이 몇 비트로 표현될 것인지가 화면설정에 종속
2. DIB(device independant bitmap) 화면설정과는 관계없이 영상파일 자체의 정보로써 표현
- Color 표현
1. True color mode : RGB 각각 8비트
2. Index mode :Color table(palette) 사용
3. 흑백영상
BMP format
파일 헤드의 구조체
Typedef struct tagBITMAPFILEHEADER
{
WORD bfType; // ”BM”이라는 값을 저장
DWORD bfSize; // Byte단위의 전체파일 크기
WORD bfReserved1; // 예약된 변수
WORD bfReserved1; // 예약된 변수
DWORD bfOffBits; // 영상 데이터까지의 거리
} BITMAPFILEHEADER;
영상 헤드의 구조체
Typedef struct tagBITMAPINFOHEADER
{
DWORD biSize; // 구조체의 크기
LONG biWidth; // 픽셀 단위의 영상 폭
LONG biHeight; // 영상의 높이
WORD biPlanes; // 비트 플레인 수(항상 1)
WORD biBitCount; // 픽셀당 비트 수
DWORD biCompression; // 압축 여부
DWORD biSizeImage; // 영상의 크기(바이트 단위)
LONG biXPelsPerMeter; // 가로 해상도
LONG biYPelsPerMeter; // 세로 해상도
DWORD biClrUsed; // 실제 사용 색상 수
DWORD biClrImportant; // 중요한 색상 인덱스
} BITMAPINFOHEADER;
Palette의 구조체
Typedef struct tagRGBQUAD
{
BYTE rgbBlue; // 파란색
BYTE rgbGreen; // 녹색
BYTE rgbRed; // 빨강색
BYTE rgbReserved; // 예약된 변수
} RGBQUAD;
RGBQUAD hRGB[256];
이미지 반전
for (i=0; i<biHeight; i++) {
for (j=0; j<biWidth; j++) {
GrayImg[i*biWidth+j] = lpMem[(biHeight-i-1)*rwsize+j];
}
}
- 가로 줄의 길이는 항상 4Byte의 배수가 되어야 함
#define WIDTHBYTES(bits) (((bits)+31)/32*4) // 4Byte 배수로 변환
rwsize = WIDTHBYTES(biBitCount*biWidth); // 호출시
흑백 BMP 영상 입출력 프로그램
#include <stdio.h>
#include <window.h>
#define WIDTHBYTES(bits) (((bits)+31)/32*4)
#define BYTE unsigned char
void main ( )
{
// 입력 파일 오픈
FILE *infile = fopen(“Lenna.bmp", "rb");
if (infile==NULL) {printf("영상파일 없음!"); return;}
// 정보 헤드 변수 선언
BITMAPFILEHEADER hf;
BITMAPINFOHEADER hInfo;
// 파일 정보 헤드 읽음
fread(&hf, sizeof(BITMAPFILEHEADER), 1, infile);
if (hf.bfType!=0x4D42) exit(1); // 0x4D42는 ‘BM’
// 영상 정보 헤드 읽음
fread(&hInfo, sizeof(BITMAPINFOHEADER), 1, infile);
if (hInfo.biBitCount!=8) {printf(“Bad file format!"); return;}
// 팔레트 정보 입력
RGBQUAD hRGB[256];
fread(hRGB, sizeof(RGBQUAD), 256, infile);
// 메모리 할당
BYTE *lpImg = new BYTE[hInfo.biSizeImg];
fread(lpImg, sizeof(char), hInfo.biSizeImage, infile);
fclose(infile);
int rwsize = WIDTHBYTES(hInfo.bitBitCount*hInfo.biWidth);
// 역상 이미지 구하기
for (int i=0; i<hInfo.biHeight; i++) {
for (int j=0; j<hInfo.biWidth; j++)
lpImg[i*rwsize+j] = 255- lpImg[i*rwsize+j];
}
// 영상 출력 파일 오픈
FILE *outfile = fopen(“out.bmp", “wb");
// 파일 헤드 출력
fwrite(&hf, sizeof(BITMAPFILEHEADER), 1, outfile);
// 영상 헤드 출력
fwrite(&hInfo, sizeof(BITMAPINFOHEADER), 1, outfile);
// 팔레트 출력
fwrite(hRGB, sizeof(RGBQUAD), 256, outfile);
// 영상 데이터 출력
fwrite(lpImg, sizeof(char), hInfo.biSizeImage, outfile);
// 출력 파일 닫음
fclose(outfile);
// 메모리 해제
delete [ ] IpImg;
}
Color BMP 영상 입출력 프로그램
#include <stdio.h>
#include <window.h>
#define WIDTHBYTES(bits) (((bits)+31)/32*4)
#define BYTE unsigned char
void main ( )
{
FILE *infile = fopen(“pshop256l.bmp", "rb");
if (infile==NULL) {printf("영상파일 없음!"); return;}
BITMAPFILEHEADER hf;
fread(&hf, sizeof(BITMAPFILEHEADER), 1, infile);
if (hf.bfType!=0x4D42) exit(1); // 0x4D42는 ‘BM’
BITMAPINFOHEADER hInfo;
fread(&hInfo, sizeof(BITMAPINFOHEADER), 1, infile);
// 256 color 미만은 취급하지 않음
if (hInfo.biBitCount<8) {printf(“Bad file format!”); return;}
RGBQUAD *pRGB;
if (hInfo.biClrUsed!=0) { // 팔레트 사용
pRGB = new RGBQUAD[hInfo.biClrUsed];
fread(pRGB, sizeof(RGBQUAD), hInfo.biClrUsed, infile);
}
// 영상 데이터를 저장할 메모리 할당
BYTE *lpImg = new BYTE[hInfo.biSizeImage];
fread(lpImg, sizeof(char), hInfo.biSizeImage, infile);
fclose(infile);
// 크기 계산, 메모리 할당
int rwsize = WIDTHBYTES(hInfo.biBitCount*hInfo.biWidth);
int rwsize2= WIDTHBYTES(24*hInfo.biWidth); // true color
BYTE *lpOutImg = new BYTE [3*rwsize*hInfo.biHeight];
int index, R, G, B, i, j;
if(hInfo.biBitCount==24) // 입력영상이 트루(24비트) 칼라인 경우
for(i=0; i<hInfo.biHeight; i++) {
for(j=0; j<hInfo.biWidth; j++) {
lpOutImg[i*rwsize2+3*j+2] = 255-lpImg[i*rwsize+3*j+2];
lpOutImg[i*rwsize2+3*j+1] = 255-lpImg[i*rwsize+3*j+1];
lpOutImg[i*rwsize2+3*j] = 255-lpImg[i*rwsize+3*j];
}
}
else // 트루칼라가 아닌 경우
for(i=0; i<hInfo.biHeight; i++) {
for(j=0; j<hInfo.biWidth; j++) {
index = lpImg[i*rwsize+j]; // 영상데이타는 팔레트의 인덱스
R = pRGB[index].rgbRed; // 팔레트의 데이터(R)
G = pRGB[index].rgbGreen; // 팔레트의 데이터(G)
B = pRGB[index].rgbBlue; // 팔레트의 데이터(B)
R = 255-R; G = 255-G; B = 255-B; // 역상 계산
lpOutImg[i*rwsize2+3*j+2] = (BYTE)R;
lpOutImg[i*rwsize2+3*j+1] = (BYTE)G;
lpOutImg[i*rwsize2+3*j] = (BYTE)B;
}
}
// 영상 출력 (24비트인 트루칼라로 출력)
hInfo.biBitCount = 24;
hInfo.biSizeImage = 3*rwsize*hInfo.biHeight;
hInfo.biClrUsed = hInfo.biClrImportant = 0;
hf.bfOffBits = 54; // 팔레트가 없으므로 값이 변함
hf.bfSize = hf.bfOffBits+hInfo.biSizeImage;
FILE *outfile = fopen("OutImg24.bmp","wb");
fwrite(&hf,sizeof(char),sizeof(BITMAPFILEHEADER),outfile);
fwrite(&hInfo,sizeof(char),sizeof(BITMAPINFOHEADER),outfile);
fwrite(lpOutImg,sizeof(char),3*rwsize*hInfo.biHeight,outfile);
fclose(outfile);
// 메모리 해제
if(hInfo.biClrUsed!=0) delete [] pRGB;
delete [] lpOutImg;
delete [] lpImg;
}