位图在内存中的存储方式&各种位图之间的转换

位图在内存中的存储方式

当确定文件是一副bmp图像后,就可以读取它的信息头BITMAPINFOHEADER。其时,前面对CFile操作的从程序,已经将整个文件读到了内存中,并用pBuffer指针指向它的首地址。

该文件在内存中的存储状态如下图所示

也就是说,pBuffer加上BITMAPFILEHEADER的长度,就是BITMAPINFOHEADER的首地址。

BITMAPINFOHEADER * pBIH = ( BITMAPINFOHEADER * ) (pBuffer + sizeof( BITMAPFILEHEADER ));

然后就可以获得诸如位图色深(以得知调色板的大小,对于24、32bit的图像,不存在调色板),图像长、宽等信息。比如:

int nWidth = pBIH->biWidth;

按说,pBuffer加上文件信息的长度,就指向了位图数据区,但BITMAPFILEHEADER中提供了一个元素:bfOffBits,就是从文件起始处到数据区的偏移量。

BYTE pBitBuffer = pBuffer + pBFH->bfOffBits;

这样,就可以通过pBitBuffer来操作位图了

 

各种位图之间的转换

图像文件的格式有多种多样,因为笔者是在Windows环境下编程的,所以通常进行图像处理的是BitMap文件,windows位图文件,该种文件由于其对每个象素的存储字节大小不同可以分成2位、4位、8位、15位、16位、24位和32位图像。一般除了2位的图像只能用黑白图像表示外,其余图像我们均可以为了满足美观程度在位图文件中引进调色板而使图像显示为彩色(在这里需要搞清楚一点就是数据区存放的灰度数据并不能独立表达自己的含义,只有引进调色板时才有其真正含义,所以数据区的灰度数据随着调色板的变化也需要变化)。通常24位以上图片就没必要再引进调色板了,因为它本身自己就能显示RGB真彩色了。

各种位图之间的转换是很常见的,特别是图像处理中通常用到的算法都是直接对8位灰度图像进行处理的,这就必须要在图像处理之前先进行转为8位图像的转换算法。现在先让笔者介绍一下如何完成转8位图像的实现吧:

1、首先取得原图像,如果不是Bitmap位图则转换为Bitmap位图,然后取得该位图的文件头信息BITMAPFILEHEADER、位图头信息BITMAPINFOHEADER、调色板信息,以及数据区的地址信息(一般以上都用指针描述);

2、创建一个新图像,根据原图像信息对文件头信息和位图头信息进行适当修改参数,创建新的调色板,必须满足灰度图像要求的RGB三分量一致;

3、转换部分:根据不同位数的图像,其运算方法又各不相同(低于八位图像不用进行处理)最主要就是要取得转换后的图像灰度数据:

A、对于原来八位的彩色图像,首先根据原有调色板按照一定原则(采用Y=0.3R+0.59G+0.11B公式或者就单一分量公式如Y=R等)将原有调色板中的某一数值转为为真实的8256色灰度时所对应的新调色板的值;根据原有八位灰度数据转换为新调色板。假设原调色板上的序列为pPaletter[i],g[i],b[i])经过转换原则,得到该原调色板所对应的新调色板的序列值为pLooki),则现有一个灰度为pOldGray[i]的原图像灰度值其在新图像中的灰度数据则变为:

pNewGray[i]pLook[pOldGray[i]]

如上就转换完毕了。

B、对于16位色真彩色图像其灰度数据格式为RRRRRGGGGGGBBBBB,所以我们先要取得每一灰度的RGB三分量才能进行运算,用GETRGB565( r, g, b, pData)

{ WORD *wData = (WORD *)pData;

 r= (unsigned char) ( ( (*wData) & 0xf800  ) >> 8 );

 g = (unsigned char) ( ( (*wData) & 0x07e0 ) >> 3);

 b = (unsigned char) ( ( (*wData) & 0x001f ) << 3 ); }其中pData就是数据区指针,

对以上取得的RGB三分量进行一定原则即能转换为合适的8位灰度图像的灰度数据了。

C、对于15位色真彩色图像只不过是其数据格式为0RRRRRGGGGGBBBBB而已,其他都一样的,换算公式为GETRGB565( r, g, b, pData)

{ WORD *wData = (WORD *)pData;

 r= (unsigned char) ( ( (*wData) & 0x7c00 ) >> 7 );

 g = (unsigned char) ( ( (*wData) & 0x03e0 ) >> 2 );

 b = (unsigned char) ( ( (*wData) & 0x001f ) << 3 ); }

B理,对以上取得的RGB三分量进行一定原则即能转换为合适的8位灰度图像的灰度数据了。

D、对于24位真彩色图像其数据格式就更简单了,就是RGB888,相信也不会很难理解吧。但是需要注意的一点就是24位图存放时是以BGR格式存放的。以下就不用我多说了吧?

E、对于32位真彩色图像则其格式为RGBAA为亮度。

好了,经过以上的分析,我觉得各种不同位图之间转换现在应该霍然开朗多了,觉得不是很难了吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值