bmp文件的结构比较简单,主要包括文件头,BMP信息头,BMP数据内容。文件头BITMAPFILEHEADER结构为:
Windows GDI提供了
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
BMP信息头BITMAPINFO结构为:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO, FAR *LPBITMAPINFO, *PBITMAPINFO;
typedef struct tagBITMAPCOREINFO {
BITMAPCOREHEADER bmciHeader;
RGBTRIPLE bmciColors[1];
} BITMAPCOREINFO, FAR *LPBITMAPCOREINFO, *PBITMAPCOREINFO;
#include <pshpack2.h>
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
有一次,一个朋友给了一套BMP文字的图片,想把BMP转化为字库,需要去掉BMP的头和BMP信息,只取数据部分,并存为数组,就根据BMP结构,写了如下一个小程序,主要包括文件读写,文件查找等:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <windows.h>
BITMAPFILEHEADER file_head;
BITMAPINFO fileinfo;
//把彩色的图转为黑白色,输入源文件名字和转出的文件名字
#define FONT_WIDTH_1 (28)
#define FONT_WIDTH_2 (22)
char * getfilename(char * filename)
{
char strResult[128]={0}; //保存结果
char *temp, *ret;
temp = filename;
int nStrLen = strlen(filename); //原始字符串长度
for(int i = nStrLen; i > 0; i--) //倒查,每个字符和反斜杠对比
{
if (filename[i] == '//') //如果当前字符是反斜杠
{
//复制倒数第一个斜杠后的数据,并去掉.bmp
strncpy(strResult, (char *)(temp+i+1), nStrLen-i-1-4);
break;
}
else
{
//复制字符串,去掉.bmp
if (i = 1)
{
strncpy(strResult, (char *)temp, nStrLen-4);
break;
}
}
}
ret = strResult;
return (ret);
}
#if 1
char * getfilepath(char * filename)
{
char strResult[128] = {0}; //保存结果
char *temp, *ret;
temp = filename;
int nStrLen = strlen(filename); //原始字符串长度
for(int i = nStrLen; i > 0; i--) //倒查,每个字符和斜杠对比
{
if (filename[i] == '//') //如果当前字符是斜杠
{
//复制路径,包括斜杠
strncpy(strResult, (char *)temp, i+1);
break;
}
}
ret = strResult;
return (ret);
}
#endif
int colorbmp2bwbmp(char * f_in, char * f_out)
{
int infileLen; //文件长度
int n=0; //n 字节计数器
unsigned char c,c_in; //C_in文件字节,C转化
FILE *fh_in;
FILE *fh_out;
assert((f_in != NULL) && (f_out != NULL));
fh_in=fopen(f_in,"rb");
if (NULL==fh_in)
{
printf("open read file error!!");
return 1;
}
fseek(fh_in,0,SEEK_END);
infileLen=ftell(fh_in);
fseek(fh_in,0,SEEK_SET);
/*read bmp file head,14 BYTE*/
if (sizeof(file_head)!=fread(&file_head,1,sizeof(file_head),fh_in))
{
printf("read bmp file error!!");
fclose(fh_in);
return 1;
}
/*判断是不是BMP文件*/
if (file_head.bfType!=0x4d42)
{
printf("bmp file error!!");
fclose(fh_in);
return 1;
}
/*文件指针移到文件开始处*/
fseek(fh_in,0,SEEK_SET);
fh_out=fopen(f_out,"wb");
if (NULL==fh_out)
{
printf("open write file error!!");
return 1;
}
/*把文件头读入目标文件*/
while((int)file_head.bfOffBits--)
{
c_in=getc(fh_in);
c=c_in;
putc(c,fh_out);
}
/*转为黑白片*/
while (n<(infileLen-(int)file_head.bfOffBits))
{
c_in=getc(fh_in);
c=c_in;
if (c>0x7f)
{
c =0xff;
}
else
{
c = 0x00;
}
putc(c,fh_out);
n++;
}
fclose(fh_in);
fclose(fh_out);
return 0;
}
//byte转为BIT
void ByteToBit(char *Out, const char *In, unsigned char bits)
{
unsigned char i;
for(i=0; i<bits; i++)
{
Out[i] = (In[i/8]>>(i%8)) & 1;
}
}
//BIT转为byte
void BitToByte(char * Out, const char *In, unsigned bits)
{
unsigned char i;
memset(Out, 0, (bits+7)/8);
for(i=0; i<bits; i++)
{
Out[i/8] |= In[i]<<(i%8);
}
}
//把位图转为文件,输入bmp文件名和头文件名
int bmp2headfile(char * bmpfile, char * headfile)
{
int infileLen; //文件长度
int n=0,num=1; //n 字节计数器, NUM换行指示
unsigned char c, c_in; //C_in文件字节,C转化
FILE *fh_in;
FILE *fh_out;
char com[256]={0};
char ch[2]={0};
long wid, hig;
assert((bmpfile != NULL) && (headfile != NULL));
fh_in=fopen(bmpfile,"rb");
if (NULL==fh_in)
{
printf("open read file error!!");
return 1;
}
fseek(fh_in,0,SEEK_END);
infileLen=ftell(fh_in);
fseek(fh_in,0,SEEK_SET);
/*读取BMP文件头*/
if (sizeof(file_head)!=fread(&file_head,1,sizeof(file_head),fh_in))
{
printf("read bmp file error!!");
fclose(fh_in);
return 1;
}
/*读取BMP文件信息*/
if (sizeof(fileinfo)!=fread(&fileinfo,1,sizeof(fileinfo),fh_in))
{
printf("read bmp file error!!");
fclose(fh_in);
return 1;
}
/*判断是不是BMP图片*/
if (file_head.bfType!=0x4d42)
{
printf("bmp file error!!");
fclose(fh_in);
return 1;
}
fseek(fh_in,file_head.bfOffBits,SEEK_SET);
fh_out=fopen(headfile,"ab");
if (NULL==fh_out)
{
printf("open write file error!!");
return 1;
}
/*写入注释*/
memcpy(ch, getfilename(bmpfile), sizeof(getfilename(bmpfile)));
wid = fileinfo.bmiHeader.biWidth;
hig = fileinfo.bmiHeader.biHeight;
sprintf(com, "/*The size is :%dX%d. The char is : %s.*/", wid, hig, ch);
fputs(com, fh_out);
putc(0x0d,fh_out);
putc('/n',fh_out);
/*写入数据*/
while (n<(infileLen-(int)file_head.bfOffBits))
{
putc('0',fh_out);
putc('X',fh_out);
c_in=getc(fh_in);
c=c_in;
c=(c>>4)&0x0f; //获取高四个BIT的内容
if (c<0x0a)
{
c+=0x30; //把符号转成数字
}
else
{
c+=0x37; //转成a到f
}
putc(c,fh_out);
c=c_in&0x0f; //获取低四个BIT内容
if (c<0x0a)
{
c+=0x30;
}
else
{
c+=0x37;
}
putc(c,fh_out);
putc(',',fh_out);
n++;
if (num++ % (fileinfo.bmiHeader.biWidth/8 + 1) ==0)
{
putc(0x0d,fh_out);
putc('/n',fh_out);
}
}
putc(0x0d,fh_out);
putc('/n',fh_out);
fclose(fh_in);
fclose(fh_out);
return 0;
}
int main(int argc, char* argv[])
{
WIN32_FIND_DATA fd;
if (argc>2)
{
printf("***************位图帮助***************/n");
printf("bmptofile [drive:][path][filename]");
return 1;
}
else if (argc == 2)
{
if (strchr(argv[1], '.')!=NULL)
{
bmp2headfile(argv[1], (char *)"font.h");
}
else //if (memcmp(argv[1], "/?", sizeof(argv[1])) == 0)
{
printf("***************位图帮助***************/n");
printf("bmptofile [drive:][path][filename]");
return 1;
}
}
else if (argc == 1)
{
HANDLE hd=::FindFirstFile((LPCTSTR)"*.bmp",&fd); //开始查找
if(hd==INVALID_HANDLE_VALUE)
{
printf("没有找到文件");
return 0;
}
bmp2headfile(fd.cFileName, (char *)"font.h");
while(FindNextFile(hd,&fd)) //继续查找
{
bmp2headfile(fd.cFileName, (char *)"font.h");
}
FindClose(hd);//关闭查找
}
return 0;
}