位图(BMP)文件格式(一)
位图文件分四部份数据块
1.位图文件头
BITMAPFILEHEADERtypedef struct tagBITMAPFILEHEADER {WORD bfType; //文件类型,对于位图格式,其值是'MB'19778, 由于字节存放次序问题的原故,实际为'BM'DWORD bfSize; //文件总大小WORD bfReserved1; //保留,置0WORD bfReserved2; //保留,置0DWORD bfOffBits; //位图数据偏移长度
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
2.位图信息头
BITMAPINFOHEADERtypedef struct tagBITMAPINFOHEADER{DWORD biSize; //信息头大小,sizeof(BITMAPINFOHEADER)
LONG biWidth; //图片宽度LONG biHeight; //图片高度WORD biPlanes; //面数,置1WORD biBitCount; //每一位像素占的位数,DWORD biCompression; //压缩,0比表示不压缩.BI_RGBDWORD biSizeImage; //图片大小,对24位来说,biWidth * biHeight * 3LONG biXPelsPerMeter; //分辨率,每米多少个像素LONG biYPelsPerMeter; //分辨率,每米多少个像素
DWORD biClrUsed; //用到的颜色数DWORD biClrImportant; //重要的颜色
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
3.调色版
typedef struct tagRGBQUAD {BYTE rgbBlue;BYTE rgbGreen;BYTE rgbRed;BYTE rgbReserved; //保留,置0
} RGBQUAD;
typedef RGBQUAD FAR* LPRGBQUAD;
4.位图数据
不同位数的数据格式不同,对24位位图来说,没有调色版,位图信息依次存放是BGR...
***********************************************************************************
另外两个数据结构,
//实际上OS/2的调色版,(1,4,8位)
typedef struct tagRGBTRIPLE // rgbt
{ BYTE rgbtBlue ; // blue level BYTE rgbtGreen ; // green level BYTE rgbtRed ; // red level
}
RGBTRIPLE ;
//位图信息,(位图信息头 + 调色版)
typedef struct tagBITMAPINFO // bmi
{ BITMAPINFOHEADER bmiHeader ; // info-header structure RGBQUAD bmiColors[1] ; // color table array
}
BITMAPINFO, * PBITMAPINFO ;
对于24位位图来说,没有色彩对照表(调色版),
其位图数据是
B G R
- - - - - - - - - - - - - - - - - - - - - - - -
也就是RGBTRIPLE结构
另外位图数据是自下而上.也就是说左下角为其第一个元素
关于字节对齐的问题,32位对齐也就是4个字节对节
对24位位图来说
由于存放数据时候时候,每像素3个节字,所以需要考虑对齐
//每行像素byte WIDTHBYTE(row) ((row * 3 + 3 ) / 4 ) * 4//更有效率一点 WIDTHBYTE(row) ((row * 24 + 31)>>5)<<2
测试例子
QQ截一幅图55.bmp
属性如下:
宽度 :847
高度 :596
水平分辨率 :96 DPI
垂直分辨率 :96 DPI
位深度 :24
帧数 :1
图片大小:1516278 字节
有了前面这些.
手动计算 考虑对齐的问题,宽度 BYTE : ((847*3+3)/4)*4 =2544 (byte)
总大小 = 宽度 * 高度 + 文件头(14 bytes) + 信息头(40 bytes)
= 2544 * 596 + 54 = 1516278 (bytes)
读图例子如下:
#include <afx.h>
int main()
{char *pbuf = NULL;BITMAPFILEHEADER bfh={0};BITMAPINFOHEADER bih={0};CFile file;file.Open("55.bmp",CFile::modeRead);int nLen = file.GetLength();pbuf = new char[nLen+1];file.ReadHuge(pbuf , nLen);file.Close();bfh = *(LPBITMAPFILEHEADER)pbuf;bih = *(LPBITMAPINFOHEADER)(pbuf + sizeof(BITMAPFILEHEADER));delete []pbuf;return 0;
}
//结果如下:
//文件头
//BITMAPFILEHEADER bfh
//bfType = 19778 //'MB'
//bfSize = 1516278
//bfReserved1 = 0
//bfReserved2 = 0
//bfOffBits = 54
//信息头
//BITMAPINFOHEADER bih
//biWidth = 847
//biHeight = 596
//biPlanes = 1
//biBitCount = 24
//biCompression = 0 //BI_RGB
//biSizeImage = 1516224 // bfSize - bfOffBits
//biXPelsPerMeter = 3780
//biYPelsPerMeter = 3780
//biClrUsed = 0
//biClrImportant = 0
//
//显示图片
//最原始的用SetPixel来显示图片
//例子
//单文档工程中.CBmpView...
//成员变量
public:char * m_pBuf;//整个文件缓存char * m_pBits;//位图数据int m_nWidth;//宽度int m_nHeight;//高度int m_nRowBytes;//每行的节字数LPBITMAPFILEHEADER m_pbfh;//文件头指针LPBITMAPINFOHEADER m_pbih;//信息头指针
//构造函数中
CBmpView::CBmpView()
{// TODO: add construction code herem_pBuf = NULL;m_pBits = NULL;m_pbfh = NULL;m_pbih = NULL;
//读数据CFile file;file.Open("55.bmp",CFile::modeRead);int nLen = file.GetLength();m_pBuf = new char[nLen+1];file.ReadHuge(m_pBuf,nLen);file.Close();
m_pbfh = LPBITMAPFILEHEADER(m_pBuf);//文件头int nOffBits = m_pbfh->bfOffBits;//真实位图数据位移大小m_pbih = LPBITMAPINFOHEADER(m_pBuf + sizeof(BITMAPFILEHEADER));//信息头
m_pBits = m_pBuf + nOffBits;//位图数据
m_nWidth = m_pbih->biWidth; //宽度m_nHeight = m_pbih->biHeight; //高度m_nRowBytes = ((m_nWidth*3+3)/4) * 4;//每行的节字大小
}
//显示图片
void CBmpView::OnDraw(CDC* pDC)
{CBmpDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereRGBTRIPLE *rgb = (RGBTRIPLE *)(m_pBits);char *pRow = (char *)rgb;int nXOff = 20;int nYoff = 20;
//从下往上显示for(int y = m_nHeight-1 ; y > 0 ; y--){for(int x = 0 ; x < m_nWidth ; x++){BYTE r = rgb[x].rgbtRed;BYTE g = rgb[x].rgbtGreen;BYTE b = rgb[x].rgbtBlue;COLORREF clr = RGB(r,g,b);//取颜色pDC->SetPixel( nXOff + x , nYoff + y ,clr);}pRow += m_nRowBytes;//指向下一行rgb = (RGBTRIPLE *)pRow;//指向下一行}
}
//,常规方法.更为简便,速度的方法
int StretchDIBits(
HDC hdc, // handle to DC
int XDest, // x-coord of destination upper-left corner
int YDest, // y-coord of destination upper-left corner
int nDestWidth, // width of destination rectangle
int nDestHeight, // height of destination rectangle
int XSrc, // x-coord of source upper-left corner
int YSrc, // y-coord of source upper-left corner
int nSrcWidth, // width of source rectangle
int nSrcHeight, // height of source rectangle
CONST VOID *lpBits, // bitmap bits
CONST BITMAPINFO *lpBitsInfo, // bitmap data
UINT iUsage, // usage options
DWORD dwRop // raster operation code
);
StretchDIBits(pDC->GetSafeHdc(),nXOff,nYoff,m_nWidth,m_nHeight,0,0,m_nWidth,m_nHeight,m_pBits,(LPBITMAPINFO)m_pbih,DIB_RGB_COLORS,SRCCOPY);
int SetDIBitsToDevice(
HDC hdc, // handle to DC
int XDest, // x-coord of destination upper-left corner
int YDest, // y-coord of destination upper-left corner
DWORD dwWidth, // source rectangle width
DWORD dwHeight, // source rectangle height
int XSrc, // x-coord of source lower-left corner
int YSrc, // y-coord of source lower-left corner
UINT uStartScan, // first scan line in array
UINT cScanLines, // number of scan lines
CONST VOID *lpvBits, // array of DIB bits
CONST BITMAPINFO *lpbmi, // bitmap information
UINT fuColorUse // RGB or palette indexes
);
SetDIBitsToDevice(pDC->GetSafeHdc(),nXOff,nYoff,m_nWidth,m_nHeight,0,0,0,m_nHeight,m_pBits,(LPBITMAPINFO)m_pbih,DIB_RGB_COLORS);
-*******************************************
//文件的保存
(24位)文件的保存
void CBmpView::OnFullscreen()
{// TODO: Add your command handler code hereHDC hdc,hmemDC;HBITMAP hBitmap,hOldBitmp;//屏幕DC,长度,宽度hdc = CreateDC("DISPLAY",NULL,NULL,NULL);int cx = GetDeviceCaps(hdc,HORZRES);int cy = GetDeviceCaps(hdc,VERTRES);//兼容DC,兼容位图hmemDC = CreateCompatibleDC(hdc);hBitmap = CreateCompatibleBitmap(hdc,cx,cy);hOldBitmp =(HBITMAP)SelectObject(hmemDC,hBitmap);BitBlt(hmemDC,0,0,cx,cy,hdc,0,0,SRCCOPY);hBitmap = (HBITMAP)SelectObject(hmemDC,hOldBitmp);DeleteDC(hdc);DeleteObject(hOldBitmp);//基本长度,宽度BITMAP bm;GetObject(hBitmap,sizeof(bm),&bm);int nWidth = bm.bmWidth;int nHeight = bm.bmHeight;//像素数据大小(byte)DWORD dwBmBitsSize = ((nWidth*24+31)/32)*4*nHeight;BITMAPFILEHEADER bfh={0};BITMAPINFOHEADER bih={0};//文件头信息bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);bfh.bfReserved1 = 0;bfh.bfReserved2 = 0;bfh.bfSize = bfh.bfOffBits + dwBmBitsSize;bfh.bfType = 'MB';//信息头信息bih.biBitCount = 24;bih.biCompression = BI_RGB;bih.biHeight = nHeight;bih.biWidth = nWidth;bih.biPlanes = 1;bih.biSize = sizeof(BITMAPINFOHEADER);bih.biSizeImage = dwBmBitsSize;bih.biClrImportant = 0;bih.biClrUsed = 0;bih.biXPelsPerMeter= 0;bih.biYPelsPerMeter= 0;//位图数据char *pBits = new char[dwBmBitsSize];memset(pBits , 0 , dwBmBitsSize);GetDIBits(hmemDC,hBitmap,0,nHeight,pBits,(LPBITMAPINFO)&bih,DIB_RGB_COLORS);DeleteDC(hmemDC);DeleteObject(hBitmap);//写文件CFile file;file.Open("1.bmp",CFile::modeCreate | CFile::modeWrite);file.Write(&bfh,14);file.Write(&bih,40);file.Write(pBits,dwBmBitsSize);file.Close();delete []pBits;
}
位图(BMP)文件格式(一)
位图文件分四部份数据块
1.位图文件头
BITMAPFILEHEADERtypedef struct tagBITMAPFILEHEADER {WORD bfType; //文件类型,对于位图格式,其值是'MB'19778, 由于字节存放次序问题的原故,实际为'BM'DWORD bfSize; //文件总大小WORD bfReserved1; //保留,置0WORD bfReserved2; //保留,置0DWORD bfOffBits; //位图数据偏移长度
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
2.位图信息头
BITMAPINFOHEADERtypedef struct tagBITMAPINFOHEADER{DWORD biSize; //信息头大小,sizeof(BITMAPINFOHEADER)
LONG biWidth; //图片宽度LONG biHeight; //图片高度WORD biPlanes; //面数,置1WORD biBitCount; //每一位像素占的位数,DWORD biCompression; //压缩,0比表示不压缩.BI_RGBDWORD biSizeImage; //图片大小,对24位来说,biWidth * biHeight * 3LONG biXPelsPerMeter; //分辨率,每米多少个像素LONG biYPelsPerMeter; //分辨率,每米多少个像素
DWORD biClrUsed; //用到的颜色数DWORD biClrImportant; //重要的颜色
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
3.调色版
typedef struct tagRGBQUAD {BYTE rgbBlue;BYTE rgbGreen;BYTE rgbRed;BYTE rgbReserved; //保留,置0
} RGBQUAD;
typedef RGBQUAD FAR* LPRGBQUAD;
4.位图数据
不同位数的数据格式不同,对24位位图来说,没有调色版,位图信息依次存放是BGR...
***********************************************************************************
另外两个数据结构,
//实际上OS/2的调色版,(1,4,8位)
typedef struct tagRGBTRIPLE // rgbt
{ BYTE rgbtBlue ; // blue level BYTE rgbtGreen ; // green level BYTE rgbtRed ; // red level
}
RGBTRIPLE ;
//位图信息,(位图信息头 + 调色版)
typedef struct tagBITMAPINFO // bmi
{ BITMAPINFOHEADER bmiHeader ; // info-header structure RGBQUAD bmiColors[1] ; // color table array
}
BITMAPINFO, * PBITMAPINFO ;
对于24位位图来说,没有色彩对照表(调色版),
其位图数据是
B G R
- - - - - - - - - - - - - - - - - - - - - - - -
也就是RGBTRIPLE结构
另外位图数据是自下而上.也就是说左下角为其第一个元素
关于字节对齐的问题,32位对齐也就是4个字节对节
对24位位图来说
由于存放数据时候时候,每像素3个节字,所以需要考虑对齐
//每行像素byte WIDTHBYTE(row) ((row * 3 + 3 ) / 4 ) * 4//更有效率一点 WIDTHBYTE(row) ((row * 24 + 31)>>5)<<2
测试例子
QQ截一幅图55.bmp
属性如下:
宽度 :847
高度 :596
水平分辨率 :96 DPI
垂直分辨率 :96 DPI
位深度 :24
帧数 :1
图片大小:1516278 字节
有了前面这些.
手动计算 考虑对齐的问题,宽度 BYTE : ((847*3+3)/4)*4 =2544 (byte)
总大小 = 宽度 * 高度 + 文件头(14 bytes) + 信息头(40 bytes)
= 2544 * 596 + 54 = 1516278 (bytes)
读图例子如下:
#include <afx.h>
int main()
{char *pbuf = NULL;BITMAPFILEHEADER bfh={0};BITMAPINFOHEADER bih={0};CFile file;file.Open("55.bmp",CFile::modeRead);int nLen = file.GetLength();pbuf = new char[nLen+1];file.ReadHuge(pbuf , nLen);file.Close();bfh = *(LPBITMAPFILEHEADER)pbuf;bih = *(LPBITMAPINFOHEADER)(pbuf + sizeof(BITMAPFILEHEADER));delete []pbuf;return 0;
}
//结果如下:
//文件头
//BITMAPFILEHEADER bfh
//bfType = 19778 //'MB'
//bfSize = 1516278
//bfReserved1 = 0
//bfReserved2 = 0
//bfOffBits = 54
//信息头
//BITMAPINFOHEADER bih
//biWidth = 847
//biHeight = 596
//biPlanes = 1
//biBitCount = 24
//biCompression = 0 //BI_RGB
//biSizeImage = 1516224 // bfSize - bfOffBits
//biXPelsPerMeter = 3780
//biYPelsPerMeter = 3780
//biClrUsed = 0
//biClrImportant = 0
//
//显示图片
//最原始的用SetPixel来显示图片
//例子
//单文档工程中.CBmpView...
//成员变量
public:char * m_pBuf;//整个文件缓存char * m_pBits;//位图数据int m_nWidth;//宽度int m_nHeight;//高度int m_nRowBytes;//每行的节字数LPBITMAPFILEHEADER m_pbfh;//文件头指针LPBITMAPINFOHEADER m_pbih;//信息头指针
//构造函数中
CBmpView::CBmpView()
{// TODO: add construction code herem_pBuf = NULL;m_pBits = NULL;m_pbfh = NULL;m_pbih = NULL;
//读数据CFile file;file.Open("55.bmp",CFile::modeRead);int nLen = file.GetLength();m_pBuf = new char[nLen+1];file.ReadHuge(m_pBuf,nLen);file.Close();
m_pbfh = LPBITMAPFILEHEADER(m_pBuf);//文件头int nOffBits = m_pbfh->bfOffBits;//真实位图数据位移大小m_pbih = LPBITMAPINFOHEADER(m_pBuf + sizeof(BITMAPFILEHEADER));//信息头
m_pBits = m_pBuf + nOffBits;//位图数据
m_nWidth = m_pbih->biWidth; //宽度m_nHeight = m_pbih->biHeight; //高度m_nRowBytes = ((m_nWidth*3+3)/4) * 4;//每行的节字大小
}
//显示图片
void CBmpView::OnDraw(CDC* pDC)
{CBmpDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereRGBTRIPLE *rgb = (RGBTRIPLE *)(m_pBits);char *pRow = (char *)rgb;int nXOff = 20;int nYoff = 20;
//从下往上显示for(int y = m_nHeight-1 ; y > 0 ; y--){for(int x = 0 ; x < m_nWidth ; x++){BYTE r = rgb[x].rgbtRed;BYTE g = rgb[x].rgbtGreen;BYTE b = rgb[x].rgbtBlue;COLORREF clr = RGB(r,g,b);//取颜色pDC->SetPixel( nXOff + x , nYoff + y ,clr);}pRow += m_nRowBytes;//指向下一行rgb = (RGBTRIPLE *)pRow;//指向下一行}
}
//,常规方法.更为简便,速度的方法
int StretchDIBits(
HDC hdc, // handle to DC
int XDest, // x-coord of destination upper-left corner
int YDest, // y-coord of destination upper-left corner
int nDestWidth, // width of destination rectangle
int nDestHeight, // height of destination rectangle
int XSrc, // x-coord of source upper-left corner
int YSrc, // y-coord of source upper-left corner
int nSrcWidth, // width of source rectangle
int nSrcHeight, // height of source rectangle
CONST VOID *lpBits, // bitmap bits
CONST BITMAPINFO *lpBitsInfo, // bitmap data
UINT iUsage, // usage options
DWORD dwRop // raster operation code
);
StretchDIBits(pDC->GetSafeHdc(),nXOff,nYoff,m_nWidth,m_nHeight,0,0,m_nWidth,m_nHeight,m_pBits,(LPBITMAPINFO)m_pbih,DIB_RGB_COLORS,SRCCOPY);
int SetDIBitsToDevice(
HDC hdc, // handle to DC
int XDest, // x-coord of destination upper-left corner
int YDest, // y-coord of destination upper-left corner
DWORD dwWidth, // source rectangle width
DWORD dwHeight, // source rectangle height
int XSrc, // x-coord of source lower-left corner
int YSrc, // y-coord of source lower-left corner
UINT uStartScan, // first scan line in array
UINT cScanLines, // number of scan lines
CONST VOID *lpvBits, // array of DIB bits
CONST BITMAPINFO *lpbmi, // bitmap information
UINT fuColorUse // RGB or palette indexes
);
SetDIBitsToDevice(pDC->GetSafeHdc(),nXOff,nYoff,m_nWidth,m_nHeight,0,0,0,m_nHeight,m_pBits,(LPBITMAPINFO)m_pbih,DIB_RGB_COLORS);
-*******************************************
//文件的保存
(24位)文件的保存
void CBmpView::OnFullscreen()
{// TODO: Add your command handler code hereHDC hdc,hmemDC;HBITMAP hBitmap,hOldBitmp;//屏幕DC,长度,宽度hdc = CreateDC("DISPLAY",NULL,NULL,NULL);int cx = GetDeviceCaps(hdc,HORZRES);int cy = GetDeviceCaps(hdc,VERTRES);//兼容DC,兼容位图hmemDC = CreateCompatibleDC(hdc);hBitmap = CreateCompatibleBitmap(hdc,cx,cy);hOldBitmp =(HBITMAP)SelectObject(hmemDC,hBitmap);BitBlt(hmemDC,0,0,cx,cy,hdc,0,0,SRCCOPY);hBitmap = (HBITMAP)SelectObject(hmemDC,hOldBitmp);DeleteDC(hdc);DeleteObject(hOldBitmp);//基本长度,宽度BITMAP bm;GetObject(hBitmap,sizeof(bm),&bm);int nWidth = bm.bmWidth;int nHeight = bm.bmHeight;//像素数据大小(byte)DWORD dwBmBitsSize = ((nWidth*24+31)/32)*4*nHeight;BITMAPFILEHEADER bfh={0};BITMAPINFOHEADER bih={0};//文件头信息bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);bfh.bfReserved1 = 0;bfh.bfReserved2 = 0;bfh.bfSize = bfh.bfOffBits + dwBmBitsSize;bfh.bfType = 'MB';//信息头信息bih.biBitCount = 24;bih.biCompression = BI_RGB;bih.biHeight = nHeight;bih.biWidth = nWidth;bih.biPlanes = 1;bih.biSize = sizeof(BITMAPINFOHEADER);bih.biSizeImage = dwBmBitsSize;bih.biClrImportant = 0;bih.biClrUsed = 0;bih.biXPelsPerMeter= 0;bih.biYPelsPerMeter= 0;//位图数据char *pBits = new char[dwBmBitsSize];memset(pBits , 0 , dwBmBitsSize);GetDIBits(hmemDC,hBitmap,0,nHeight,pBits,(LPBITMAPINFO)&bih,DIB_RGB_COLORS);DeleteDC(hmemDC);DeleteObject(hBitmap);//写文件CFile file;file.Open("1.bmp",CFile::modeCreate | CFile::modeWrite);file.Write(&bfh,14);file.Write(&bih,40);file.Write(pBits,dwBmBitsSize);file.Close();delete []pBits;
}
发布评论