본문 바로가기
프로그래밍/MFC

Raw to BMP 설명

by 완소루피 2020. 11. 12.
728x90
반응형

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;
}

 

728x90
반응형

'프로그래밍 > MFC' 카테고리의 다른 글

영상처리 - 미디언 필터  (0) 2020.11.13
Raw to BMP 저장  (0) 2020.11.13
GDI+ 기반 BMP to JPG  (0) 2020.11.12
BMP 저장  (0) 2020.11.12
Socket Error Code  (0) 2020.11.12