数字图像处理--BMP文件的读入和保存

BMP文件是Windows系统标准图像文件格式,是一种将内存中的图像数据不经过压缩直接按位存盘的文件格式,所以被称为位图(bitmap),文件扩展名为BMP.

 

BMP文件被分为以下四个部分:位图文件头(Bitmap File Header),位图信息头(Bitmap Info Header),颜色表(Color Map)和位图数据。灰度图像和彩色图像是其中最主要的两种图片表现方式。灰度图像只表达图像的亮度信息而没有颜色信息,图像中每个像素点用一个量化的离散数值表示其灰度级,通常用1个字节存储,可描述出0~255的灰度等级(人眼可分辨的灰度等级也就几十)。8位的灰度图需要颜色板,256个选项的颜色表记录了灰度图的灰度值,灰度图中的位图数据值仅是颜色表的索引。彩色图像包含图像的亮度信息和颜色信息,每个像素使用3个字节,3个字节分别由(RGB)的三基色组成,该类型亦被称为24位真彩色(24位图像不需要颜色表)。

 

 

位图文件头(Bitmap File Header)的结构:

 

typedef struct tagBITMAPFILEHEADER

{

    WORD bfType;                                      //位图文件类型,必须是0x424D

    DWORD bfSize;                                     //位图文件大小

   WORD  bfReserved1;                             //Windows保留字

   WORD  bfReserved2;                             //Windows保留字

   DWORD bfOffBits;                                  //从文件头到位图数据的偏移字节数

}BITMAPFILEHEADER,FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;

 

位图信息头(Bitmap Info Header)的结构:

 

typedef struct tagBITMAPINFOHEADER

{

   DWORD   biSize;                                  //该结构的长度,大小为40个字节

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

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

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

   WORD     biBitCount;                          //每个像素所占的位数

   DWORD   biCompression;                  //位图压缩类型

   DWORD   biSizeImage;                      //位图数据所占的字节数

   LONG      biXPelsPerMeter;               //目标设备水平分辨率

   LONG      biYPelsPerMeter;               // 目标设备垂直分辨率

   DWORD   biClrUsed;                       //位图实际所用的颜色数

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

}BITMAPINFOHEADER,FAR *LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;

 

颜色表(Color Map)的结构:

 

typedef struct tagRGBQUAD

{

   BYTE  rgbBlue;                               //颜色的蓝色分量

   BYTE  rgbGreen;                           //颜色的绿色分量

   BYTE  rgbRed;                              //颜色的红色分量

   ByTE  rgbReserved;                     //保留字节

}RGBQUAD;

 

 

位图数据:

             Windows规定每行的字节数必须是4的倍数,不足4的倍数要补足;如果一幅图像宽为Width,每像素所占用bit个比特,那么该行的字节数=(Width*bit/8+3)/4*4。(+3和/4是为了应对不足4的倍数的情况)。如果该图的高为Height,那么该图的实际拥有的字节数=高X每行字节数=Height*(Width*bit/8+3)/4*4。

            BMP文件的数据是从图像左下角开始逐行载入内存(从左到右,从下到上),像素中的RGB基元是按照BGR排列(如一个a[3]数组表示24位的像素,那么a[0]=blue分量的值,a[1]=green分量的值,a[2]=red分量的值)

 

 

本文系转载,以前为c++程序。以下的程序由自己拿c语言改过: 

 

BMP文件的载入和保存:


#include "Windows.h"
#include <stdio.h>
BOOL LoadBmp(char *);
BOOL SaveBmp(char *BmpName); 

unsigned char *pBmpBuffer;             //bmp像素指针
int BmpWidth;                              //位图的宽度
int BmpHeight;                            //位图的高度
RGBQUAD *ColorTable;            //颜色表的指针
int BmpBit;                           //每个像素占用位数

void main()
{
 char Load[]="lena24.bmp";            
   int i,j,k;
   int LineByte;
   char Save[]="lena0.BMP";   
 LoadBmp(Load);

 printf("the height of the picture:/n");
 scanf("%d",&BmpWidth);

 printf("the bit of the per pixcel:/n");
 scanf("%d",&BmpBit);
 

 LineByte=(BmpWidth*BmpBit/8+3)/4*4; //图像每行的字节数

 //将图像的左下角1/4部分置成黑色

 if(BmpBit==8)                                              //如果是8位图
 {
  for(i=0;i<BmpHeight/2;i++)
   for(j=0;j<BmpWidth/2;j++)
    *(pBmpBuffer+i*LineByte+j)=0;
 }

 if(BmpBit==24)                                              //如果是24位图
 {
  for(i=0;i<BmpHeight/2;i++)
   for(j=0;j<BmpWidth/2;j++)
    for(k=0;k<3;k++)
     *(pBmpBuffer+i*LineByte+j*3+k)=0;
 }

 SaveBmp(Save);
 free(pBmpBuffer);  //释放pBmpBuffer所指向的内存
 if(BmpBit==8)    //如果有颜色表,释放指向颜色表的内存
  free(ColorTable);
}

BOOL LoadBmp(char *BmpName)                      //从硬盘中读取BMP文件进内存
{
 BITMAPINFOHEADER head;
 FILE *fp=fopen(BmpName,"rb");
 int LineByte=0;
 if(fp==0)
 {
  return 0;
 }

 fseek(fp,sizeof(BITMAPFILEHEADER),0);      //跳过图像文件头结构BITMAPFILEHEADER
 
 fread(&head,sizeof(BITMAPINFOHEADER),1,fp);            //读取文件信息头进入head结构体

 BmpWidth=head.biWidth;                                             //导入图像的宽
 BmpHeight=head.biHeight;                                           //导入图像的高
 BmpBit=head.biBitCount;                                             //每个像素所占位数

 LineByte=(BmpWidth*BmpBit/8+3)/4*4;                //一个扫描行所占真实字节数

 if(BmpBit==8)                                                         //如果是8位图
 {
  ColorTable=malloc(sizeof(RGBQUAD)*256);              //申请颜色表需要的空间,读颜色表进内存
  fread(ColorTable,sizeof(RGBQUAD),256,fp);
 }

 pBmpBuffer= (unsigned char*)malloc(sizeof(unsigned char)*LineByte*BmpHeight);        //申请图像像素所用空间
 fread(pBmpBuffer,1,LineByte*BmpHeight,fp);                        //读像素数据进内存
 fclose(fp);

 return 1;
}

BOOL SaveBmp(char *BmpName)                                  //保存bmp文件
{
 FILE *fp;
 BITMAPINFOHEADER head; 
 BITMAPFILEHEADER fileHead;
 int colorTablesize=0;
 int LineByte=0;
 if(!pBmpBuffer)   //如果指针为空,退出
 {
  return 0;
 }

 if(BmpBit==8)
 {
  colorTablesize=1024;
 }

 LineByte=(BmpWidth*BmpBit/8+3)/4*4;            //计算图像每行的像素

 fp=fopen(BmpName,"wb");                          //打开待被写入的BMP文件
 if(fp==0) return 0;

  //保存文件头
 fileHead.bfType=0x4D42;                                                          

 fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTablesize+LineByte*BmpHeight;
 fileHead.bfReserved1=0;
 fileHead.bfReserved2=0;

 fileHead.bfOffBits=54+colorTablesize;

 fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);          
                                                    //保存信息头
 head.biBitCount=BmpBit;
 head.biClrImportant=0;
 head.biClrUsed=0;
 head.biCompression=0;
 head.biHeight=BmpHeight;
 head.biPlanes=1;
 head.biSize=40;
 head.biSizeImage=LineByte*BmpHeight;
 head.biWidth=BmpWidth;
 head.biXPelsPerMeter=0;
 head.biYPelsPerMeter=0;

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

 if(BmpBit==8)                                                                       //如果存在颜色表
  fwrite(ColorTable,sizeof(RGBQUAD),256,fp);
 fwrite(pBmpBuffer,BmpHeight*LineByte,1,fp);                         //保存像素
 fclose(fp);

 return 1;
}

 

 

你可能感兴趣的:(windows,struct,header,byte,FP,图像处理)