天天看点

C语言编写的bmp读写程序

C语言编写的bmp读写程序 建议先把bmp的数据存储格式了解下 

<span style="font-size:16px;">#include "Windows.h"  

#include "stdio.h"  

#include "string.h"  

#include "malloc.h"  

unsigned char *pBmpBuf;//读入图像数据的指针  

int bmpWidth;//图像的宽  

int bmpHeight;//图像的高  

RGBQUAD *pColorTable;//颜色表指针  

int biBitCount;//图像类型,每像素位数  

bool readBmp(char *bmpName)  

{  

  //二进制读方式打开指定的图像文件  

  FILE *fp=fopen(bmpName,"rb");  

  if(fp==0) return 0;  

  //跳过位图文件头结构BITMAPFILEHEADER  

  fseek(fp, sizeof(BITMAPFILEHEADER),0);  

  //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中  

  BITMAPINFOHEADER head;     

  fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);    

  //获取图像宽、高、每像素所占位数等信息  

  bmpWidth = head.biWidth;  

  bmpHeight = head.biHeight;  

  biBitCount = head.biBitCount;  

  //定义变量,计算图像每行像素所占的字节数(必须是4的倍数)  

  int lineByte=(bmpWidth * biBitCount/8+3)/4*4;  

  //灰度图像有颜色表,且颜色表表项为256  

  if(biBitCount==8){  

  //申请颜色表所需要的空间,读颜色表进内存  

  pColorTable=new RGBQUAD[256];  

  fread(pColorTable,sizeof(RGBQUAD),256,fp);  

  }  

  //申请位图数据所需要的空间,读位图数据进内存  

  pBmpBuf=new unsigned char[lineByte * bmpHeight];  

  fread(pBmpBuf,1,lineByte * bmpHeight,fp);  

  //关闭文件  

  fclose(fp);  

  return 1;  

}  

bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height,    

  int biBitCount, RGBQUAD *pColorTable)  

  //如果位图数据指针为0,则没有数据传入,函数返回  

  if(!imgBuf)  

  return 0;  

  //颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0  

  int colorTablesize=0;  

  if(biBitCount==8)  

  colorTablesize=1024;  

  //待存储图像数据每行字节数为4的倍数  

  int lineByte=(width * biBitCount/8+3)/4*4;  

  //以二进制写的方式打开文件  

  FILE *fp=fopen(bmpName,"wb");  

  //申请位图文件头结构变量,填写文件头信息  

  BITMAPFILEHEADER fileHead;  

  fileHead.bfType = 0x4D42;//bmp类型  

  //bfSize是图像文件4个组成部分之和  

  fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)  

  + colorTablesize + lineByte*height;  

  fileHead.bfReserved1 = 0;  

  fileHead.bfReserved2 = 0;  

  //bfOffBits是图像文件前3个部分所需空间之和  

  fileHead.bfOffBits=54+colorTablesize;  

  //写文件头进文件  

  fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);  

  //申请位图信息头结构变量,填写信息头信息  

  BITMAPINFOHEADER head;    

  head.biBitCount=biBitCount;  

  head.biClrImportant=0;  

  head.biClrUsed=0;  

  head.biCompression=0;  

  head.biHeight=height;  

  head.biPlanes=1;  

  head.biSize=40;  

  head.biSizeImage=lineByte*height;  

  head.biWidth=width;  

  head.biXPelsPerMeter=0;  

  head.biYPelsPerMeter=0;  

  //写位图信息头进内存  

  fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);  

  //如果灰度图像,有颜色表,写入文件    

  fwrite(pColorTable, sizeof(RGBQUAD),256, fp);  

  //写位图数据进文件  

  fwrite(imgBuf, height*lineByte, 1, fp);  

void main()  

  char inFileName[90],outFileName[90];  

printf("请输入原始位图文件的文件名:");  

  scanf("%s",inFileName);  

  printf("请输入加密程序产生的新位图文件的文件名:");  

  scanf("%s",outFileName);  

//读入指定BMP文件进内存  

  readBmp(inFileName);  

  //输出图像的信息  

  printf("width=%d,height=%d, biBitCount=%d\n",bmpWidth,bmpHeight, biBitCount);  

  //将图像数据存盘  

  saveBmp(outFileName, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);  

  //清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间  

  delete []pBmpBuf;  

  delete []pColorTable;  

</span>  

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

一、BMP文件结构 

BMP文件组成 

BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。   

BMP文件头 

BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。   

其结构定义如下: 

typedef   struct   tagBITMAPFILEHEADER 

WORDbfType;   //   位图文件的类型,必须为BM 

DWORD   bfSize;   //   位图文件的大小,以字节为单位   

WORDbfReserved1;   //   位图文件保留字,必须为0 

WORDbfReserved2;   //   位图文件保留字,必须为0 

DWORD   bfOffBits;   //   位图数据的起始位置,以相对于位图 

//   文件头的偏移量表示,以字节为单位 

}   BITMAPFILEHEADER; 

3.   位图信息头 

BMP位图信息头数据用于说明位图的尺寸等信息。 

typedef   struct   tagBITMAPINFOHEADER{ 

DWORD   biSize;   //   本结构所占用字节数 

LONGbiWidth;   //   位图的宽度,以像素为单位 

LONGbiHeight;   //   位图的高度,以像素为单位 

WORD   biPlanes;   //   目标设备的级别,必须为1 

WORD   biBitCount//   每个像素所需的位数,必须是1(双色), 

//   4(16色),8(256色)或24(真彩色)之一 

DWORD   biCompression;   //   位图压缩类型,必须是   0(不压缩), 

//   1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 

DWORD   biSizeImage;   //   位图的大小,以字节为单位 

LONGbiXPelsPerMeter;   //   位图水平分辨率,每米像素数 

LONGbiYPelsPerMeter;   //   位图垂直分辨率,每米像素数 

DWORD   biClrUsed;//   位图实际使用的颜色表中的颜色数 

DWORD   biClrImportant;//   位图显示过程中重要的颜色数 

}   BITMAPINFOHEADER; 

4.   颜色表 

  颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下: 

typedef   struct   tagRGBQUAD   { 

BYTErgbBlue;//   蓝色的亮度(值范围为0-255) 

BYTErgbGreen;   //   绿色的亮度(值范围为0-255) 

BYTErgbRed;   //   红色的亮度(值范围为0-255) 

BYTErgbReserved;//   保留,必须为0 

}   RGBQUAD; 

颜色表中RGBQUAD结构数据的个数有biBitCount来确定: 

当biBitCount=1,4,8时,分别有2,16,256个表项; 

当biBitCount=24时,没有颜色表项。 

位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下: 

typedef   struct   tagBITMAPINFO   { 

BITMAPINFOHEADER   bmiHeader;   //   位图信息头 

RGBQUAD   bmiColors[1];   //   颜色表 

}   BITMAPINFO; 

5.   位图数据 

  位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数: 

当biBitCount=1时,8个像素占1个字节; 

当biBitCount=4时,2个像素占1个字节; 

当biBitCount=8时,1个像素占1个字节; 

当biBitCount=24时,1个像素占3个字节; 

Windows规定一个扫描行所占的字节数必须是 

4的倍数(即以long为单位),不足的以0填充, 

一个扫描行所占的字节数计算方法: 

DataSizePerLine=   (biWidth*   biBitCount+31)/8;   

//   一个扫描行所占的字节数 

DataSizePerLine=   DataSizePerLine/4*4;   //   字节数必须是4的倍数 

位图数据的大小(不压缩情况下): 

DataSize=   DataSizePerLine*   biHeight; 

继续阅读