BMP位图32位转为24位深度
2011-04-02 10:13
1086 查看
帮朋友做一个视频采集和基本处理功能,要求的是.bmp格式
几天下来,通过directshow进行视频采集,并抓去图片保存,按照要求进行业务处理,以前的处理程序是基于RGB24
而显示器是32位真彩色,后调整directshow 的grab filter,修改媒体类型,pmt->majortype = MEDIATYPE_Video;
pmt->subtype = MEDIASUBTYPE_RGB24; 结果在业务中效果不理想,为既保留32位图,也生成rgb24位图
硬是将BITMAPINFOHEADER *lpbi 中的值进行强行设置lpbi->biBitCount = 24;
结果是:产生的图片带有间断性的彩色条纹
然后再在谷歌、摆渡中继续游泳,没有实质性进展
无奈,进微软msdn、gdi+...
接下来的两天就是恶补BMP知识,发现彩色条纹应该是RGB32位颜色空间值,对于RGB32与RGB24,它们的像素点空间只差了一个字节,
继而,自行转换数据
首先是从directshow中获取图像数据
其次是,保留获取数据的文件头
然后是转换位图数据内容,并将内容另置空间
最后设定BITMAPFILEHEADER文件头,并写文件,
为备忘,具体实现如下:
TRY
{
BYTE *buffer = NULL;
hr = m_pWindowsLessControl->GetCurrentImage(&buffer); //这里 m_pWindowsLessControl为IVMRWindowlessControl,进行图像抓取;
if (!SUCCEEDED(hr))
{
return hr;
}
BITMAPFILEHEADER hdr;
BITMAPINFOHEADER *lpbi = (BITMAPINFOHEADER *)buffer;
//颜色空间转换,如果为32位位图,转换为24
DWORD dwSize24 = 0;
DWORD dwSize32 = lpbi->biSizeImage;
dwSize24 = (dwSize32*3)/4; //RGB32与RGB24的像素点空间差一个字节
BYTE* pImg24 = new BYTE[dwSize24]; //存放RGB24存储空间
BYTE* pImg24Temp = pImg24;//设定临时指针,后续进行数据管理
BYTE* pImg32 = buffer + sizeof(BITMAPINFOHEADER);//跳过文件头,定位到数据部分
bool isSize24 = false;
if (lpbi->biBitCount==32)
{
isSize24 = true;
for (DWORD index=0; index<dwSize32/4; index++)
{
unsigned char r = *(pImg32++);
unsigned char g = *(pImg32++);
unsigned char b = *(pImg32++);
pImg32++; //跳过颜色空间alpha分量,实现转换
*(pImg24++) = r;
*(pImg24++) = g;
*(pImg24++) = b; //赋值
}
//将指针指向新的控件
lpbi->biBitCount = 24;//强行指定
}
int nColors = 1 << lpbi->biBitCount; //按照设定深度,进行颜色计算
if (nColors > 256)
nColors = 0;
hdr.bfType = ((WORD)('M' << 8) | 'B'); // 指定BMP
//进行文件头设置
hdr.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nColors * sizeof(RGBQUAD) + lpbi->biSizeImage;
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + lpbi->biSize + nColors * sizeof(RGBQUAD));
//进行位图写入
FILE *bmpFile = NULL;
bmpFile = fopen((LPCTSTR)szFile, "wb");//szFile为文件名
if (bmpFile != NULL)
{
fwrite(&hdr, 1, sizeof(BITMAPFILEHEADER), bmpFile);//位图文件头
fwrite(buffer, 1, sizeof(BITMAPINFOHEADER), bmpFile);//位图信息头
if (!isSize24)
{
fwrite(buffer+sizeof(BITMAPINFOHEADER), 1, nColors * sizeof(RGBQUAD), bmpFile);//颜色表
fwrite(buffer+sizeof(BITMAPINFOHEADER)+nColors * sizeof(RGBQUAD), 1, lpbi->biSizeImage, bmpFile);//位图数据
}
else
{
fwrite(pImg24Temp,1,dwSize24,bmpFile);
}
}
fclose(bmpFile);
CoTaskMemFree(buffer);//释放资源
delete pImg24Temp;
return hr;
}
CATCH (CMemoryException, e)
{
}
END_CATCH
}
折腾了两天,真费劲,特此记录一下备忘
几天下来,通过directshow进行视频采集,并抓去图片保存,按照要求进行业务处理,以前的处理程序是基于RGB24
而显示器是32位真彩色,后调整directshow 的grab filter,修改媒体类型,pmt->majortype = MEDIATYPE_Video;
pmt->subtype = MEDIASUBTYPE_RGB24; 结果在业务中效果不理想,为既保留32位图,也生成rgb24位图
硬是将BITMAPINFOHEADER *lpbi 中的值进行强行设置lpbi->biBitCount = 24;
结果是:产生的图片带有间断性的彩色条纹
然后再在谷歌、摆渡中继续游泳,没有实质性进展
无奈,进微软msdn、gdi+...
接下来的两天就是恶补BMP知识,发现彩色条纹应该是RGB32位颜色空间值,对于RGB32与RGB24,它们的像素点空间只差了一个字节,
继而,自行转换数据
首先是从directshow中获取图像数据
其次是,保留获取数据的文件头
然后是转换位图数据内容,并将内容另置空间
最后设定BITMAPFILEHEADER文件头,并写文件,
为备忘,具体实现如下:
TRY
{
BYTE *buffer = NULL;
hr = m_pWindowsLessControl->GetCurrentImage(&buffer); //这里 m_pWindowsLessControl为IVMRWindowlessControl,进行图像抓取;
if (!SUCCEEDED(hr))
{
return hr;
}
BITMAPFILEHEADER hdr;
BITMAPINFOHEADER *lpbi = (BITMAPINFOHEADER *)buffer;
//颜色空间转换,如果为32位位图,转换为24
DWORD dwSize24 = 0;
DWORD dwSize32 = lpbi->biSizeImage;
dwSize24 = (dwSize32*3)/4; //RGB32与RGB24的像素点空间差一个字节
BYTE* pImg24 = new BYTE[dwSize24]; //存放RGB24存储空间
BYTE* pImg24Temp = pImg24;//设定临时指针,后续进行数据管理
BYTE* pImg32 = buffer + sizeof(BITMAPINFOHEADER);//跳过文件头,定位到数据部分
bool isSize24 = false;
if (lpbi->biBitCount==32)
{
isSize24 = true;
for (DWORD index=0; index<dwSize32/4; index++)
{
unsigned char r = *(pImg32++);
unsigned char g = *(pImg32++);
unsigned char b = *(pImg32++);
pImg32++; //跳过颜色空间alpha分量,实现转换
*(pImg24++) = r;
*(pImg24++) = g;
*(pImg24++) = b; //赋值
}
//将指针指向新的控件
lpbi->biBitCount = 24;//强行指定
}
int nColors = 1 << lpbi->biBitCount; //按照设定深度,进行颜色计算
if (nColors > 256)
nColors = 0;
hdr.bfType = ((WORD)('M' << 8) | 'B'); // 指定BMP
//进行文件头设置
hdr.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nColors * sizeof(RGBQUAD) + lpbi->biSizeImage;
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + lpbi->biSize + nColors * sizeof(RGBQUAD));
//进行位图写入
FILE *bmpFile = NULL;
bmpFile = fopen((LPCTSTR)szFile, "wb");//szFile为文件名
if (bmpFile != NULL)
{
fwrite(&hdr, 1, sizeof(BITMAPFILEHEADER), bmpFile);//位图文件头
fwrite(buffer, 1, sizeof(BITMAPINFOHEADER), bmpFile);//位图信息头
if (!isSize24)
{
fwrite(buffer+sizeof(BITMAPINFOHEADER), 1, nColors * sizeof(RGBQUAD), bmpFile);//颜色表
fwrite(buffer+sizeof(BITMAPINFOHEADER)+nColors * sizeof(RGBQUAD), 1, lpbi->biSizeImage, bmpFile);//位图数据
}
else
{
fwrite(pImg24Temp,1,dwSize24,bmpFile);
}
}
fclose(bmpFile);
CoTaskMemFree(buffer);//释放资源
delete pImg24Temp;
return hr;
}
CATCH (CMemoryException, e)
{
}
END_CATCH
}
折腾了两天,真费劲,特此记录一下备忘
相关文章推荐
- 把24位和32位BMP位图转为灰色bmp位图
- Android如何把图片转为深度为32位格式为.bmp的图片
- 实现1位,4位,8位,24位BMP位图的互相转换的方法,32位转24位
- 把24位bmp位图按水平扫描和垂直扫描转为点阵数组
- C++ C语言 读取32位BMP图片转为8位灰度图
- 32位位图到24位位图的转换
- 怎样在CSDN博客中使用程序结果的截图和win7自带的画图工具:可以将jpg图片转为bmp位图。win7的截图工具和绘图工具在哪?
- bmp位图文件:读取、写入、24位真彩转8位灰度、灰度图的二值化
- 24位 位图与32位 位图差异解析
- 32位位图到24位位图的转换
- (tip_修订0618)bmp 32位转24位
- 24位真彩位图转4位(16色)灰度图(BMP)
- BMP的8位位图转换24位位图
- BMP格式知识之二:16位,24位,32位的BMP图片算法是如何运算的
- 24位位图转4位彩色图(BMP)
- 【数字图像】C++8位和24位BMP位图的平滑、锐化、二值化处理,以及24位真彩图的灰度化
- bmp文件格式中rgb555与rgb888之间的转换,24位与16位位图的转换
- 32位BMP带通道的透明图转化24位BMP带通道透明图问题
- 将32位BMP文件转换为24位BMP
- 32位位图与24位位图互相转换