位图概述 位图格式 typedef struct tagBITMAPINFOHEADER { 该结构体包含关于与颜色格式相关的设备无关位图。 指定的颜色表内的颜色索引,该索引是在位土内被使用的。如果这个值是零。
目录
一.位图文件存储格式位图文件存储格式请参考图1.1。 图1.1 位图文件存储格式 图说明请参考表1.1。 表1.1 位图文件存储格式说明
二.BitmapFileHeadertypedef struct tagBITMAPFILEHEADER { // bmfh WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER; bfType:文件类型,0x4d42,也就是BM bfSize:文件大小,计算方法是 bfReserved1:预留字段,为0。 bfReserved2:预留字段,为0。 bfOffBits:图象数据的偏移量,计算方法是
三.BitmapInfotypedef struct tagBITMAPINFO { // bmi BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1]; } BITMAPINFO; bmiHeader:位图信息头,见下节的结构体说明。 bmiColors:RGB颜色表数组。一般不存储到位图,在GetDIBits时将丢失这个信息,biClrUsed将被设置为0。
四.BitmapInfoHeadertypedef 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位以下时需要使用,计算方法 biSizeImage:图象数据大小,计算方法 注:宽度象素数目+7再除以8,用来处理余数的情况,如位图宽度为2,除以8为0,所以要+7再除以8。 五.BitmapData24位位图图象数据的存储是RGB序列,在windows中是BGR序列:
32位位图象素数据的存储是RGBA序列,A是Alpha值,windows是BGRA序列:
16位图象的分布是:
六.保存位图为文件可以将程序中的图象保存为文件,具体代码如下: 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; } |
|