C 언어로 BMP 포맷 이미지 읽기 및 쓰기 가능

6104 단어 도형 영상 학습
하루 동안의 실천을 통해 마침내 알아낸 BMP 그림의 격식과 그림 정보를 정확하게 읽고 새로운 BMP 그림을 생성하는 것을 완성하였다.
프로그램을 쓰기 전에 먼저 몇 가지 지식을 알아야 한다.
      1. BMP 그림의 파일 헤더, 정보 헤더는 모두 54바이트로 구체적인 구조와 의미는 프로그램에 상세한 설명이 있다.
      2. BMP는 픽셀당 색상이 차지하는 비트 수로 1비트(2색), 4비트(16색), 8비트(256색), 24비트(진채색), 32비트(투명도 정보 포함) 등 총 5가지로 24비트와 32비트를 제외하고 모두 팔레트를 사용해야 한다.
      3. BMP의 이미지 데이터는 줄마다 32비트로 정렬되고 32비트가 부족하면 0으로 보충하기 때문에 줄마다 실제 길이는 (픽셀 너비*픽셀은bit수+31)/32비트이다.
상세한 프로그램을 첨부하여 bmp 이미지 정보를 읽고 bmp 이미지를 다시 생성하는 기능을 실현하였으며, 동시에 각 픽셀의 RGB 세 개의 분량 값을 각각 추출하여 각각 세 개의 파일에 저장하였다.
#include
#include
typedef unsigned short int WORD;  
typedef unsigned int DWORD;  
typedef unsigned char BYTE; 

typedef struct tagBITMAPFILEHEADER
{
	WORD	bfType;			//       ,   ‘BM’(0-1  )
	DWORD	bfSize;			//       ,      (2-5  )
	WORD	bfReserved1;	//        ,   0(6-7  )
	WORD	bfReserved2;	//        ,   0(8-9  )
	DWORD	bfOffBits;		//          (10-13  )
}BITMAPFILEHEAEDER;

typedef struct tagBITMAPINFOHEADER
{
	DWORD	biSize;			//            (14-17  )
	DWORD	biWidth;		//      ,      (18-21  )
	DWORD	biHeight;		//      ,      (22-25  )
	WORD	biPlanes;		//        ,   1(26-27  )
	WORD	biBitCount;		// 1(  ),4(16 ),8(256 ),24(   )(28-29  )
	DWORD	biCompression;	//       :0(   ),1(BI_RLES8),2(BI_RLE4)(30-33  )
	DWORD	biSizeImage;	//      ,      (34-37  )
	DWORD	biXPelsPerMeter;//        ,     (38-41  )
	DWORD	biYPelsPerMeter;//        ,     (42-45  )
	DWORD	biClrUsed;		//           ,0      (46-49  )
	DWORD	biClrImportant;	//             (50-53  )
}BITMAPINFOHEADER;

typedef struct taRGBQUAD
{
	BYTE rgbBlue;
	BYTE rgbGreen;
	BYTE rgbRed;
	BYTE rgbReserved;		//    ,   0
}RGBQUAD;

int main(int argc, char** argv)
{
	FILE *result_r;			//         ,            
	FILE *result_g;
	FILE *result_b;
	FILE *bmp;				//   bmp  
	FILE *copy;				//       bmp  
	long real_w;
	long offset = 0;

	BITMAPFILEHEAEDER header;
	BITMAPINFOHEADER info;

	//             ,     
	if(!(bmp = fopen("oral.bmp", "rb")))
	{
		printf("the file bmp isn't exist.
"); exit(0); } if(!(copy = fopen("copy.bmp", "wb"))) { printf("create new file failed.
"); exit(0); } // fread(&header, 14, 1, bmp); fwrite(&header, 14, 1, copy); fread(&info, 40, 1, bmp); fwrite(&info, 40, 1, copy); // bmp , , printf("width: %d, height: %d
", info.biWidth, info.biHeight); printf("size of pixel: %d
", info.biBitCount); printf("type of compression: %d
", info.biCompression); printf("count of colors: %d
", info.biClrUsed); result_r = fopen("red", "wb"); result_g = fopen("green", "wb"); result_b = fopen("blue", "wb"); // bmp 32 , 32 ,real_w // offset 32 , real_w = (info.biWidth * info.biBitCount + 31) / 32 * 4; offset = real_w - (info.biWidth * info.biBitCount + 7) / 8; char *w = (char*)malloc(offset); printf("offset: %d
", offset); if(info.biBitCount == 24 || info.biBitCount == 32) // { int i = 0, j; for(; i < info.biHeight; i++) { j = 0; for(; j < info.biWidth; j++) { RGBQUAD rgb; char string[16]; fread(&rgb.rgbBlue, 1, 1, bmp); fwrite(&rgb.rgbBlue, 1, 1, copy); fread(&rgb.rgbGreen, 1, 1, bmp); fwrite(&rgb.rgbGreen, 1, 1, copy); fread(&rgb.rgbRed, 1, 1, bmp); fwrite(&rgb.rgbRed, 1, 1, copy); if(info.biBitCount == 32) { fread(&rgb.rgbReserved, 1, 1, bmp); fwrite(&rgb.rgbReserved, 1, 1, copy); } sprintf(string, "%d ", rgb.rgbRed); fputs(string, result_r); sprintf(string, "%d ", rgb.rgbGreen); fputs(string, result_g); sprintf(string, "%d ", rgb.rgbBlue); fputs(string, result_b); } if(offset && j != info.biWidth-1) { //fseek(bmp, offset, SEEK_CUR); fread(w, offset, 1, bmp); fwrite(w, offset, 1, copy); } fputs("
", result_r); fputs("
", result_g); fputs("
", result_b); } free(w); } else // { int i = 0; int index = 0; int biClrUsed; RGBQUAD *clTable; // biClrUsed = 1 << info.biBitCount;// 2^info.biBitCount clTable = (RGBQUAD*)malloc(biClrUsed*sizeof(RGBQUAD)); for(; i < biClrUsed; i++) // /// { fread(&clTable[i], 4, 1, bmp); fwrite(&clTable[i], 4, 1, copy); clTable[i].rgbReserved = 0; } i = 0; for(; i < info.biHeight; i++) { int j = 0; WORD tmp; // for(; j < info.biWidth; j++) { RGBQUAD rgb; char string[16]; if(info.biBitCount == 8) // 8 , { fread(&tmp, 1, 1, bmp); fwrite(&tmp, 1, 1, copy); index = tmp; } else if(info.biBitCount == 4) // 4 , { if(j%2) index = tmp&0xF; // else { fread(&tmp, 1, 1, bmp); fwrite(&tmp, 1, 1, copy); index = tmp>>4; // } } else if(info.biBitCount == 1) // 1 , 8 { int joffset = j % 8; if(!joffset) { fread(&tmp, 1, 1, bmp); fwrite(&tmp, 1, 1, copy); } index = (tmp>>(7-joffset))&0x1; // , , } rgb = clTable[index]; sprintf(string, "%d ", rgb.rgbRed); fputs(string, result_r); sprintf(string, "%d ", rgb.rgbGreen); fputs(string, result_g); sprintf(string, "%d ", rgb.rgbBlue); fputs(string, result_b); } if(offset) { int i = 0; fseek(bmp, offset, SEEK_CUR); for(; i < offset; i++) { WORD zero = 0; fwrite(&zero, 1, 1, copy); } } fputs("
", result_r); fputs("
", result_g); fputs("
", result_b); } free(clTable); } fclose(result_r); fclose(result_g); fclose(result_b); fclose(bmp); fclose(copy); printf(" 。
"); return 0; }

좋은 웹페이지 즐겨찾기