位图的格式如下:

  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位。

头文件定义:

  1. #pragma pack(1)
  2. typedef unsigned char BYTE ;
  3. typedef unsigned short WORD ;
  4. typedef unsigned int DWORD ;
  5. typedef long LONG ;
  6.  
  7. typedef struct BW_BITMAPFILEHEADER
  8. {
  9. WORD fileType ;
  10. DWORD fileSize ;
  11. WORD fileReserved1 ;
  12. WORD fileReserved2 ;
  13. DWORD offSet ;
  14. } BITMAPFILEHEADER ;
  15. typedef struct BW_BITMAPFINFOHEADER
  16. {
  17. DWORD headSize ;
  18. LONG width ;
  19. LONG height ;
  20. WORD plant ;
  21. WORD bitCount ;
  22. DWORD compression ;
  23. DWORD sizeImage ;
  24. LONG XPelPerMeter ;
  25. LONG YPelPerMeter ;
  26. DWORD clrUsed ;
  27. DWORD clrImportant ;
  28. }BITMAPINFOHEAD;
  29.  
  30. typedef struct BW_RGBQUAD
  31. {
  32. BYTE rgbBlue ;
  33. BYTE rgbGreen ;
  34. BYTE rgbRed ;
  35. BYTE rgbReserved ;
  36. }RGBQUAD;
  37.  
  38. typedef struct BW_PIXEL
  39. {
  40. BYTE blue ;
  41. BYTE green ;
  42. BYTE red ;
  43. } PIXEL ;
  44.  
  45. class BW_BITMAP
  46. {
  47. public:
  48. bool ReadBMP(char*) ;
  49. BITMAPFILEHEADER bitMapFileHeader ;
  50. BITMAPINFOHEAD bitMapInfoHead ;
  51. RGBQUAD *rgbquad ;
  52. PIXEL* pixelData ;
  53. };

具体cpp文件:

  1. bool BW_BITMAP::ReadBMP(char *fileName)
  2. {
  3. FILE *fileR ,fileW ;
  4. fileR = fopen(fileName , "rb") ;
  5. if (fileR != NULL)
  6. {
  7. //BW_BITMAP* bitMap = new BW_BITMAP ;
  8.  
  9. fread(&bitMapFileHeader , , sizeof(BITMAPFILEHEADER) , fileR) ;
  10. if (0x4d42 != bitMapFileHeader.fileType)
  11. {
  12. fclose(fileR) ;
  13. return NULL ;
  14. }
  15. fread(&bitMapInfoHead, , sizeof(BITMAPINFOHEAD) , fileR) ;
  16.  
  17. rgbquad = new RGBQUAD[bitMapInfoHead.clrUsed] ;
  18. for (int icount = ; icount < bitMapInfoHead.clrUsed ; ++icount)
  19. {
  20. fread((char *)&(rgbquad[icount].rgbBlue),,sizeof(BYTE),fileR);
  21. fread((char *)&(rgbquad[icount].rgbGreen),,sizeof(BYTE),fileR);
  22. fread((char *)&(rgbquad[icount].rgbRed),,sizeof(BYTE),fileR);
  23. //fread((char *)&(bitMap->rgbquad[icount].rgbReserved),1,sizeof(BYTE),fileR);
  24. }
  25.  
  26. int width = bitMapInfoHead.width ;
  27.  
  28. int height = bitMapInfoHead.height ;
  29. pixelData = new PIXEL[width * height * sizeof(PIXEL)];
  30. //初始化原始图片的像素数组
  31.  
  32. //fseek(fpi,54,SEEK_SET);
  33. //读出图片的像素数据
  34. fread(pixelData,sizeof(PIXEL) * width,height,fileR);
  35. fclose(fileR);
  36. return true ;
  37. }
  38. else
  39. {
  40. //cout<<"file open error!"<<endl;
  41. return false ;
  42. }
  43. }
  44. }

  

  在写该段代码时要注意在头文件的文件头使用#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)实现及其要点的更多相关文章

  1. (算法)位图BitMap

    题目: 给定一数组,大小为M,数组中的数字范围为1-N,如果某带宽有限,无法传输该大小的数组,该怎么办? 思路: 通过位图BitMap来压缩数组,将数组中每个数字在bit位上标志,这样就可以将数组大小 ...

  2. EmguCV从位图(Bitmap)加载Image<Gray,byte>速度慢的问题

    先说背景.最近在用C#+EmguCV(其实就是用P/Invoke封闭了OpecCV,与OpenCVDotNet差不多) 做一个视频的东西.视频是由摄像头采集回来的1f/s,2048X1000大小,其实 ...

  3. [置顶] 程序员必知(二):位图(bitmap)

    位图是什么? 位图就是数组,一般来说是bit型的数组,具有快速定位某个值的功能,这种思想有很广泛的应用,比如下边两题: 1 找出一个不在5TB个整数中存在的数 假设整数是32位的,总共有4GB个数,我 ...

  4. Android学习之位图BitMap

    BitMap代表一张位图,扩展名可以是.bmp或者.dib.位图是Windows标准格式图形文件,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2.4.8.16.24和32位色彩.例如 ...

  5. [2011-3-9 12:59 ]As3.0中的位图(Bitmap/BitmapData)用法

    1.位图使用(模糊)滤镜 //创建一个矩形区域的BitmapData var bmd:BitmapData = new BitmapData(80, 30, false, 0xefefef); //画 ...

  6. 【索引】位图BitMap索引

    位图(BitMap)索引 前段时间听同事分享,偶尔讲起Oracle数据库的位图索引,顿时大感兴趣.说来惭愧,在这之前对位图索引一无所知,因此趁此机会写篇博文介绍下位图索引. 1. 案例 有张表名为ta ...

  7. android在listview中放入从sdcard读取的bitmap

    重写viewbinder public class viewbinder_bookmark implements SimpleAdapter.ViewBinder{ @Override public ...

  8. 位图bitmap应用

    所有比特的编号方法是,从低字节的低位比特位开始,第一个bit为0,最后一个bit为 n-1. 比如说,现在有个数组是这样子的,int a[4],那么a[0]的比特位为0--31a[1]的比特位为32- ...

  9. redis位图(bitmap)常用命令的解析

    描述   bitmap是redis封装的用于针对位(bit)的操作,其特点是计算效率高,占用空间少,常被用来统计用户签到.登录等场景 常用命令及解析 常用命令 setbit key offset va ...

随机推荐

  1. Unit02: 参数值注入 、 基于注解的组件扫描

    Unit02: 参数值注入 . 基于注解的组件扫描 (4)IOC (Inversion Of Controll 控制反转) 什么是IOC? 对象之间的依赖关系由容器来建立. 什么是DI? (Depen ...

  2. erlang里面中文相关处理

    在控制台输出的话 Name = "测试数据", io:format("~ts~n",[Name]). 如果是和客户端通信,假如都是utf8编码 服务器获取的时候 ...

  3. 将socket程序从linux移植到windows上

    今天突然想试下纯socket编程在两个系统上代码重合量有多大,只要不使用VC自定义的宏(比如SOCKET.SOCKADDR等等)感觉代码重合量挺大的. 比如最简单的TCP客户端和服务端对话,在VC中用 ...

  4. JVM内存管理之垃圾搜集器参数精解

    本文是GC相关的最后一篇,这次LZ只是罗列一下hotspot JVM中垃圾搜集器相关的重点参数,以及各个参数的解释.废话不多说,这就开始. 垃圾搜集器文章传送门 JVM内存管理------JAVA语言 ...

  5. c#通过app.manifest使程序 右键 以管理员身份运行

    c#通过app.manifest使程序以管理员身份运行 时间:2013-06-27 22:47来源:网络收集+本站整理 作者:jtydl 点击: 1175 次 微软在Windows Vista开始引入 ...

  6. POJ 3276 Face The Right Way(反转)

      Face The Right Way Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6038   Accepted: 2 ...

  7. 浅谈PHP面向对象编程(四、类常量和静态成员)

    4.0 类常量和静态成员 通过上几篇博客我们了解到,类在实例化对象时,该对象中的成员只被当前对象所有.如果希望在类中定义的成员被所有实例共享. 此时可以使用类常量或静态成员来实现,接下来将针对类常量和 ...

  8. 2_python之路之多级菜单

    python之路之多级菜单 1.使用知识点 (1)列表,字典的使用 (2)if条件判断语句 (3)for/while循环的使用 2.代码详细 #!/usr/bin/env python # _*_ c ...

  9. Tkinter简易教程

    支持python的常见GUI工具包: Tkinter 使用Tk平台 很容易得到 半标准 wxpython 基于wxWindows.跨平台越来越流行 Python Win 只能在Windows上使用 使 ...

  10. shell基本语法和执行

    执行脚本: 编写一个简单的脚本test.sh: #! /bin/sh cd .. ls Shell脚本中用#表示注释,相当于C语言的//注释.但如果#位于第一行开头,并且是#!(称为Shebang)则 ...