LPBITMAPCOREHEADER是什么意思?
发布网友
发布时间:2022-04-30 08:16
我来回答
共1个回答
热心网友
时间:2022-06-19 15:40
好好看看百度的BMP格式百科,你就明白了。
首先你不是获得了DIB位图的句柄lpDIB 了吗?
这个lpDIB里面有哪些东西呢?
首先是DIB头文件(好像是40字节,就是首地址*lpDIB)
注意这里的lpDIB因为读取BMP文件之后得到的地址所以不包含BMP文件的文件头。
然后看你的DIB位图的存储格式了
你的例子中采用了256色位图,有调色板,如果有调色板的话
调色板的首地址就是*lpDIB+40,也就是向后偏移40字节就是调色板了。
调色板构成,1个索引占3-4字节,不同的系统编码不一样。
单色位图的调色板是只有1个索引4个字节
16色有16个索引16*4个字节
256色位图有256个索引256*4个字节
16、24、32有的有调色板,有的没有,自己看BMP文件百科去
接下来就是像素在图像数据中的存储,首地址是*lpDIB+40+相应的调色板大小
单色位图是一个字节代表8个像素,例如:FF换算成机器位就是11111111,表示前8位都是白色的
256色位图是1个字节代表1个像素,例如:FF换成十进制就是255,表示调色板第256个索引所代表的颜色。
16位顾名思义就是2个字节代表一个像素(没有调色板,直接表示RGB三个分量),然后被RGB三个 分量均分,留一个机器位做保留位
例如:FFFF 换算成机器位就是1 11111 11111 11111,RGB三个分量分别是11111,我用空格分隔开了。
32位同样是32个机器位表示1个像素,也就是4个字节,当无调色板时,1个字节保留,3个字节分别代表RGB分量。
所以理论上来说,所有的DIB图像处理,都可以想象成一个长长的字符串,然后你就可以按照顺序来进行指针操作。不过在处理图像之前需要从DIB头文件中获取图像信息,你可以定义LPBITMAPINFO变量类型来获取各种图像信息,比如高度、宽度、像素占用机器位数等等
我手里有自己做的2色位图转换成256色位图的源代码,你可以参考一下,道理是一样的。
/****************************************************
*
* 函数名称:
* TwoTo256()
*
* 参数:
* LPSTR lpDIB - 指向源DIB图像指针
*
* 返回值:
* HGLOBAL - 成功返回转化为256色图像句柄,否则返回NULL。
*
* 说明:
* 该函数将一个单色位图的转化为256色黑白位图,
*单色位图一个字节表示8个像素,256色图像一个字节表示一个像素,
* 为了方便像素的运算处理,而特意制作该函数。
****************************************************/
HGLOBAL WINAPI TwoTo256(LPSTR lpDIB)
{
// 源图像的宽度和高度
LONGlWidth;
LONGlHeight;
// 目的图像的宽度和高度
LONGlNewWidth;
LONGlNewHeight;
// 目的图像的宽度(lNewWidth',必须是4的倍数)
LONGlNewLineBytes;
// 指向源图像的指针
LPSTRlpDIBBits;
// 指向源象素的指针
LPSTRlpSrc;
// 目的图像的DIB句柄
HDIB hDIB;
// 指向目的图像对应象素的指针
LPSTRlpDst;
// 指向目的图像的指针
LPSTRlpNewDIB;
LPSTRlpNewDIBBits;
// 指向BITMAPINFOHEADER结构的指针(Win3.0)
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPCOREINFOHEADER结构的指针
LPBITMAPCOREHEADER lpbmc;
// 循环变量(象素在新DIB中的坐标)
LONGi;
LONGj;
int k;
// 源图像每行的字节数
LONG lLineBytes;
// 找到源DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
// 获取源图像的宽度
lWidth = ::DIBWidth(lpDIB);
// 计算源图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 1);
// 获取源图像的高度
lHeight = ::DIBHeight(lpDIB);
// 目的图像宽度
lNewWidth = lWidth;
// 计算目的图像每行的字节数
lNewLineBytes = WIDTHBYTES(lNewWidth * 8);
// 计算目的图像高度
lNewHeight = lHeight;
//计算256色位图调色板大小
long PaletteNew;
if (IS_WIN30_DIB(lpDIB))
{
PaletteNew= 4*256;
}
else
{
PaletteNew= 3*256;
}
// 分配内存,以保存新DIB
hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight
+ *(LPDWORD)lpDIB + PaletteNew);
// 判断是否内存分配失败
if (hDIB == NULL)
{
// 分配内存失败
return NULL;
}
// 锁定内存
lpNewDIB = (char * )::GlobalLock((HGLOBAL) hDIB);
// 复制DIB信息头
memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB);
// 获取指向BITMAPINFOHEADER结构的指针(Win3.0)
lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
// 获取指向BITMAPCOREHEADER结构的指针
lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
//修改DIB信息头中的信息
if (IS_WIN30_DIB(lpNewDIB))
{
lpbmi->biBitCount=8;
lpbmi->biClrUsed=0;
lpbmi->biSizeImage=lNewLineBytes*lNewHeight;
}
else
{
lpbmc->bcBitCount=8;
}
//添加新图象调色板信息
for (k = 0; k < 256; k ++)
{
if (IS_WIN30_DIB(lpNewDIB))
{
lpDst=(char *)lpNewDIB + *(LPDWORD)lpNewDIB + k*4;
*lpDst=(unsigned char)k;
lpDst=(char *)lpNewDIB + *(LPDWORD)lpNewDIB + k*4 +1;
*lpDst=(unsigned char)k;
lpDst=(char *)lpNewDIB + *(LPDWORD)lpNewDIB + k*4 +2;
*lpDst=(unsigned char)k;
lpDst=(char *)lpNewDIB + *(LPDWORD)lpNewDIB + k*4 +3;
*lpDst=(unsigned char)0;
}
else
{
lpDst=(char *)lpNewDIB + *(LPDWORD)lpNewDIB + k*3;
*lpDst=(unsigned char)k;
lpDst=(char *)lpNewDIB + *(LPDWORD)lpNewDIB + k*3 +1;
*lpDst=(unsigned char)k;
lpDst=(char *)lpNewDIB + *(LPDWORD)lpNewDIB + k*3 +2;
*lpDst=(unsigned char)k;
}
}
LPBITMAPINFO lpbmiNew;
lpbmiNew = (LPBITMAPINFO)lpNewDIB;
// 找到新DIB象素起始位置
lpNewDIBBits = ::FindDIBBits(lpNewDIB);
// 针对图像每行进行操作
for(i = 0; i < lNewHeight; i++)
{
// 针对图像每列进行操作
for(j = 0; j < lLineBytes; j++)
{
//指向源图像数据的第i行j列的指针
lpSrc = (char *)lpDIBBits + lLineBytes * i + j;
//对原图像数据的第i行j列的数据进行位运算,取出每一位的数据
//复值给目标图像数据第i行,第j*8+k列
for (k = 0 ; k < 8 ; k ++)
{
lpDst = (char *)lpNewDIBBits + lNewLineBytes * i + j * 8 +k;
if ((unsigned char)((* lpSrc)>>(7-k)) & 0x01 == 0x01)
{
*lpDst = (unsigned char)255;
}
else
{
*lpDst = (unsigned char)0;
}
}
}
}
// 返回
return hDIB;
}