C 언어로 BMP 포맷 이미지 읽기 및 쓰기 가능
6104 단어 도형 영상 학습
프로그램을 쓰기 전에 먼저 몇 가지 지식을 알아야 한다.
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;
}