当前位置:首页 > 芯闻号 > 充电吧
[导读]关于位图数据怎么4字节对齐:假如一张2*2的RGB图片如下:那么它在内存中数据理论应该为(图片数据在内存中是连续的,也就是说一行数据紧接着另一行数据,这里为了直观所以布局成这样)(0xFF 0x00

关于位图数据怎么4字节对齐:

假如一张2*2的RGB图片如下:

那么它在内存中数据理论应该为(图片数据在内存中是连续的,也就是说一行数据紧接着另一行数据,这里为了直观所以布局成这样)

(0xFF 0x00 0x00) (0x00 0xFF 0x00)

(0x00 0x00 0x00) (0xFF 0xFF 0xFF)

但是位图保存到磁盘时规定图片的数据每行的字节数要能被4整除(具体什么的我也不太清楚,对于我们一般人来说,我认为只要知道有这规定就行),对于上面的这张图片它每行数据为6个字节,显然6除以4还于2,显然没有4字节对齐,所以需要在每行数据后面补充2个字节的数据(随便值为多少,只要时2字节就行),因此补充后上图的数据变成:


(0xFF 0x00 0x00) (0x00 0xFF 0x00) (0x00 0x00)

(0x00 0x00 0x00) (0xFF 0xFF 0xFF)(0x00 0x00)

这样子的话将图片保存到磁盘中时就不会出现问题了。(不管图片每个像素是8字节 16字节 还是24字节都一样)


在实际中怎么操作呢,假如我们从摄像头中取出一张2*2的图片如下:


其数据在bitmapData 中,一共6个字节

当我们想要将它保存到磁盘中去时,我们可以调用下面这个函数simple_4ByteAlignment(2,2,bitmapData)(一些说明全在写在下面函数中。)

bool simple_4ByteAlignment(int width, int height, unsigned char * bitmapData)
{
	if (!bitmapData)
	{
		return false;
	}
	unsigned char * fData=0;
	//length 数据的总长度
	//fillCount 每行需要补充的字节数
	int length=0, fillCount=0;

	length = width*3;//这里乘3是因为我们图片为Rgb图片,每个像素占3个字节
	if (length % 4 != 0)//先计算补充字节后,数据的总字节数
	{
		fillCount = 4 - length % 4;
		length += fillCount;
	}
	length *=height;

	//分配相应长度的内存
	fData = (uchar*)malloc(length);

	if (!fData)
	{
		return false;
	}

	memset(fData, 0, length);

	for (size_t i = 0; i < height; i++)
	{
		//由于需要4字节对齐,所以需要对每行进行补充fillCount的字节的数据。
		memcpy(fData+(width*3+ fillCount )*i, bitmapData+width * 3*i, width * 3);
	}

	bool ret=WriteBitmap888ToFile("你要保存的图片的路径.bmp", width, height, (uchar*)fData, length);
	//释放内存  
	free(fData);
	return ret;
}


下面两个为保存图片为bmp格式的函数,一个保存图片为rgb888一个保存为rgb565。

//根据bitmapData的(RGB)数据,保存bitmap  
//filename是要保存到物理硬盘的文件名(包括路径)  
//dateSize 表示图形数据的大小
//bitmapData 数据必须经过4字节对齐
static BOOL WriteBitmap888ToFile(const char * filename, int width, int height, unsigned char * bitmapData, int dateSize)
{

	//填充BITMAPINFOHEADER  
	BITMAPINFOHEADER bitmapInfoHeader;
	memset(&bitmapInfoHeader, 0, sizeof(BITMAPINFOHEADER));
	bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitmapInfoHeader.biWidth = width;
	bitmapInfoHeader.biHeight = height;
	bitmapInfoHeader.biPlanes = 1;
	bitmapInfoHeader.biBitCount = 24;

	bitmapInfoHeader.biCompression = BI_RGB;

	bitmapInfoHeader.biSizeImage = dateSize;


	//填充BITMAPFILEHEADER  
	BITMAPFILEHEADER bitmapFileHeader;
	memset(&bitmapFileHeader, 0, sizeof(BITMAPFILEHEADER));
	bitmapFileHeader.bfType = 0x4d42;   //BM固定为这个
	bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	bitmapFileHeader.bfSize = bitmapFileHeader.bfOffBits + dateSize;
	bitmapFileHeader.bfReserved1 = 0;
	bitmapFileHeader.bfReserved2 = 0;

	FILE * filePtr = 0;       

	fopen_s(&filePtr, filename, "wb");
	if (NULL == filePtr)
	{
		return FALSE;
	}

	fwrite(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);

	fwrite(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);

	fwrite(bitmapData, bitmapInfoHeader.biSizeImage, 1, filePtr);
	fclose(filePtr);
	return TRUE;
}

//根据bitmapData的(RGB)数据,保存bitmap  
//filename是要保存到物理硬盘的文件名(包括路径)  
//dateSize 表示图形数据的大小,
//bitmapData 数据必须经过4字节对齐
static BOOL WriteBitmap565ToFile(const char * filename, int width, int height, unsigned char * bitmapData, int dateSize)
{

	BITMAPFILEHEADER bitmapFileHeader;
	//填充BITMAPINFOHEADER  
	BITMAPINFOHEADER bitmapInfoHeader;

	RGBQUAD bmiColors[3]; //定义调色板

	bitmapFileHeader.bfType = 0x4d42;   //"BM"
	bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 3; 
	bitmapFileHeader.bfSize = bitmapFileHeader.bfOffBits + dateSize;
	bitmapFileHeader.bfReserved1 = 0;
	bitmapFileHeader.bfReserved2 = 0;


	memset(&bitmapInfoHeader, 0, sizeof(BITMAPINFOHEADER));
	bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitmapInfoHeader.biWidth = width;
	bitmapInfoHeader.biHeight = -height;
	bitmapInfoHeader.biPlanes = 1;
	bitmapInfoHeader.biBitCount = 16;
	bitmapInfoHeader.biCompression = BI_BITFIELDS;
	bitmapInfoHeader.biSizeImage = dateSize;


	bmiColors[0].rgbBlue = 0;
	bmiColors[0].rgbGreen = 0xF8;
	bmiColors[0].rgbRed = 0;
	bmiColors[0].rgbReserved = 0;

	bmiColors[1].rgbBlue = 0xE0;
	bmiColors[1].rgbGreen = 0x07;
	bmiColors[1].rgbRed = 0;
	bmiColors[1].rgbReserved = 0;

	bmiColors[2].rgbBlue = 0x1F;
	bmiColors[2].rgbGreen = 0;
	bmiColors[2].rgbRed = 0;
	bmiColors[2].rgbReserved = 0;


	FILE * filePtr = 0;       

	fopen_s(&filePtr, filename, "wb");
	if (NULL == filePtr)
	{
		return FALSE;
	}

	fwrite(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);

	fwrite(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);

	fwrite(bmiColors,3 * sizeof(RGBQUAD), 1, filePtr);

	fwrite(bitmapData, bitmapInfoHeader.biSizeImage, 1, filePtr);
	fclose(filePtr);
	return TRUE;
}



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

其实在 c++语言里面const修饰的才算是一个真正的常量,在 c 语言中 const 可以说是个“冒牌货”。为什么会这样?其实是 c++ 编译器对 const 进行了加强,当 c++ 编译器遇到常量声明时,不会像 c...

关键字: c++ C语言 const

返回函数的引用去初始化一个新的引用这个和前面一样,都是不会产生副本,但是现在是用返回值去初始化一个引用声明c,也就是说这时候变成了变量temp的别名,在c的生命周期内temp是一直有效的,这样做完全可以。

关键字: c++ 返回值 引用声明

C++是一种面向对象的高级程序设计语言,是C语言的超集。

关键字: c++ C语言

2020 年 6 月 21-24 日,第二届北京智源大会将以线上直播形式盛大召开,本届大会邀请了包括 6 位图灵奖获得者 、10 多位院士在内的上百位人工智能领域的顶级专家学者,围绕技术、应用、基础设施等话题展开对话,探...

关键字: 人工智能 位图

(文章来源:全景VR网) 现在的科技发展是真的很快,随着科技的发展又出现了一个新的词汇,那就是虚拟现实全景,很多人都不知道它是什么东西,那今天我们就来看看虚拟现实全景到底是什么?全景虚拟

关键字: 人机交互 虚拟现实技术 VR 位图

“为更好的防控新型冠状病毒,请乘客打开手机,扫描车厢中的二维码进行登记!” 对于这句话,很多人并不陌生,特别是在疫情期间,无论是车站广播,还是巡逻的保安,都会对每一个乘客及用户

关键字: 物联网 条形码 位图 移动互联网

(文章来源:新材发现) 碳纤维复合材料已广泛应用于医学的各个领域,除了用于X光、CT、B超等检查用的碳纤维床板、头托、腹板等常见医疗辅助设备外。碳纤维复合材料在医疗领域中的应用形式越来越

关键字: 碳纤维 金属 X射线 位图

分析:这是Adobe 公司2007 年校园招聘的最新笔试题。这道题除了考察应聘者的C++ 基本功底外,还能考察反应能力,是一道很好的题目。 在Java 中定义了关键字final ,被final 修饰的

关键字: c++ class

泛型算法中的定制操作很多算法都会比较输入序列中的元素,通过定制比较动作,可以控制算法按照编程者的意图工作。本文以string排序为例进行说明,首先是缺省的排序动作: vector v{"This","

关键字: c++

为什么是lambda?讲了这么多天的lambda表达式,有一个很基本的问题没有回答:为什么叫lambda表达式呢?首先这个lambda就是罗马字母λ,lambda表达式即λ表达式。数学上有一个概念叫λ

关键字: c++
关闭
关闭