您的位置:首页 > 其它

把24位和32位BMP位图转为灰色bmp位图

2014-07-28 15:13 399 查看
源码来自网上,原来只支持24位位图转灰度位图,我增加了32位位图转灰度位图。

//Code By xets007 //转载请注明出处
//Modify By Gergul
#include <windows.h>

BOOL BMPto8(char *szSourceFile,char *szTargetFile);

int main(int argc,char* argv[])
{ //调用这个函数直接把24位真彩色灰度化
BOOL stat=BMPto8("c://1.bmp","c://target.bmp");
return 0;
}

BOOL BMPto8(char *szSourceFile,char *szTargetFile)
{
HANDLE hSourceFile=INVALID_HANDLE_VALUE,hTargetFile=INVALID_HANDLE_VALUE;
DWORD dwSourceSize=0,dwTargetSize=0;
PBYTE pSource=NULL,pTarget=NULL;

//打开源文件
hSourceFile=CreateFile(szSourceFile,GENERIC_READ,FILE_SHARE_READ,NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hSourceFile==INVALID_HANDLE_VALUE)
return FALSE;
//获得文件大小,并分配内存空间
dwSourceSize=GetFileSize(hSourceFile,NULL);
pSource=(PBYTE)VirtualAlloc(NULL,dwSourceSize,MEM_COMMIT,PAGE_READWRITE); //分配空间失败或者文件太小(BMP文件不可能小于54个字节)
if(pSource==NULL||dwSourceSize<=54)
{
CloseHandle(hSourceFile);
return FALSE;
}

//读出bmp文件的全部内容
DWORD dwReaded = 0;
ReadFile(hSourceFile,pSource,dwSourceSize,&dwReaded,NULL);
CloseHandle(hSourceFile);

//把读出的内容转换到bmp格式(指针直接指向即可)
BITMAPFILEHEADER *pSourceFileHeader=(BITMAPFILEHEADER*)pSource;//文件头
//判断图片是不是BMP文件或者不是24位真彩色
BITMAPINFOHEADER *pSourceInfoHeader=(BITMAPINFOHEADER*)(pSource+sizeof(BITMAPFILEHEADER));
if(pSourceFileHeader->bfType!=0x4d42)
{
VirtualFree(pSource, NULL, MEM_RELEASE);
return FALSE;
}

//获得bmp位数
int nPixelCount = 0;
int nBitNum = pSourceInfoHeader->biBitCount;
switch (nBitNum)
{
case 24:
nPixelCount = 3;//R G B三量
break;
case 32:
nPixelCount = 4;//R G B A 四量
break;
default:
VirtualFree(pSource, NULL, MEM_RELEASE);
return FALSE;
}

LONG nWidth = pSourceInfoHeader->biWidth;
LONG nHeight = pSourceInfoHeader->biHeight;

//每一行的字节数必须是4的整数倍,如果不是,则需要补齐。
LONG nSourceWidth = nWidth * nPixelCount;
if(nSourceWidth%4)
{
nSourceWidth=(nSourceWidth/4+1)*4;
}
LONG nTargetWidth = nWidth;
if(nTargetWidth%4)
{
nTargetWidth=(nTargetWidth/4+1)*4;
}

//图像文件的大小
dwTargetSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256 + nHeight*nTargetWidth;
//目标bmp内存
pTarget=(PBYTE)VirtualAlloc(NULL,dwTargetSize,MEM_COMMIT,PAGE_READWRITE);
memset(pTarget,0,dwTargetSize);
if(pTarget==NULL)
{
VirtualFree(pTarget,NULL,MEM_RELEASE);
return FALSE;
}

//设置目标bmp文件头数据
BITMAPFILEHEADER *pTargetFileHeader=(BITMAPFILEHEADER *)pTarget;
pTargetFileHeader->bfType=pSourceFileHeader->bfType;
pTargetFileHeader->bfSize=dwTargetSize;
pTargetFileHeader->bfReserved1=0;
pTargetFileHeader->bfReserved2=0;
pTargetFileHeader->bfOffBits=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;
//设置目标bmp信息头数据
BITMAPINFOHEADER *pTargetInfoHeader = (BITMAPINFOHEADER *)(pTarget+sizeof(BITMAPFILEHEADER));
pTargetInfoHeader->biBitCount=8;
pTargetInfoHeader->biClrImportant=0;
pTargetInfoHeader->biClrUsed=256;
pTargetInfoHeader->biCompression=BI_RGB;
pTargetInfoHeader->biHeight=pSourceInfoHeader->biHeight;
pTargetInfoHeader->biPlanes=1;
pTargetInfoHeader->biSize=sizeof(BITMAPINFOHEADER);
pTargetInfoHeader->biSizeImage=nHeight*nTargetWidth;
pTargetInfoHeader->biWidth=pSourceInfoHeader->biWidth;
pTargetInfoHeader->biXPelsPerMeter=pSourceInfoHeader->biXPelsPerMeter;
pTargetInfoHeader->biYPelsPerMeter=pSourceInfoHeader->biYPelsPerMeter;

//初始化8位灰度图的调色板信息
RGBQUAD *pRgb;
PBYTE pRGBQuadBegin = pTarget + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
for(int i=0; i<256; i++)
{
pRgb = (RGBQUAD*)(pRGBQuadBegin + i*sizeof(RGBQUAD));
pRgb->rgbBlue = i;
pRgb->rgbGreen = i;
pRgb->rgbRed = i;
pRgb->rgbReserved = 0;
}

//转化真彩色图为灰度图
for (int h=0; h<nHeight; h++)
{
for(int w=0; w<nWidth; w++)
{
//把RGB的三个值转化为一个灰度值,所以一个彩色bmp大约比灰度bmp大三倍
//gray = red * 0.299 + green * 0.587 + blue * 0.114
int nIndexRgb = pSourceFileHeader->bfOffBits + h*nSourceWidth + w*nPixelCount; //每个彩色像素点的位置[blue, green, red]
int nIndexGray = pTargetFileHeader->bfOffBits + h*nTargetWidth + w; //每个灰色像素点的位置
pTarget[nIndexGray] = (BYTE)
( pSource[nIndexRgb] * 0.114 //蓝
+ pSource[nIndexRgb+1] * 0.587 //绿
+ pSource[nIndexRgb+2] * 0.299 //红
);
}
}

//保存灰度bmp
hTargetFile = CreateFile(szTargetFile,GENERIC_WRITE,FILE_SHARE_WRITE, NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
DWORD dwWrited = 0;
BOOL stat = WriteFile(hTargetFile,pTarget,dwTargetSize,&dwWrited,NULL);
CloseHandle(hTargetFile);
VirtualFree(pSource,NULL,MEM_RELEASE);
VirtualFree(pTarget,NULL,MEM_RELEASE);

return stat;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息