bitmap格式分析
位图(Bitmap)当然是最简单的,它Windows显示图片的基本格式,其文件扩展名为*.BMP。在Windows下,任何各式的图片文件(包括视频播放)都要转化为位图个时候才能显示出来,各种格式的图片文件也都是在位图格式的基础上采用不同的压缩算法生成的(Flash中使用了适量图,是按相同颜色区域存储的)。
一、下面我们来看看位图文件(*.BMP)的格式。
位图文件主要分为如下3个部分:
1、 文件信息头BITMAPFILEHEADER
结构体定义如下:
typedef struct tagBITMAPFILEHEADER { /* bmfh */
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
其中:
2、位图信息头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;
其中:
3、RGB颜色阵列
有关RGB三色空间我想大家都很熟悉,这里我想说的是在Windows下,RGB颜色阵列存储的格式其实BGR。也就是说,对于24位的RGB位图像素数据格式是:
蓝色B值 绿色G值 红色R值
对于32位的RGB位图像素数据格式是:
蓝色B值 绿色G值 红色R值 透明通道A值
透明通道也称Alpha通道,该值是该像素点的透明属性,取值在0(全透明)到255(不透明)之间。对于24位的图像来说,因为没有Alpha通道,故整个图像都不透明。
二、搞清了文件格式,下一步我们要实现加载。
加载文件的目的是要得到图片属性,以及RGB数据,然后可以将其绘制在DC上(GDI),或是生成纹理对象(3D:OpenGL/Direct3D)。这两种用途在数据处理上有点区别,我们主要按前一种用法讲,在和3D有不同的地方,我们再提出来。
1、加载文件头
//Load the file header
BITMAPFILEHEADER header;
memset(&header, 0, sizeof(header));
inf.read((char*)&header, sizeof(header));
if(header.bfType != 0x4D42)
return false;
这个很简单,没有什么好说的。
2、加载位图信息头
//Load the image information header
BITMAPINFOHEADER infoheader;
memset(&infoheader, 0, sizeof(infoheader));
inf.read((char*)&infoheader, sizeof(infoheader));
m_iImageWidth = infoheader.biWidth;
m_iImageHeight = infoheader.biHeight;
m_iBitsPerPixel = infoheader.biBitCount;
这里我们得到了3各重要的图形属性:宽,高,以及每个像素颜色所占用的位数。
3、行对齐
由于Windows在进行行扫描的时候最小的单位为4个字节,所以当
图片宽 X 每个像素的字节数 != 4的整数倍
时要在每行的后面补上缺少的字节,以0填充(一般来说当图像宽度为2的幂时不需要对齐)。位图文件里的数据在写入的时候已经进行了行对齐,也就是说加载的时候不需要再做行对齐。但是这样一来图片数据的长度就不是:宽 X 高 X 每个像素的字节数 了,我们需要通过下面的方法计算正确的数据长度:
//Calculate the image data size
int iLineByteCnt = (((m_iImageWidth*m_iBitsPerPixel) + 31) >> 5) << 2;
m_iImageDataSize = iLineByteCnt * m_iImageHeight;
4、加载图片数据
对于24位和32位的位图文件,位图数据的偏移量为sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER),也就是说现在我们可以直接读取图像数据了。
if(m_pImageData) delete []m_pImageData;
m_pImageData = new unsigned char[m_iImageDataSize];
inf.read((char*)m_pImageData, m_iImageDataSize);
如果你足够细心,就会发现内存m_pImageData里的数据的确是BGR格式,可以用个纯蓝色或者是纯红色的图片测试一下。
5、绘制
好了,数据和属性我们都有了,现在就可以拿来随便用了,就和吃馒头一样,爱粘白糖粘白糖,爱粘红糖粘红糖。下面是我的GDI绘制代码,仅作参考。
void CImage::DrawImage(HDC hdc, int iLeft, int iTop, int iWidth, int iHeight)
{
if(!hdc || m_pImageData == NULL)
return;
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
bmi.bmiHeader.biWidth = m_iImageWidth;
bmi.bmiHeader.biHeight = m_iImageHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = m_iBitsPerPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = m_iImageDataSize;
StretchDIBits(hdc, iLeft, iTop, iWidth, iHeight,
0, 0, m_iImageWidth, m_iImageHeight,
m_pImageData, &bmi, DIB_RGB_COLORS, SRCCOPY);
}
6、3D(OpenGL)的不同之处
如果你是想用刚才我们得到的数据生成纹理对象,那么你还要请出下面的问题。
首先,用来生成纹理的数据不需要对齐,也就是说不能在每行的后面加上对齐的字节。当然在OpenGL里要求纹理图片的尺寸为2的幂,所以这个问题实际上不存在;
其次,我们得到的图形数据格式是BGR(BGRA),所以在生成纹理的时候,需指定格式为GL_BGR_EXT(GL_BGRA_EXT);否则需要做BGR->RGB(BGRA->RGBA)的转化。
bitmap格式分析的更多相关文章
- bitmap格式分析(转)
源:bitmap格式分析 参考:bitmap图像介绍 最近正在着手开发一个图片库,也就是实现对常见图片格式的度写操作.作为总结与积累,我会把这些图片格式以及加载的实现写在我的Blog上. 说到图片,位 ...
- 10、bitmap格式分析
说到图片,位图(Bitmap)当然是最简单的,它Windows显示图片的基本格式,其文件扩展名为*.BMP.在Windows下,任何各式的图片文件(包括视频播放)都要转化为位图个时候才能显示出来,各种 ...
- HTTP POST请求报文格式分析与Java实现文件上传
时间 2014-12-11 12:41:43 CSDN博客 原文 http://blog.csdn.net/bboyfeiyu/article/details/41863951 主题 HTTPHt ...
- X264库直接压缩BITMAP格式数据
最近帮朋友看了下X264压缩视频,主要参考了雷霄骅(leixiaohua1020)的专栏的开源代码: http://blog.csdn.net/leixiaohua1020/article/detai ...
- zw版【转发·台湾nvp系列Delphi例程】HALCON HImage与Bitmap格式转换
zw版[转发·台湾nvp系列Delphi例程]HALCON HImage与Bitmap格式转换 (Delphi Prism)namespace HImage_Bitmap_Prism;interfac ...
- Bitmap的分析与使用.md
https://github.com/GeniusVJR/LearningNotes/blob/master/Part1/Android/Bitmap的分析与使用.md
- AAC 格式分析
一直在做一个语音项目,到了测试阶段,近来不是很忙,想把之前做的内容整理一下. 关于AAC音频格式基本情况,可参考维基百科http://en.wikipedia.org/wiki/Advanced_Au ...
- AAC ADTS AAC LATM 格式分析
http://blog.csdn.net/tx3344/article/details/7414543# 目录(?)[-] ADTS是个啥 ADTS内容及结构 将AAC打包成ADTS格式 1.ADTS ...
- Google的Protocol Buffer格式分析
[转]转自:序列化笔记之一:Google的Protocol Buffer格式分析 从公开介绍来看,ProtocolBuffer(PB)是google 的一种数据交换的格式,它独立于语言,独立于平台.作 ...
随机推荐
- Monkey学习(4)简单测试实例
1.首先测试设备是否连接成功,在命令行中输入: adb devices 如果出现设备信息,代表链接成功.我这里的设备名称是“emulator-5554” 2.得到测试apk的包名,如果有APK源码包的 ...
- Android网络编程系列 一 Socket抽象层
在<Android网络编程>系列文章中,前面已经将Java的通信底层大致的描述了,在我们了解了TCP/IP通信族架构及其原理,接下来我们就开始来了解基于tcp/ip协议层的Socket抽 ...
- NSString / NSData / char* 类型之间的转换
转自网络: NSString / NSData / char* 类型之间的转换 1. NSString转化为UNICODE String: (NSString*)fname = @“Test”; ch ...
- js boolean 判断
在写项目的时候出现了一个这样的问题,虽然问题解决了,但是还是有点疑问. 在数据库中设计的表的一个字段为是否审核(is_vaild) 类型 tinyint(1) 对应的在 java中就是布尔类型(boo ...
- [转载]最牛B的编码套路
原文地址:http://www.codeceo.com/article/nb-coding-style.html 这篇文章很不错,推荐给大家看. 最近,我大量阅读了Steve Yegge的文章.其中有 ...
- azure git 托管
azure git上传部署步骤:(首次提交)cd 至本地代码路径git initgit add .git commit –m "initial commit"git remote ...
- drupal 2016-11-3
我随意定义了一个hook menu发现里面的内容很快就加入到了navigation menu里面.
- sizeof和strlen()的区别
二者有本质上的区别 从定义可以知道sizeof只是一个operator,而strlen()则是定义一个定义在<string.h>中的函数;所以sizeof(string)是在计算strin ...
- centos7 修改selinux 开机导致 faild to load SELinux policy freezing 错误
centos7 修改selinux 开机导致 faild to load SELinux policy freezing 错误 之前把selinux关闭了,这次想打开selinux,于是修改了 /e ...
- Unity3D Mecanim 动画系统骨骼动画问题解决方法
http://7dot9.com/2014/08/16/unity3d-mecanim%E5%8A%A8%E7%94%BB%E7%B3%BB%E7%BB%9F%E9%AA%A8%E9%AA%BC%E5 ...