就填充方式来说,跟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;
}
版权声明:本文为humadivinity原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。