microsoftxiao

记忆 流逝

导航

Windows位图文件格式[转]

位图概述

位图格式
位图文件头
结构包含关于类型,大小以及与设备无关的文件层。
typedef struct tagBITMAPFILEHEADER {
  WORD bfType;
  DWORD bfSize;
  WORD bfReserved1;
  WORD bfReserved2;
  DWORD bfOffBits;
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
  DWORD biSize;                        // 大小
  LONG biWidth;                        // 宽度
  LONG biHeight;                       // 高度
  WORD biPlanes;                       // 平面?
  WORD biBitCount                      // 为个数
  DWORD biCompression;                 // 压缩
  DWORD biSizeImage;                   // 图像大小
  LONG biXPelsPerMeter;                // 每公尺X上的像素
  LONG biYPelsPerMeter;                // 每公尺Y上的像素
  DWORD biClrUsed;                     // ???
  DWORD biClrImportant;                // ???
} BITMAPINFOHEADER;
位图信息头

该结构体包含关于与颜色格式相关的设备无关位图。

指定的颜色表内的颜色索引,该索引是在位土内被使用的。如果这个值是零。
如果biClrUsed是非零值且biBitCount值小于16, biClrUsed成员指定实际图形引擎或设备驱动的存取值。
biClrImportant被指定的颜色索引必须显示在位图上。
如果颜色值是零,所有颜色是必须的。

 

 

目录

位图格式分析

一.位图文件存储格式

二.BitmapFileHeader

三.BitmapInfo

四.BitmapInfoHeader

五.BitmapData

六.保存位图为文件

1. 错误信息函数

2. 建立位图信息结构体函数

3. 建立位图文件函数

4. 保存位图到文件函数

七.从文件加载位图

1.错误信息函数

2. 从位图文件加载图象函数

 

.位图文件存储格式

位图文件存储格式请参考图1.1。

图1.1 位图文件存储格式

图说明请参考表1.1。

表1.1 位图文件存储格式说明

结构体

说明

BitmapFileHeader

位图文件信息头

BitmapInfo

位图信息,由以下两个结构体组成

BitmapInfoHeader

位图信息头

RGBQUAD

颜色表

BitmapData

位图数据

.BitmapFileHeader

typedef struct tagBITMAPFILEHEADER { // bmfh

    WORD    bfType;

    DWORD   bfSize;

    WORD    bfReserved1;

    WORD    bfReserved2;

    DWORD   bfOffBits;

} BITMAPFILEHEADER;

bfType:文件类型,0x4d42,也就是BM

bfSize:文件大小,计算方法是
位图文件头大小【sizeof(BITMAPFILEHEADER)】
+位图信息头大小【pbih->biSize】
+颜色表大小【pbih->biClrUsed*sizeof(RGBQUAD)】
+位图数据大小【pbih->biSizeImage】

bfReserved1:预留字段,为0。

bfReserved2:预留字段,为0。

bfOffBits:图象数据的偏移量,计算方法是
位图文件头大小【sizeof(BITMAPFILEHEADER)】
+位图信息头大小【pbih->biSize】
+颜色表大小【pbih->biClrUsed*sizeof(RGBQUAD)】

 

.BitmapInfo

typedef struct tagBITMAPINFO { // bmi

    BITMAPINFOHEADER bmiHeader;

    RGBQUAD          bmiColors[1];

} BITMAPINFO;

bmiHeader:位图信息头,见下节的结构体说明。

bmiColors:RGB颜色表数组。一般不存储到位图,在GetDIBits时将丢失这个信息,biClrUsed将被设置为0。

 

.BitmapInfoHeader

typedef struct tagBITMAPINFOHEADER{ // bmih

    DWORD biSize;

    LONG   biWidth;

    LONG   biHeight;

    WORD   biPlanes;

    WORD   biBitCount

    DWORD biCompression;

   DWORD biSizeImage;

    LONG   biXPelsPerMeter;

    LONG   biYPelsPerMeter;

    DWORD biClrUsed;

    DWORD biClrImportant;

} BITMAPINFOHEADER;

biSize:结构体大小。

biWidth:位图宽度,象素。对应位图宽度,bmp.bmWidth。

biHeight:位图高度,象素。对应位图高度,bmp.bmHeight。

biPlanes:调色板数目,一般是1。对应位图调色板数目,bmp.bmPlanes。

biBitCount:颜色位数。对应位图bmp.bmBitsPixel。

biClrUsed:使用的颜色数,在24位以下时需要使用,计算方法
if(cClrBits < 24) pbmi->bmiHeader.biClrUsed=(1<<cClrBits);

biSizeImage:图象数据大小,计算方法
位图宽度象素数目转换成字节【(pbmi->bmiHeader.biWidth+7)/8】
*位图高度象素数目【pbmi->bmiHeader.biHeight】
*象素位数【cClrBits】

注:宽度象素数目+7再除以8,用来处理余数的情况,如位图宽度为2,除以8为0,所以要+7再除以8。

.BitmapData

24位位图图象数据的存储是RGB序列,在windows中是BGR序列:

象素B蓝色分量值

象素G绿色分量值

象素R红色分量值

32位位图象素数据的存储是RGBA序列,A是Alpha值,windows是BGRA序列:

象素B蓝色分量值

象素G绿色分量值

象素R红色分量值

象素alpha分量值

16位图象的分布是:

最高位保留,为0

高5位,红色分量

中间5位,绿色分量

最低5位,蓝色分量

 

.保存位图为文件

可以将程序中的图象保存为文件,具体代码如下:

1. 错误信息函数

//错误信息

void exitWND(LPCTSTR msg)

{

     MessageBox(NULL,msg,"Error",0);

     exit(0);

}

2. 建立位图信息结构体函数

//建立位图信息结构体

PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)

{

     BITMAP bmp;

     if(!GetObject(hBmp,sizeof(BITMAP),&bmp))

         exitWND("Error when get object from hbitmap");

     //获取颜色位数

     WORD cClrBits;

     cClrBits=(WORD)(bmp.bmPlanes*bmp.bmBitsPixel);

     if(cClrBits == 1)

         cClrBits=1;

     else if(cClrBits <= 4)

         cClrBits=4;

     else if(cClrBits <= 8)

         cClrBits=8;

     else if(cClrBits <= 16)

         cClrBits=16;

     else if(cClrBits <= 24)

         cClrBits=24;

     else cClrBits=32;

     //分配位图信息结构体

     PBITMAPINFO pbmi;

     if(cClrBits != 24)

         pbmi=(PBITMAPINFO)

         LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*(1<<cClrBits));

     else

         pbmi=(PBITMAPINFO)

         LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER));                           

     //初始化位图结构体

     pbmi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);

     pbmi->bmiHeader.biWidth=bmp.bmWidth;

     pbmi->bmiHeader.biHeight=bmp.bmHeight;

     pbmi->bmiHeader.biPlanes=bmp.bmPlanes;

     pbmi->bmiHeader.biBitCount=bmp.bmBitsPixel;

     if(cClrBits < 24)

         pbmi->bmiHeader.biClrUsed=(1<<cClrBits);

     //不压缩位图

     pbmi->bmiHeader.biCompression=BI_RGB;

     //初始化图象数据大小

     pbmi->bmiHeader.biSizeImage=

         (pbmi->bmiHeader.biWidth+7)/8

         *pbmi->bmiHeader.biHeight

         *cClrBits;

     //所有的设备颜色都重要

     pbmi->bmiHeader.biClrImportant=0;

     //返回指针

     return pbmi;

}

3. 建立位图文件函数

//建立位图文件

void CreateBMPFile(LPTSTR pszFile,PBITMAPINFO pbi,HBITMAP hBmp,HDC hDC)

{

     PBITMAPINFOHEADER pbih=(PBITMAPINFOHEADER)pbi;

     LPBYTE lpBits;

     lpBits=(LPBYTE)GlobalAlloc(GMEM_FIXED,pbih->biSizeImage);

     if(!lpBits)

         exitWND("error to global alloc memory");

     //获取位图图象数据

     GetDIBits(hDC,hBmp,0,(WORD)pbih->biHeight,lpBits,pbi,DIB_RGB_COLORS);

     //建立位图文件

     HANDLE hf;

     hf=CreateFile(pszFile,GENERIC_READ|GENERIC_WRITE,

         NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

     if(hf == INVALID_HANDLE_VALUE)

         exitWND("error to create file");

     //建立位图文件信息头

     BITMAPFILEHEADER hdr;

     hdr.bfType=0x4d42;

     hdr.bfSize=(DWORD)(sizeof(BITMAPFILEHEADER)+

         pbih->biSize+pbih->biClrUsed*sizeof(RGBQUAD)+

         pbih->biSizeImage);

     hdr.bfReserved1=0;

     hdr.bfReserved2=0;

     //计算位图数据偏移量

     hdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+

         pbih->biSize+pbih->biClrUsed*sizeof(RGBQUAD);

     //写入位图文件头

     DWORD wt;

     if(!WriteFile(hf,(LPVOID)&hdr,sizeof(BITMAPFILEHEADER),&wt,NULL))

         exitWND("error when write bitmap file header");

     //写入位图信息头

     if(!WriteFile(hf,(LPVOID)pbih,

         sizeof(BITMAPINFOHEADER)+pbih->biClrUsed*sizeof(RGBQUAD),

         &wt,NULL))

         exitWND("error when write bitmap info header and RGBquad");

     //写入位图数据

     if(!WriteFile(hf,(LPVOID)lpBits,pbih->biSizeImage,&wt,NULL))

         exitWND("error when write data");

     //关闭文件

     if(!CloseHandle(hf))

         exitWND("error when close file handle");

     //释放图象数据所占内存

     GlobalFree(lpBits);

}

4. 保存位图到文件函数

//保存位图到文件

void SaveBitmapFile(LPTSTR fileName,HWND hWnd,HBITMAP bmp)

{

     PBITMAPINFO pbmi;

     pbmi=CreateBitmapInfoStruct(bmp);

     HDC hdc;

     hdc=GetDC(hWnd);

     CreateBMPFile(fileName,pbmi,bmp,hdc);

     ReleaseDC(hWnd,hdc);

}

 

.从文件加载位图

从文件加载位图,用ReadFile定位文件需要使用OVERLAPPED,展开位图到DC使用StretchDIBits函数。代码如下:

1.错误信息函数

//错误信息

void exitWND(LPCTSTR msg)

{

     MessageBox(NULL,msg,"Error",0);

     exit(0);

}

2. 从位图文件加载图象函数

//从位图文件加载图象

HBITMAP LoadBitmapFile(LPCTSTR fileName,HWND hWnd)

{

     //打开文件

     HANDLE hf;

     hf=CreateFile(fileName,GENERIC_READ,FILE_SHARE_READ,

         NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);

     if(hf == INVALID_HANDLE_VALUE){

         exitWND("error when open file handle");

         return 0x00;

     }

     //展开位图文件到DC

     DWORD read;

     //读取文件信息头

     BITMAPFILEHEADER bfh;

     OVERLAPPED olbfh;

     memset(&olbfh,0,sizeof(OVERLAPPED));

     olbfh.Offset=0;

     ReadFile(hf,&bfh,sizeof(bfh),&read,&olbfh);

     //读取位图信息

     BITMAPINFO bi;

     OVERLAPPED olbi;

     memset(&olbi,0,sizeof(OVERLAPPED));

     olbi.Offset=sizeof(BITMAPFILEHEADER);

     ReadFile(hf,&bi.bmiHeader,sizeof(bi.bmiHeader),&read,&olbi);

     //读取位图数据

     LPBYTE lpBits;

     lpBits=(LPBYTE)GlobalAlloc(GMEM_FIXED,bi.bmiHeader.biSizeImage);

     OVERLAPPED ollpbits;

     memset(&ollpbits,0,sizeof(OVERLAPPED));

     ollpbits.Offset=bfh.bfOffBits;

     ReadFile(hf,lpBits,bi.bmiHeader.biSizeImage,&read,&ollpbits);

     //建立和窗口关联的DC

     HDC hdc;

     hdc=GetDC(hWnd);

     HDC mem;

     mem=CreateCompatibleDC(hdc);

     //建立和DC关联的位图

     HBITMAP bmp;

     bmp=CreateCompatibleBitmap(hdc,bi.bmiHeader.biWidth,bi.bmiHeader.biHeight);

     SelectObject(mem,bmp);

     //在DC中展开

     StretchDIBits(mem,

         0,0,bi.bmiHeader.biWidth,bi.bmiHeader.biHeight,

         0,0,bi.bmiHeader.biWidth,bi.bmiHeader.biHeight,

         (LPVOID)lpBits,&bi,DIB_RGB_COLORS,SRCCOPY);

     //清理工作

     GlobalFree(lpBits);

     DeleteDC(mem);

     ReleaseDC(hWnd,hdc);

     CloseHandle(hf);

     //返回位图对象

     return bmp;

}

 

posted on 2008-09-13 13:37  龙巢NET刀  阅读(2754)  评论(2编辑  收藏  举报