1. 程式人生 > >基於C語言的BMP檔案格式轉換

基於C語言的BMP檔案格式轉換

//將bmp圖片檔案保存於1.bmp中,若圖片是bmp檔案,則在out.bmp檔案中可以看到,若不是,則在out.bmp中顯示開啟失敗。
//識別乒乓球
#include<stdio.h>
#include<stdlib.h>


//此bmp檔案影象深度要求24bit
#define BM 19778  //BM對應的asc碼0x4d42轉為10進位制
#define BITMAPFILEHEADERLENGTH 14  // The bmp FileHeader length is 14
void BmpFILEtest(FILE* fpbmp);//測試是否為bmp檔案 
void BmpHeaderPartLength(FILE* fpbmp);//獲得從點陣圖頭到點陣圖詳細資料部分的offset
void BmpWidthHeight(FILE* fpbmp);//獲得bmp檔案的寬度和高度資訊 
void BmpDataPart(FILE* fpbmp);//獲得調色盤的rgb資料
void Bmpoutput(FILE *fpout);//輸出與txt檔案相符的bmp影象


unsigned int offset=0;//offset定義為資料的起始地址
long width;
long height;
unsigned char r[2000][2000],output_r[2000][2000];
unsigned char g[2000][2000],output_g[2000][2000];
unsigned char b[2000][2000],output_b[2000][2000];
unsigned char num=0;






int main()
{
unsigned char *fp_temp;
FILE *fpbmp;
FILE *fpout;


fpbmp=fopen("1.bmp","rb");  //開啟1.bmp檔案


if(fpbmp==NULL)
{
printf("開啟bmp檔案失敗!!!\n");
return 1;
}
if((fpout=fopen("out.bmp","wb"))==NULL)
{
printf("開啟out.bmp檔案失敗!!!\n");
return 1;
}
BmpFILEtest(fpbmp); //測試是否為bmp檔案
BmpHeaderPartLength(fpbmp);//得到bmp檔案的首地址區
BmpWidthHeight(fpbmp);//得到bmp檔案的高度和寬度

fseek(fpbmp,0L,SEEK_SET);
fseek(fpout,0L,SEEK_SET);


fp_temp=(unsigned char*)malloc(offset*sizeof(unsigned char));
fread(fp_temp,1,offset,fpbmp);
fwrite(fp_temp,1,offset,fpout);


BmpDataPart(fpbmp);//將資料儲存在檔案中
/*
//對圖片進行處理


  */


Bmpoutput(fpout);//轉化為bmp檔案


fclose(fpbmp);
fclose(fpout);  //關閉檔案

printf("圖片中乒乓球的個數為%d個。\n",num+1);
return 0;



 } 
 
void BmpFILEtest(FILE* fpbmp)   
{
unsigned short bftybe=0;
fseek(fpbmp,0L,SEEK_SET);  //fseek將位置指標移到指定位置(檔案起始) 
fread(&bftybe,sizeof(char),2,fpbmp);//讀取fpbmp檔案中的前兩個位元組到bftybe中
if(BM!=bftybe)
{
printf("This file is not bmp file!!!\n");
exit(1);
}
}


void BmpHeaderPartLength(FILE* fpbmp)
{
fseek(fpbmp,10L,SEEK_SET);
fread(&offset,sizeof(char),4,fpbmp);
printf("The header part is of length %d.\n",offset);

}


void BmpWidthHeight(FILE* fpbmp)
{
fseek(fpbmp,18L,SEEK_SET);
fread(&width,sizeof(char),4,fpbmp);
fseek(fpbmp,22L,SEEK_SET);
fread(&height,sizeof(char),4,fpbmp);
printf("The width of the bmp file is %ld.\n",width);
printf("The height of the bmp file is %ld.\n",height);
}


void BmpDataPart(FILE* fpbmp)
{
int i,j=0;
int stride;//儲存影象資料每行的位元組個數
unsigned char *pix=NULL; //儲存畫素到pix中
FILE *fpr;
FILE *fpg;
FILE *fpb;
if((fpr=fopen("bmpr.txt","w+"))==NULL)
{
printf("Failed to construct file bmpr.txt");
exit(1);
}
if((fpg=fopen("bmpg.txt","w+"))==NULL)
{
printf("Failed to construct file bmpg.txt");
exit(1);
}
if((fpb=fopen("bmpb.txt","w+"))==NULL)
{
printf("Failed to construct file bmpb.txt");
exit(1);
}
fseek(fpbmp,offset,SEEK_SET);
stride=(24*width+31)/8;
stride=stride/4*4;
pix=(unsigned char*)malloc(stride*sizeof(unsigned char));  //動態分配畫素大小 


for(j=0;j<height;j++)  
{
fread(pix,1,stride,fpbmp);//讀取fpbmp中的stride個數據,每個資料讀一個位元組,到pix中
for(i=0;i<width;i++)
{
r[height-1-j][i]=pix[i*3+2];
g[height-1-j][i]=pix[i*3+1];
b[height-1-j][i]=pix[i*3];  //順序為b g r,從下到上,從左到右掃描

output_r[height-1-j][i]=pix[i*3+2];
output_g[height-1-j][i]=pix[i*3+1];
output_b[height-1-j][i]=pix[i*3];


}
}


for(i=0;i<height;i++)
{
for(j=0;j<width-1;j++)
{
fprintf(fpb,"%4d",b[i][j]);
fprintf(fpg,"%4d",g[i][j]);
fprintf(fpr,"%4d",r[i][j]);
}
}


fclose(fpr);
fclose(fpg);
fclose(fpb);


}


void Bmpoutput(FILE* fpout)
{
int i,j;
int stride;
unsigned char* pixout=NULL;


stride=(24*width+31)/8;
stride=stride/4*4;
pixout=(unsigned char*)malloc(stride*sizeof(unsigned char));


fseek(fpout,offset,SEEK_SET);


for(j=0;j<height;j++)
{
for(i=0;i<width;i++)
{
//通過RGB值判斷是否為黃色,如果不是則將其變為黑色,
//if((output_b[height-1-j][i]<=100)&&(output_g[height-1-j][i]>=100)&&(output_g[height-1-j][i]<=200)&&(output_r[height-1-j][i]>200))
//{
//}
//else
//{
//output_b[height-1-j][i]=0;
//output_g[height-1-j][i]=0;
//output_r[height-1-j][i]=0;
//}
pixout[i*3+2]=output_r[height-1-j][i];
pixout[i*3+1]=output_g[height-1-j][i];
pixout[i*3]  =output_b[height-1-j][i];
}
fwrite(pixout,1,stride,fpout);
}


}