保存原始rgb8bit 数据到bmp文件

就填充方式来说,跟24位位图基本是一样的,不同的是bitcolor 位设置的颜色位数要填充为8,而不是24.

百度了很久,目前只能是勉强能保存成图片,能正常打开,但目前还有未能理解的问题,列举如下,如果有知道的朋友,希望能得到您的慷慨解惑,感激不尽!

1、8bit 的bmp图如何控制颜色的显示,我尝试过对每个字节进行0或255的颜色替换,以期待生成黑白图,但实际替换颜色后的图片全是黑色的一片,根本看不到具体内容

2、猜想问题1,是不是需要在bmp文件头中加入调色板,以支持颜色的显示?如果需要的话,这个调色板信息该怎么加,我在百度上找了好久都没找到。

3、8bit 的rgb 数据要怎么才能转换成 24bit的BMP图呢,简单的颜色扩充吗?

图片文件

原始封装函数如下

int simplest_bgr8_to_bmp(uint8_t*pSrcBuffer, int32_t iBufferLen, int32_t width, int32_t height, uint8_t * pDestBuffer, int32_t* OutPutLength)
{
//结构体1字节对齐
#pragma pack(push)
#pragma pack(1)
	typedef struct
	{
		int32_t imageSize;
		int32_t blank;
		int32_t startPosition;
	}BmpHead;

	typedef struct
	{
		int32_t  Length;
		int32_t  width;
		int32_t  height;
		uint16_t  colorPlane;
		uint16_t  bitColor;
		int32_t  zipFormat;
		int32_t  realSize;
		int32_t  xPels;
		int32_t  yPels;
		int32_t  colorUse;
		int32_t  colorImportant;
	}InfoHead;
#pragma pack(pop)


	//int i = 0, j = 0;
	BmpHead m_BMPHeader = { 0, 0, 0 };

	InfoHead  m_BMPInfoHeader = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
	char bfType[2] = { 'B', 'M' };
	int header_size = sizeof(bfType) + sizeof(BmpHead) + sizeof(InfoHead);
	unsigned char *rgb24_buffer = pSrcBuffer;
	unsigned char *pDest = pDestBuffer;

	m_BMPHeader.imageSize = 1 * width*height + header_size;
	m_BMPHeader.startPosition = header_size;

	m_BMPInfoHeader.Length = sizeof(InfoHead);
	m_BMPInfoHeader.width = (width+3)/4 *4;    //这里不确定是否要给4字节对齐后的长度,但放进去似乎也没啥影响,希望后面有朋友看到后,能帮忙解惑

    //图像分辩率这块不知道怎么填,不知道是不是填图像宽高,但不填似乎也能正常打开图片

	//BMP storage pixel data in opposite direction of Y-axis (from bottom to top).
	m_BMPInfoHeader.height = -height;
	m_BMPInfoHeader.colorPlane = 1;
	m_BMPInfoHeader.bitColor = 1*8;
	m_BMPInfoHeader.realSize = 1 * width*height;

	memcpy(pDest, bfType, sizeof(bfType));
	pDest += sizeof(bfType);
	memcpy(pDest, &m_BMPHeader, sizeof(m_BMPHeader));
	pDest += sizeof(m_BMPHeader);
	memcpy(pDest, &m_BMPInfoHeader, sizeof(m_BMPInfoHeader));
	pDest += sizeof(m_BMPInfoHeader);

	*OutPutLength = 1 * width*height + sizeof(bfType) + sizeof(m_BMPHeader) + sizeof(m_BMPInfoHeader);

	//memcpy(pDest, rgb24_buffer, iBufferLen); 

/*注意,这里不能直接复制数据,因为有对齐要求(每行宽度要进行4字节对齐),只能一行一行来填充,
* 否则图像会扭曲。
*/

	int iLength = 0;
	int iOffSet = 0;
	for (int j = 0; j < height; j++)
	{
		memcpy(pDest + iLength, rgb24_buffer + iOffSet, width);
		iLength += m_BMPInfoHeader.width;
		iOffSet += width;
	}

	return 0;
}

接上面,增加了颜色表后,图片显示正常了,看来果然是颜色表的问题,附修改后的代码

int simplest_bgr8_to_bmp(uint8_t*pSrcBuffer, int32_t iBufferLen, int32_t width, int32_t height, uint8_t * pDestBuffer, int32_t* OutPutLength)
{
#pragma pack(push)
#pragma pack(1)
	typedef struct
	{
		int32_t imageSize;
		int32_t blank;
		int32_t startPosition;
	}BmpHead;

	typedef struct
	{
		int32_t  Length;
		int32_t  width;
		int32_t  height;
		uint16_t  colorPlane;
		uint16_t  bitColor;
		int32_t  zipFormat;
		int32_t  realSize;
		int32_t  xPels;
		int32_t  yPels;
		int32_t  colorUse;
		int32_t  colorImportant;
	}InfoHead;
#pragma pack(pop)

	const int icolor_table_size = 4 * 256;
	unsigned char * color_table = new unsigned char[icolor_table_size];

	unsigned char red[256] = { 0, 128, 0, 128, 0, 128, 0, 192, 192, 166, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96,
		128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32,
		64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224,
		0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192,
		224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160,
		192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128,
		160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96,
		128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64,
		96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32,
		64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0,
		32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 255, 160,
		128, 255, 0, 255, 0, 255, 0, 255 };

	unsigned char green[256] = { 0, 0, 128, 128, 0, 0, 128, 192, 220, 202, 32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64,
		64, 64, 64, 96, 96, 96, 96, 96, 96, 96, 96, 128, 128, 128, 128, 128, 128, 128, 128, 160, 160, 160, 160,
		160, 160, 160, 160, 192, 192, 192, 192, 192, 192, 192, 192, 224, 224, 224, 224, 224, 224, 224, 224, 0,
		0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 64, 64, 96, 96, 96, 96, 96,
		96, 96, 96, 128, 128, 128, 128, 128, 128, 128, 128, 160, 160, 160, 160, 160, 160, 160, 160, 192, 192, 192,
		192, 192, 192, 192, 192, 224, 224, 224, 224, 224, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32,
		32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 64, 64, 96, 96, 96, 96, 96, 96, 96, 96, 128, 128, 128, 128, 128,
		128, 128, 128, 160, 160, 160, 160, 160, 160, 160, 160, 192, 192, 192, 192, 192, 192, 192, 192, 224, 224,
		224, 224, 224, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64,
		64, 64, 64, 96, 96, 96, 96, 96, 96, 96, 96, 128, 128, 128, 128, 128, 128, 128, 128, 160, 160, 160, 160,
		160, 160, 160, 160, 192, 192, 192, 192, 192, 192, 251, 160, 128, 0, 255, 255, 0, 0, 255, 255 };

	unsigned char blue[256] = { 0, 0, 0, 0, 128, 128, 128, 192, 192, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
		64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
		64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
		128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
		128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
		128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192,
		192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
		192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
		192, 192, 192, 240, 164, 128, 0, 0, 0, 255, 255, 255, 255 };

	for (int i = 0; i < 256; i++)
	{
		color_table[0 + 4 * i] = red[i];
		color_table[1 + 4 * i] = green[i];
		color_table[2 + 4 * i] = blue[i];
		color_table[3 + 4 * i] = (unsigned char)(0x00);
	}

    //灰度图颜色表
	//for (int i = 0; i < 256; i++)
	//{
	//	color_table[0 + 4 * i] = (unsigned char)i;
	//	color_table[1 + 4 * i] = (unsigned char)i;
	//	color_table[2 + 4 * i] = (unsigned char)i;
	//	color_table[3 + 4 * i] = (unsigned char)(0xff);
	//}

	BmpHead m_BMPHeader = { 0, 0, 0 };

	InfoHead  m_BMPInfoHeader = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
	char bfType[2] = { 'B', 'M' };
	int header_size = sizeof(bfType) + sizeof(BmpHead) + sizeof(InfoHead) + icolor_table_size;
	unsigned char *rgb24_buffer = pSrcBuffer;
	unsigned char *pDest = pDestBuffer;

	m_BMPHeader.imageSize = 1 * width*height + header_size;
	m_BMPHeader.startPosition = header_size;

	m_BMPInfoHeader.Length = sizeof(InfoHead);
	m_BMPInfoHeader.width = (width+3)/4 *4;
	//BMP storage pixel data in opposite direction of Y-axis (from bottom to top).
	m_BMPInfoHeader.height = -height;
	m_BMPInfoHeader.colorPlane = 1;
	m_BMPInfoHeader.bitColor = 1*8;
	m_BMPInfoHeader.realSize = 1 * width*height;

	memcpy(pDest, bfType, sizeof(bfType));
	pDest += sizeof(bfType);
	memcpy(pDest, &m_BMPHeader, sizeof(m_BMPHeader));
	pDest += sizeof(m_BMPHeader);
	memcpy(pDest, &m_BMPInfoHeader, sizeof(m_BMPInfoHeader));
	pDest += sizeof(m_BMPInfoHeader);

	memcpy(pDest, color_table, icolor_table_size);
	pDest += icolor_table_size;

	*OutPutLength = 1 * width*height + sizeof(bfType) + sizeof(m_BMPHeader) + sizeof(m_BMPInfoHeader) + icolor_table_size;

	int iLength = 0;
	int iOffSet = 0;
	for (int j = 0; j < height; j++)
	{
		memcpy(pDest + iLength, rgb24_buffer + iOffSet, width);
		iLength += m_BMPInfoHeader.width;
		iOffSet += width;
	}

	delete[] color_table;
	color_table = NULL;

	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个将RGB565数据保存BMP文件的Java方法: ```java public static void saveRGB565ToBMP(int width, int height, byte[] data, File file) throws IOException { int rowLength = width * 2; byte[] rowPadding = new byte[(4 - rowLength % 4) % 4]; int pixelArraySize = rowLength * height; int fileSize = pixelArraySize + 54; byte[] bmpData = new byte[fileSize]; // BMP Header bmpData[0] = 'B'; // Magic number bmpData[1] = 'M'; // Magic number ByteBuffer.wrap(bmpData, 2, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(fileSize); // File size ByteBuffer.wrap(bmpData, 10, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(54); // Offset to pixel array ByteBuffer.wrap(bmpData, 14, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(40); // DIB Header size ByteBuffer.wrap(bmpData, 18, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(width); // Image width ByteBuffer.wrap(bmpData, 22, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(height); // Image height ByteBuffer.wrap(bmpData, 26, 2).order(ByteOrder.LITTLE_ENDIAN).putShort((short) 1); // Color planes ByteBuffer.wrap(bmpData, 28, 2).order(ByteOrder.LITTLE_ENDIAN).putShort((short) 16); // Bits per pixel ByteBuffer.wrap(bmpData, 34, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(pixelArraySize); // Pixel array size // Pixel array int bmpOffset = 54; int dataOffset = 0; for (int y = height - 1; y >= 0; y--) { for (int x = 0; x < width; x++) { byte b1 = data[dataOffset++]; byte b2 = data[dataOffset++]; int r = ((b2 & 0xF8) >> 3) << 16; int g = (((b2 & 0x07) << 3) | ((b1 & 0xE0) >> 5)) << 8; int b = (b1 & 0x1F) << 3; int rgb = r | g | b; ByteBuffer.wrap(bmpData, bmpOffset, 3).order(ByteOrder.LITTLE_ENDIAN).putInt(rgb); bmpOffset += 3; } bmpOffset += rowPadding.length; } // Write BMP data to file try (FileOutputStream fos = new FileOutputStream(file)) { fos.write(bmpData); } } ``` 该方法使用Java的ByteBuffer类来处理字节序和字节对齐,实现了将RGB565数据保存BMP文件的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值