版权声明:本文为博主原创文章,转载申明
最近几天做了一个还原串口传输的rgb565数据为图片的上位机,
中间过程遇到最大的困难便是不知道如何去正确的写入位图数据。
因为过去都是直接还原灰度图,没有涉及过还原彩色图片,所以一开始的时候遇到过很多的不解,
简单的认为rgb565的位图数据大小只是图片的长X宽,到后来了解到串口最长只能发送8个bit,
而同样以BYTE型数组存储的rgb565的位图数据正好也是8位,
所以正确的16位的rgb565位图数据大小应该是长X宽X2;
这也符合了bmp文件格式中所规定的位图数据大小:BPP * Width * Height/8(BPP是每像素的比特数(Bits Per Pixel),即biBitCount,Width是宽度,Height是高度)。当初没有看到这一点瞎忙活了半天。。。
之后便是关于如何添加文件头和位图信息头,因为是16位的真彩图,不需要去添加调色板所以只需要正确设置文件头和位图信息头即可,
而MFC最为方便的一点便是提供了一个CImage::CImage的 构造函数;我们只需要去创建一个
CImage m_COMImage;
就可以去接受位图数据啦,前提是你要设置好前面所提到的文件头和位图信息头(搞来搞去还是要设置。。。)
但是,重点来了,
这个设置只需要一句代码
//初始化image
DWORD adwBitmasks[3] = { 0x0000F800, 0x000007E0, 0x0000001F }; //设置掩码
image.CreateEx(width, height, 16, BI_BITFIELDS, adwBitmasks, 0); //宽度高度和位数
差不多一句。。。
下面是vs2015c++的官方文档对CreateEx这个函数的解释:
BOOL CreateEx(
int nWidth,
int nHeight,
int nBPP,
DWORD eCompression,
const DWORD* pdwBitmasks = NULL,
DWORD dwFlags = 0
) throw( );
nWidth
CImage 位图的宽度,以像素为单位。
nHeight
CImage 位图的高度,均以像素。 如果 nHeight 为正数的,位图是一个从下到上DIB,并且原点是左下角。 如果 nHeight 为负,位图是一组DIB,并且原点为左上角。
nBPP
位的数目每在位图的像素。 通常4,8,16,24或32。 可以是1单色位图或掩码。
eCompression
为压缩的位图指定压缩的类型(自下而上的 DIB 不能压缩)。 可为下列值之一:
BI_RGB 该格式被解压缩。 指定此值,在调用 CImage::CreateEx 时与调用 CImage::Create等效。
BI_BITFIELDS布局是解压缩,而且颜色表包含指定红色,绿色和蓝色分量,分别,每个像素的三 DWORD 颜色掩码。 这是有效的,但在用于16位和32-bpp位图。
初始化完成后就需要写入位图数据了,主要是利用两个嵌套for循环去一行一行写入位图数据。
在写入数据的时候要格外的小心,注意你当初设置的高度是正数还是负数,因为这个关系到写入位图数据的起点,不然很可能在写入位图数据时造成数组的越界。
也可以通过CImage::GetPitch先去读取图像的间距,确定写入位图数据的起点,
下面是vs2015c++的官方文档对GetPitch这个函数的解释:
返回值
图像的间距。 如果返回值为负,位图是一个从下到上DIB,并且原点是左下角。 如果返回值为正的,位图是一组DIB,并且原点为左上角。
备注
间距是距离,在字节,在表示一个位图行开头和位图下一行的开头的两个内存地址之间。 由于间距以字节为单位,图像帮助的间距确定像素格式的。 间距还可以包括附加的内存,预留位图。