gdi+ Bitmap转灰度?
24位Bitmap 转成 灰度?
怎么写? 请各位帮忙。 bitmap gdi+ 灰度
[解决办法]
把RGB三色, 按亮度公式,即可转换成灰度图. 转换后的图可保存为8位位图, 也可以保存成24位图, 只是RGB三个都保存前面计算的亮度值. 如亮度值计算结果为 128, 则有 R=128, G=128,B=128, 这样填充回位图中, 即可变成灰度图了.
[解决办法]
sorry, 复制错了:
//
BOOL CImageProcessingDoc::MakeGrayFromLeft()
{
DIBSECTION ds;
//
int dsSize=GetObject(m_hBmpLeft, sizeof(DIBSECTION), &ds);//0x54
if ((dsSize == sizeof(ds)) && ds.dsBm.bmBits)
{//
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
if (GetVersionEx(&osvi))
{
if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
ds.dsBm.bmWidthBytes = (ds.dsBm.bmWidthBytes + 3) & ~3;
}
}
}
//
int BytesPerPixel = ds.dsBm.bmBitsPixel/8;
int padding=ds.dsBm.bmWidthBytes - ds.dsBm.bmWidth*BytesPerPixel;//=2
if (BytesPerPixel < 3) return FALSE;
//
int DibSize=ds.dsBm.bmHeight * ds.dsBm.bmWidthBytes;
BYTE *pDibBuffer=(BYTE *)new BYTE[DibSize];
BYTE *pTmp=pDibBuffer;// for moving
BYTE *pEnd=pTmp+DibSize;
BYTE *pPix=(BYTE*)(ds.dsBm.bmBits);
//
BYTE grey;
while(pTmp<pEnd)
{//
for(int jj=0; jj < ds.dsBm.bmWidth; jj++)
{// An excellent greyscale calculation is: normal 3 bytes
//grey =(30 * (*(pPix+2)) + 59 * (*(pPix+1)) + 11 * (*pPix)) / 100;
// This is a bit too slow so a faster calculation is:
grey = ( pPix[2] + pPix[1] ) / 2;// (red + green) / 2;
*pTmp++ = grey;
*pTmp++ = grey;
*pTmp++ = grey;
pPix += BytesPerPixel;//=3
}
for(int pp=0;pp<padding;pp++)
{// has padding such as "Protell.bmp"
*pTmp++ =0;
pPix ++;
}
}
// make bmp
if(m_hBmpRight)
{
DeleteObject(m_hBmpRight);
m_hBmpRight=0;
}
BITMAPINFO bmi;
ZeroMemory(&bmi,sizeof(bmi));
CopyMemory(&bmi.bmiHeader,&ds.dsBmih, sizeof(BITMAPINFOHEADER));
// must
HDC dc=GetWindowDC(0);
m_hBmpRight=::CreateDIBitmap(dc, &ds.dsBmih, CBM_INIT, pDibBuffer,&bmi, DIB_RGB_COLORS);
ReleaseDC(0,dc);
//
if(pDibBuffer) delete []pDibBuffer;
if(m_hBmpRight) return TRUE;
elsereturn FALSE;
}
关键:
grey = ( pPix[2] + pPix[1] ) / 2;// (red + green) / 2;
[解决办法]
贴一个控制台的图像转灰度并保存的完整代码。
其中转换部分的代码简单,但速度不快,适用1次性转换。
实时窗口中绘图如需要高速的情况下,用lockbit一个个算,然后bitblt。
//24bit-jpeg转成24bit-灰度jpeg
#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace std;
using namespace Gdiplus;
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid);
int wmain()
{
GdiplusStartupInput gdiplusstartupinput;
ULONG_PTR gdiplustoken;
GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, nullptr);
wstring infilename(L"1.jpg");
wstring outfilename(L"2.jpg");
//读图片
Bitmap* srcbmp = new Bitmap(infilename.c_str());
UINT cheight = srcbmp->GetHeight();
UINT cwidth = srcbmp->GetWidth();
//建立一张bitmap
Bitmap* destbmp = new Bitmap(cwidth, cheight, srcbmp->GetPixelFormat());
//建立新bitmap的graphics对象
Graphics* pgs = new Graphics(destbmp);
//颜色转灰度的矩阵
//亮度公式 gray = G * 0.299 + G * 0.587 + B * 0.144
ColorMatrix colormatrix =
{
0.299f, 0.299f, 0.299f, 0.0f, 0.0f,
0.587f, 0.587f, 0.587f, 0.0f, 0.0f,
0.144f, 0.144f, 0.144f, 0.0f, 0.0f,
0.000f, 0.000f, 0.000f, 1.0f, 0.0f,
0.000f, 0.000f, 0.000f, 0.0f, 1.0f
};
ImageAttributes* pimageattributes = new ImageAttributes;
pimageattributes->SetColorMatrix(&colormatrix,
ColorMatrixFlagsDefault,
ColorAdjustTypeBitmap);
//转换成灰度并绘制在新的bmp上
pgs->DrawImage(srcbmp,
Rect(0, 0, cwidth, cheight),
0, 0, cwidth, cheight,
UnitPixel,
pimageattributes);
//获取编码器的类标识符
CLSID encoderclsid;
GetEncoderClsid(L"image/jpeg", &encoderclsid);
//保存jpeg需要设置的参数
ULONG quality(100); //设置jpg压缩等级,100是最小压缩, 0最大压缩。
EncoderParameters encoderparameters;
encoderparameters.Count = 1;
encoderparameters.Parameter[0].Guid = EncoderQuality;
encoderparameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderparameters.Parameter[0].NumberOfValues = 1;
encoderparameters.Parameter[0].Value = &quality;
//保存图像到文件
Status stat = destbmp->Save(outfilename.c_str(),
&encoderclsid,
&encoderparameters);
if (stat == Ok)
wcout << outfilename << L" saved successfully.\n";
else
wcout << outfilename << L" save failed with error " << GetLastError() << endl;
delete pimageattributes;
delete pgs;
delete destbmp;
delete srcbmp;
GdiplusShutdown(gdiplustoken);
return 0;
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if(size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}