转载自:http://lipingke.blog.hexun.com/35837085_d.html
贴出来不为别的,就为万一以后硬盘出问题资料在网上还有个备份。
//Code By xets007
//转载请注明出处
//
#include <windows.h>
BOOL BMP24to8(char *szSourceFile, char *szTargetFile);
int main(int argc, char *argv[])
{
BOOL stat = BMP24to8("c://source.bmp", "c://target.bmp"); //调用这个函数直接把24位真彩色灰度化
return 0;
}
BOOL BMP24to8(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);
if (pSource == NULL || dwSourceSize <= 54) //分配空间失败或者文件太小(BMP文件不可能小于54个字节)
{
CloseHandle(hSourceFile);
return FALSE;
}
DWORD dwTemp = 0;
ReadFile(hSourceFile, pSource, dwSourceSize, &dwTemp, NULL);
BITMAPFILEHEADER *pSourceFileHeader = (BITMAPFILEHEADER *)pSource;
BITMAPINFOHEADER *pSourceInfoHeader = (BITMAPINFOHEADER *)(pSource + sizeof(BITMAPFILEHEADER));
if (pSourceFileHeader->bfType != 0x4d42 || pSourceInfoHeader->biBitCount != 24) //不是BMP文件或者不是24位真彩色
{
CloseHandle(hSourceFile);
VirtualFree(pSource, NULL, MEM_RELEASE);
return FALSE;
}
CloseHandle(hSourceFile);
LONG nWidth = pSourceInfoHeader->biWidth;
LONG nHeight = pSourceInfoHeader->biHeight;
LONG nSourceWidth = nWidth * 3;
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;
pTarget = (PBYTE)VirtualAlloc(NULL, dwTargetSize, MEM_COMMIT, PAGE_READWRITE);
memset(pTarget, 0, dwTargetSize);
if (pTarget == NULL)
{
VirtualFree(pTarget, NULL, MEM_RELEASE);
return FALSE;
}
BITMAPFILEHEADER *pTargetFileHeader = (BITMAPFILEHEADER *)pTarget;
BITMAPINFOHEADER *pTargetInfoHeader = (BITMAPINFOHEADER *)(pTarget + sizeof(BITMAPFILEHEADER));
pTargetFileHeader->bfType = pSourceFileHeader->bfType;
pTargetFileHeader->bfSize = dwTargetSize;
pTargetFileHeader->bfReserved1 = 0;
pTargetFileHeader->bfReserved2 = 0;
pTargetFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256;
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;
RGBQUAD *pRgb;
for (int i = 0; i < 256; i++) //初始化8位灰度图的调色板信息
{
pRgb = (RGBQUAD *)(pTarget + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + i * sizeof(RGBQUAD));
pRgb->rgbBlue = i;
pRgb->rgbGreen = i;
pRgb->rgbRed = i;
pRgb->rgbReserved = 0;
}
for (int m = 0; m < nHeight; m++) //转化真彩色图为灰度图
{
for (int n = 0; n < nWidth; n++)
{
pTarget[pTargetFileHeader->bfOffBits + m * nTargetWidth + n] = pSource[pSourceFileHeader->bfOffBits + m * nSourceWidth + n * 3] * 0.114 + pSource[pSourceFileHeader->bfOffBits + m * nSourceWidth + n * 3 + 1] * 0.587 + pSource[pSourceFileHeader->bfOffBits + m * nSourceWidth + n * 3 + 2] * 0.299;
}
}
hTargetFile = CreateFile(szTargetFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
BOOL stat = WriteFile(hTargetFile, pTarget, dwTargetSize, &dwTemp, NULL);
CloseHandle(hTargetFile);
VirtualFree(pSource, NULL, MEM_RELEASE);
VirtualFree(pTarget, NULL, MEM_RELEASE);
return stat;
}