读取位图(bitmap)实现及其要点
位图的格式如下:
1.文件头信息块
0000-0001 :文件标识,为字母ASCII码“BM”。
0002-0005 :文件大小。
0006-0009 :保留,每字节以“00”填写。
000A-000D :记录图像数据区的起始位置。各字节的信息含义依次为:文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)。
2.图像描述信息块
000E-0011:图像描述信息块的大小,常为28H。
0012-0015:图像宽度。
0016-0019:图像高度。
001A-001B:图像的plane总数(恒为1)。
001C-001D:记录像素的位数,很重要的数值,图像的颜色数由该值决定。
001E-0021:数据压缩方式(数值位0:不压缩;1:8位压缩;2:4位压缩)。
0022-0025:图像区数据的大小。
0026-0029:水平每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。
002A-002D:垂直每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。
002E-0031:此图像所用的颜色数,如值为0,表示所有颜色一样重要。
3.颜色表
颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。即首先4字节表示颜色号0的颜色,接下来表示颜色号1的颜色,依此类推。
4.图像数据区
颜色表接下来位是位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位;16色图像每点占4位;256色图像每点占8位;真彩色图像每点占24位。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。 然而,未压缩的图像信息区的大小。除了真彩色模式外,其余的均大于或等于数据信息的大小。这是为什么呢?原因有两个:
1.BMP文件记录一行图像是以字节为单位的。因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。也就是说,设显示模式位16色,在每个字节分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节,这个字节的后4位将没有意义。接下来的一个字节将开始记录下一行的信息。
2.为了显示的方便,除了真彩色外,其他的每中颜色模式的行字节数要用数据“00”补齐为4的整数倍。如果显示模式为16色,当图像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节(加1是因为里面有一个像素点要独占了一字节)。如果显示模式为256色,当图像宽为19时,每行也要补充4-19%4=1个字节。
一下代码实现的是位图宽,高是4的整数倍,颜色位深是24位。
头文件定义:
- #pragma pack(1)
- typedef unsigned char BYTE ;
- typedef unsigned short WORD ;
- typedef unsigned int DWORD ;
- typedef long LONG ;
- typedef struct BW_BITMAPFILEHEADER
- {
- WORD fileType ;
- DWORD fileSize ;
- WORD fileReserved1 ;
- WORD fileReserved2 ;
- DWORD offSet ;
- } BITMAPFILEHEADER ;
- typedef struct BW_BITMAPFINFOHEADER
- {
- DWORD headSize ;
- LONG width ;
- LONG height ;
- WORD plant ;
- WORD bitCount ;
- DWORD compression ;
- DWORD sizeImage ;
- LONG XPelPerMeter ;
- LONG YPelPerMeter ;
- DWORD clrUsed ;
- DWORD clrImportant ;
- }BITMAPINFOHEAD;
- typedef struct BW_RGBQUAD
- {
- BYTE rgbBlue ;
- BYTE rgbGreen ;
- BYTE rgbRed ;
- BYTE rgbReserved ;
- }RGBQUAD;
- typedef struct BW_PIXEL
- {
- BYTE blue ;
- BYTE green ;
- BYTE red ;
- } PIXEL ;
- class BW_BITMAP
- {
- public:
- bool ReadBMP(char*) ;
- BITMAPFILEHEADER bitMapFileHeader ;
- BITMAPINFOHEAD bitMapInfoHead ;
- RGBQUAD *rgbquad ;
- PIXEL* pixelData ;
- };
具体cpp文件:
- bool BW_BITMAP::ReadBMP(char *fileName)
- {
- FILE *fileR ,fileW ;
- fileR = fopen(fileName , "rb") ;
- if (fileR != NULL)
- {
- //BW_BITMAP* bitMap = new BW_BITMAP ;
- fread(&bitMapFileHeader , , sizeof(BITMAPFILEHEADER) , fileR) ;
- if (0x4d42 != bitMapFileHeader.fileType)
- {
- fclose(fileR) ;
- return NULL ;
- }
- fread(&bitMapInfoHead, , sizeof(BITMAPINFOHEAD) , fileR) ;
- rgbquad = new RGBQUAD[bitMapInfoHead.clrUsed] ;
- for (int icount = ; icount < bitMapInfoHead.clrUsed ; ++icount)
- {
- fread((char *)&(rgbquad[icount].rgbBlue),,sizeof(BYTE),fileR);
- fread((char *)&(rgbquad[icount].rgbGreen),,sizeof(BYTE),fileR);
- fread((char *)&(rgbquad[icount].rgbRed),,sizeof(BYTE),fileR);
- //fread((char *)&(bitMap->rgbquad[icount].rgbReserved),1,sizeof(BYTE),fileR);
- }
- int width = bitMapInfoHead.width ;
- int height = bitMapInfoHead.height ;
- pixelData = new PIXEL[width * height * sizeof(PIXEL)];
- //初始化原始图片的像素数组
- //fseek(fpi,54,SEEK_SET);
- //读出图片的像素数据
- fread(pixelData,sizeof(PIXEL) * width,height,fileR);
- fclose(fileR);
- return true ;
- }
- else
- {
- //cout<<"file open error!"<<endl;
- return false ;
- }
- }
- }
在写该段代码时要注意在头文件的文件头使用#pragma pack(1),这是告诉编译器使用边界1对齐(也就是不对齐)。
如果不是用#pragma pack(1),经过测试有如下结果:sizeof(BITMAPFILEHEADER)的值为16,而不是14。说明编译器对其使用了4为边界对齐。
如果实在linux环境下,要使用__attribute__((packed))来实现相同的效果。
但是,在xcode 5.0下用#pragma pack(1) 居然可以~!
总结可知:在实现对数据格式有严格要求的功能时,要注意到编译器的优化带来的麻烦。而且要注意PIXEL的定义,一定不能写成red ,green ,blue 。
读取位图(bitmap)实现及其要点的更多相关文章
- (算法)位图BitMap
题目: 给定一数组,大小为M,数组中的数字范围为1-N,如果某带宽有限,无法传输该大小的数组,该怎么办? 思路: 通过位图BitMap来压缩数组,将数组中每个数字在bit位上标志,这样就可以将数组大小 ...
- EmguCV从位图(Bitmap)加载Image<Gray,byte>速度慢的问题
先说背景.最近在用C#+EmguCV(其实就是用P/Invoke封闭了OpecCV,与OpenCVDotNet差不多) 做一个视频的东西.视频是由摄像头采集回来的1f/s,2048X1000大小,其实 ...
- [置顶] 程序员必知(二):位图(bitmap)
位图是什么? 位图就是数组,一般来说是bit型的数组,具有快速定位某个值的功能,这种思想有很广泛的应用,比如下边两题: 1 找出一个不在5TB个整数中存在的数 假设整数是32位的,总共有4GB个数,我 ...
- Android学习之位图BitMap
BitMap代表一张位图,扩展名可以是.bmp或者.dib.位图是Windows标准格式图形文件,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2.4.8.16.24和32位色彩.例如 ...
- [2011-3-9 12:59 ]As3.0中的位图(Bitmap/BitmapData)用法
1.位图使用(模糊)滤镜 //创建一个矩形区域的BitmapData var bmd:BitmapData = new BitmapData(80, 30, false, 0xefefef); //画 ...
- 【索引】位图BitMap索引
位图(BitMap)索引 前段时间听同事分享,偶尔讲起Oracle数据库的位图索引,顿时大感兴趣.说来惭愧,在这之前对位图索引一无所知,因此趁此机会写篇博文介绍下位图索引. 1. 案例 有张表名为ta ...
- android在listview中放入从sdcard读取的bitmap
重写viewbinder public class viewbinder_bookmark implements SimpleAdapter.ViewBinder{ @Override public ...
- 位图bitmap应用
所有比特的编号方法是,从低字节的低位比特位开始,第一个bit为0,最后一个bit为 n-1. 比如说,现在有个数组是这样子的,int a[4],那么a[0]的比特位为0--31a[1]的比特位为32- ...
- redis位图(bitmap)常用命令的解析
描述 bitmap是redis封装的用于针对位(bit)的操作,其特点是计算效率高,占用空间少,常被用来统计用户签到.登录等场景 常用命令及解析 常用命令 setbit key offset va ...
随机推荐
- Unit02: 参数值注入 、 基于注解的组件扫描
Unit02: 参数值注入 . 基于注解的组件扫描 (4)IOC (Inversion Of Controll 控制反转) 什么是IOC? 对象之间的依赖关系由容器来建立. 什么是DI? (Depen ...
- erlang里面中文相关处理
在控制台输出的话 Name = "测试数据", io:format("~ts~n",[Name]). 如果是和客户端通信,假如都是utf8编码 服务器获取的时候 ...
- 将socket程序从linux移植到windows上
今天突然想试下纯socket编程在两个系统上代码重合量有多大,只要不使用VC自定义的宏(比如SOCKET.SOCKADDR等等)感觉代码重合量挺大的. 比如最简单的TCP客户端和服务端对话,在VC中用 ...
- JVM内存管理之垃圾搜集器参数精解
本文是GC相关的最后一篇,这次LZ只是罗列一下hotspot JVM中垃圾搜集器相关的重点参数,以及各个参数的解释.废话不多说,这就开始. 垃圾搜集器文章传送门 JVM内存管理------JAVA语言 ...
- c#通过app.manifest使程序 右键 以管理员身份运行
c#通过app.manifest使程序以管理员身份运行 时间:2013-06-27 22:47来源:网络收集+本站整理 作者:jtydl 点击: 1175 次 微软在Windows Vista开始引入 ...
- POJ 3276 Face The Right Way(反转)
Face The Right Way Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6038 Accepted: 2 ...
- 浅谈PHP面向对象编程(四、类常量和静态成员)
4.0 类常量和静态成员 通过上几篇博客我们了解到,类在实例化对象时,该对象中的成员只被当前对象所有.如果希望在类中定义的成员被所有实例共享. 此时可以使用类常量或静态成员来实现,接下来将针对类常量和 ...
- 2_python之路之多级菜单
python之路之多级菜单 1.使用知识点 (1)列表,字典的使用 (2)if条件判断语句 (3)for/while循环的使用 2.代码详细 #!/usr/bin/env python # _*_ c ...
- Tkinter简易教程
支持python的常见GUI工具包: Tkinter 使用Tk平台 很容易得到 半标准 wxpython 基于wxWindows.跨平台越来越流行 Python Win 只能在Windows上使用 使 ...
- shell基本语法和执行
执行脚本: 编写一个简单的脚本test.sh: #! /bin/sh cd .. ls Shell脚本中用#表示注释,相当于C语言的//注释.但如果#位于第一行开头,并且是#!(称为Shebang)则 ...