DIB位图文件的格式、读取、保存和显示(转载)
一、位图文件结构
位图文件由三部分组成:文件头 + 位图信息 + 位图像素数据
1、位图文件头:BitMapFileHeader。位图文件头主要用于识别位图文件。以下是位图文件头结构的定义:
typedef struct tagBITMAPFILEHEADER { // bmfh
WORD bfType; //bfType指定文件类型。其值必须是0x4d42,即字符串“MB”,也就是说所有“.bmp”文件的头两个字节都是”MB“,标志该文件是位图文件。
DWORD bfSize; //bfSize的值是位图文件的大小,包括4个字节。
WORD bfReserved1;
WORD bfReserved2; //bfReserved1,bfReserved2为保留字,不用考虑。
DWORD bfOffBits; //为从文件头到实际的位图数据的偏移字节数,
} BITMAPFILEHEADER
该结构的长度是固定的,为14个字节(WORD 为无符号16位整数,DWORD为无符号32位整数)。
2、位图信息:BitMapInfo。位图信息中所记录的值用于分配内存,设置调色板信息,读取像素值等。
以下是位图信息结构的定义:
- typedef struct tagBITMAPINFO {
- BITMAPINFOHEADER bmiHeader; //位图信息头
- RGBQUAD bmiColors[1]; //颜色表
- } BITMAPINFO;
可见位图信息也是由两部分组成的:位图信息头 + 颜色表/调色板(Palette)
2.1 、位图信息头:BitMapInfoHeader。
位图信息头包含了单个像素所用字节数以及描述颜色的格式,此外还包括位图的宽度、高度、目标设备的位平面数、图像的压缩格式。以下是位图信息头结构的定义:
- typedef struct tagBITMAPINFOHEADER{ // bmih
- DWORD biSize; //指定结构BITMAPINFOHEADER的字节数,为40个字节,即sizeof(BITMAPINFOHEADER)*
- LONG biWidth; //以像素为单位的图像宽度*
- LONG biHeight; // 以像素为单位的图像长度*
- WORD biPlanes; //目标设备的位平面数,必须是1,不用考虑。
- WORD biBitCount //指定表示颜色时每个像素的位数,常用的值为1(黑白二色图)、4(16色图)、8(256色)、24(真彩色)、*(1)
- DWORD biCompression; //图像的压缩格式(这个值几乎总是为0),有效地值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS(这些都是Windows定义好的常量)
- DWORD biSizeImage; //以字节为单位的图像数据的大小(对BI_RGB压缩方式而言)
- LONG biXPelsPerMeter; //指定目标设备的水平分辨率,单位是像素/米。
- LONG biYPelsPerMeter; //指定目标设备的垂直分辨率,单位是像素/米。
- DWORD biClrUsed; //指定本图像实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次幂。(2)
- DWORD biClrImportant; //指定本图像中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。(3)
- } BITMAPINFOHEADER;
说明:*是需要加以注意的部分,因为它们是我们在进行位图操作时经常参考的变量
(1)对于每个像素的字节数,分别有一下意义:
0,用在JPEG格式中
1,单色图,调色板中含有两种颜色,也就是我们通常说的黑白图片
4,16色图
8,256色图,通常说的灰度图
16,64K图,一般没有调色板,图像数据中每两个字节表示一个像素,5个或6个位表示一个RGB分量
24,16M真彩色图,一般没有调色板,图像数据中每3个字节表示一个像素,每个字节表示一个RGB分量
32,4G真彩色,一般没有调色板,每4个字节表示一个像素,相对24位真彩图而言,加入了一个透明度,即RGBA模式
(2)这个值通常为0,表示使用biBitCount确定的全部颜色,例外是使用的颜色数目小于制定的颜色深度的颜色数目的最大值。
(3)这个值通常为0,表示所有的颜色都是必需的。
位图信息头结构的长度也是固定的,为40个字节(LONG为32位整数)。
2.2、颜色表/调色板:RGBQuad/Palette。
调色板一般是针对16位以下的图像而设置的,对于16位和16位以上的图像,由于其位图像素数据中直接对对应像素的RGB(A)颜色进行描述,因而省却了调色板,他们的BITMAPINFOHEADER后面直接是位图数据。而对于16位以下的图像,由于其位图像素数据中记录的只是调色板索引值,因而需要根据这个索引到调色板去取得相应的RGB(A)颜色。颜色表的作用就是创建调色板。调色板实际上是一个数组,共有biClrUsed个元素(如果该值为零,则有2的biBitCount次幂个元素)。数组中每个元素的类型是一个RGBQUAD结构,占4个字节。
颜色表是由颜色表项组成的,颜色表项结构的定义如下:
- typedef struct tagRGBQUAD { // rgbq
- BYTE rgbBlue;
- BYTE rgbGreen;
- BYTE rgbRed;
- BYTE rgbReserved; //保留值
- } RGBQUAD;
其中需要注意的问题是,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。
3、位图数据。最后,在位图文件头、位图信息头、位图颜色表之后,便是位图的主体部分:位图数据。根据不同的位图,位图数据所占据的字节数也是不同的,比如,对于8位位图,每个字节代表了一个像素,对于16位位图,每两个字节代表了一个像素,对于24位位图,每三个字节代表了一个像素,对于32位位图,每四个字节代表了一个像素
二、位图文件的读取、保存和显示
头文件中定义
- private:
- DWORD m_dwDibSize;
- CPalette m_Palette;
- int m_nPaletteEntries;
- RGBQUAD *m_pPalette; //颜色表指针
- unsigned char *m_pDib, *m_pDibBits;
- BITMAPINFOHEADER *m_pBIH; //位图信息头指针
1、读取位图
- //加载图片
- void CImageDisposeDlg::OnBtnloadimage()
- {
- // TODO: Add your control notification handler code here
- //文件路径名称
- CString pszFilename;
- //浏览文件对话框
- CFileDialog hFileDlg(TRUE,"bmp",
- NULL,
- OFN_FILEMUSTEXIST|OFN_READONLY|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR,
- TEXT("BMP (*.bmp)|*.bmp|所有文件(*.*)|*.*|"),
- NULL);
- if(hFileDlg.DoModal() == IDOK)
- {
- //获得文件路径名称
- pszFilename=hFileDlg.GetPathName();
- }
- //文件类
- CFile cf;
- //文件打开失败,程序返回
- if( !cf.Open( pszFilename, CFile::modeRead ) )
- {
- return;
- }
- //获得位图信息文件大小
- DWORD dwDibSize;
- dwDibSize = cf.GetLength() - sizeof( BITMAPFILEHEADER );
- //申请一块内存存放位图信息
- unsigned char *pDib;
- pDib = new unsigned char [dwDibSize];
- if( pDib == NULL )
- {
- return;
- }
- //位图文件头
- BITMAPFILEHEADER BFH;
- //从文件读取位图文件头和位图数据
- try{
- // 判断读取位图文件头是否成功
- if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) )
- != sizeof( BITMAPFILEHEADER ) ||
- // 判断是否是位图类型
- BFH.bfType != 'MB' ||
- // 判断读取位图数据是否成功
- cf.Read( pDib, dwDibSize ) != dwDibSize ){
- //释放位图数据指针
- delete [] pDib;
- //读取失败,程序返回
- return;
- }
- }
- catch( CFileException *e ){
- e->Delete();
- delete [] pDib;
- return;
- }
- //重置全局位图信息指针
- if( m_pDib != NULL )
- {
- delete m_pDib;
- }
- //将位图信息指针和位图信息大小赋值给全局变量
- m_pDib = pDib;
- m_dwDibSize = dwDibSize;
- //获取位图信息头指针
- m_pBIH = (BITMAPINFOHEADER *) m_pDib;
- //获取位图调色板指针
- m_pPalette = (RGBQUAD *) &m_pDib[sizeof(BITMAPINFOHEADER)];
- // 计算调色板中实际颜色数量
- m_nPaletteEntries = 1 << m_pBIH->biBitCount;//1左移
- if( m_pBIH->biBitCount > 8 )
- {
- m_nPaletteEntries = 0;
- }
- else if( m_pBIH->biClrUsed != 0 )
- {
- m_nPaletteEntries = m_pBIH->biClrUsed;
- }
- // 获取位图数据指针
- m_pDibBits = &m_pDib[sizeof(BITMAPINFOHEADER)+m_nPaletteEntries*sizeof(RGBQUAD)];
- // 重置全局调色板
- if( m_Palette.GetSafeHandle() != NULL )
- {
- m_Palette.DeleteObject();
- }
- //如果调色板颜色数量不为零,则通过逻辑调色板创建调色板
- if( m_nPaletteEntries != 0 ){
- //为逻辑调色板分配内存
- LOGPALETTE *pLogPal = (LOGPALETTE *) new char
- [sizeof(LOGPALETTE)+
- m_nPaletteEntries*sizeof(PALETTEENTRY)];
- if( pLogPal != NULL ){
- //设置逻辑调色板的版本
- pLogPal->palVersion = 0x300;
- //设置逻辑调色板的颜色数量
- pLogPal->palNumEntries = m_nPaletteEntries;
- //为每个颜色实体赋颜色值
- for( int i=0; i<m_nPaletteEntries; i++ ){
- pLogPal->palPalEntry[i].peRed =
- m_pPalette[i].rgbRed;
- pLogPal->palPalEntry[i].peGreen =
- m_pPalette[i].rgbGreen;
- pLogPal->palPalEntry[i].peBlue =
- m_pPalette[i].rgbBlue;
- }
- //创建调色板
- m_Palette.CreatePalette( pLogPal );
- //释放内存
- delete [] pLogPal;
- }
- }
- //重绘
- Invalidate();
- }
2、保存位图
- //保存图片
- void CImageDisposeDlg::OnBtnsave()
- {
- // TODO: Add your control notification handler code here
- //文件路径名称
- CString pszFilename;
- //浏览文件对话框
- CFileDialog hFileDlg(FALSE,"bmp",
- NULL,
- OFN_FILEMUSTEXIST|OFN_READONLY|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR,
- TEXT("BMP (*.bmp)|*.bmp|所有文件(*.*)|*.*|"),
- NULL);
- if(hFileDlg.DoModal() == IDOK)
- {
- //获得文件路径名称
- pszFilename=hFileDlg.GetPathName();
- }
- // 如果位图信息为空则程序返回
- if( m_pDib == NULL )
- return;
- //文件类
- CFile cf;
- // 创建文件
- if( !cf.Open( pszFilename,
- CFile::modeCreate | CFile::modeWrite ) )
- return;
- // 写入数据
- try{
- //创建位图文件头
- BITMAPFILEHEADER BFH;
- memset( &BFH, 0, sizeof( BITMAPFILEHEADER ) );
- BFH.bfType = 'MB';
- BFH.bfSize = sizeof( BITMAPFILEHEADER ) + m_dwDibSize;
- BFH.bfOffBits = sizeof( BITMAPFILEHEADER ) +
- sizeof( BITMAPINFOHEADER ) +
- m_nPaletteEntries * sizeof( RGBQUAD );
- //将数据写入文件
- cf.Write( &BFH, sizeof( BITMAPFILEHEADER ) );
- cf.Write( m_pDib, m_dwDibSize );
- }
- catch( CFileException *e ){
- e->Delete();
- return;
- }
- }
3、显示位图
- void CImageDisposeDlg::OnPaint()
- {
- CPaintDC dc(this);
- //如果位图信息为空,程序返回
- if( m_pDib == NULL )
- return;
- //获得位图宽高
- int nWidth,nHeight;
- nWidth = m_pBIH->biWidth;
- nHeight = m_pBIH->biHeight;
- //如果有调色板则使用调色板
- if( m_Palette.GetSafeHandle() != NULL )
- {
- CPalette *pOldPalette;
- pOldPalette = dc.SelectPalette( &m_Palette, FALSE );//选择调色板
- dc.RealizePalette();//实现调色板
- //绘图
- StretchDIBits( dc.m_hDC, 0, 0,
- nWidth, nHeight,
- 0, 0,
- m_pBIH->biWidth, m_pBIH->biHeight,
- m_pDibBits,
- (BITMAPINFO *) m_pBIH,
- BI_RGB, SRCCOPY );
- //恢复调色板
- dc.SelectPalette( pOldPalette, FALSE );
- }
- else//没有调色板,直接绘制
- {
- StretchDIBits( dc.m_hDC, 0, 0,
- nWidth, nHeight,
- 0, 0,
- m_pBIH->biWidth, m_pBIH->biHeight,
- m_pDibBits,
- (BITMAPINFO *) m_pBIH,
- BI_RGB, SRCCOPY );
- }
- }
DIB位图文件的格式、读取、保存和显示(转载)的更多相关文章
- DIB位图(Bitmap)的读取和保存
设备无关位图(Device Independent Bitmap)是可以保存在磁盘的位图文件,可以从磁盘读取到内存或者从内存保存到磁盘上.它的文件结构是标准化的,可以在Windows/Linux/Un ...
- 位图文件(BMP)格式以及Linux下C程序实现(转)
源:位图文件(BMP)格式以及Linux下C程序实现 说到图片,位图(Bitmap)当然是最简单的,它是Windows显示图片的基本格式,其文件扩展名为*.BMP.由于没有经过任何的压缩,故BMP图 ...
- 一个获取指定目录下一定格式的文件名称和文件修改时间并保存为文件的python脚本
摘自:http://blog.csdn.net/forandever/article/details/5711319 一个获取指定目录下一定格式的文件名称和文件修改时间并保存为文件的python脚本 ...
- SharpDX之Direct2D教程II——加载位图文件和保存位图文件
本系列文章目录: SharpDX之Direct2D教程I——简单示例和Color(颜色) 绘制位图是绘制操作的不可缺少的一部分.在Direct2D中绘制位图,必须先利用WIC组件将位图加载到内存中,再 ...
- pytorch保存模型等相关参数,利用torch.save(),以及读取保存之后的文件
本文分为两部分,第一部分讲如何保存模型参数,优化器参数等等,第二部分则讲如何读取. 假设网络为model = Net(), optimizer = optim.Adam(model.parameter ...
- C# 读取保存xml文件
直接读取xml文件中的内容 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(result); XmlNode root = xmlDoc. ...
- 位图文件格式及linux下C语言来操作位图文件
说到图片,位图(Bitmap)当然是最简单的,它是Windows显示图片的基本格式,其文件扩展名为*.BMP.由于没有经过任何的压缩,故BMP图片往往很大.在Windows下,任何格式的图片文件都要转 ...
- wave文件(*.wav)格式、PCM数据格式
1. 音频简介 经常见到这样的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等. 44100HZ 16bit stereo: 每秒钟有 44100 次采 ...
- wave文件(*.wav)格式、PCM数据格式, goldwave 可以播放pcm raw audio
1. 音频简介 经常见到这样的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等. 44100HZ 16bit stereo: 每秒钟有 44100 次采 ...
随机推荐
- HTML5中表单的创建
一.常用表单标签如下: (1)<input>中的“type”属性: 复选框-checkbox:单选按钮-radio;按钮-button:提交-submit; (2)文本域 行-cols:列 ...
- JavaScript:实现瀑布流
一.前言: 瀑布流现在是一个非常常用的布局方式了,尤其在购物平台上,例如蘑菇街,淘宝等等. 二.流程: 1.在html文件中写出布局的元素内容: 2.在css文件中整体对每一个必要的元素进行样式和浮动 ...
- objective-c 中随机数的用法 3种:arc4random() 、random()、CCRANDOM_0_1()
oc 中随机数的用法(arc4random() .random().CCRANDOM_0_1() 1).arc4random() 比较精确不需要生成随即种子 使用方法 : 通过arc4random() ...
- iOS系统版本简介
iOS系统版本简介 ⽬目前iOS设备所⽀支持的最主流操作系统是iOS6,⼤大概占了93%,⽽而使 ⽤用iOS5的iOS设备⼤大概占6%,剩下的只有1%.( 根据苹果的官⽅方数据 ) 从iOS1到现在的 ...
- 怎样搭建本地svn服务器环境-轻松掌握版本管理
版本管理一直是程序员使用频率比较高的一个工具软件.不管你是自己使用还是提供给别人使用,svn服务器的架设是一个入门功课.今天我们先来介绍一下怎么样在本地搭建svn服务器.这种应用一般是网络不是很好,提 ...
- PLSQL 的简单命令之三
-- 查找两个表中ID相等的 select a.id, a.name,b.math from stu a,scores b where a.id = b.id -- 右外连接 select b.id, ...
- 异常信息:由于内部错误,服务器无法处理该请求。有关该错误的详细信息,请打开服务器上的 IncludeExceptionDetailInFaults
有方法说找到web.config 文件修改如下(蓝色部分) <behaviors> <serviceBehaviors> <behavior> ...
- 解决plsql工具不能用中文字进行模糊匹配
今天碰到了 select * from table1 t where t.name like '模块a' 查不出数据 而select * from table1 t where t.name like ...
- linux:档案权限
一.例如:-rw-r--r--. 1 root root 129 Dec 29 2013 .tcshrc 详细: 1.-rw-r--r--:档案类型和权限(总共十个栏位) 1.1:第一个栏位代表 ...
- Java线程同步和线程通信
一.线程同步 当多个线程访问同一个数据时,非常容易出现线程安全问题.这时候就需要用线程同步. 不可变类总是线程安全的,因为它的对象状态是不可改变的,但可变类对象需要额外的方法来保证线程安全. 1.同步 ...