用C语言解析BMP文件的结构

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值