24位Bitmap 转成 灰度? 怎么写? 请各位帮忙。 bitmapgdi+灰度
解决方案 »
- 程序运行过程当中,内存占用很大主要原因有哪些?除了忘记释放内存操作外。
- 使用 Simple MAPI 发送邮件,怎么避免邮件系统弹出安全警告?
- 如何调用Cstring类?
- 重新开贴求解:请问如何识别波形上的波峰?【图】
- 关于 CListCtrl 的选中问题 请高手帮忙
- 大家给小弟推荐几个经典智力型游戏,谢谢!
- 《Windows 程序设计》第 7 章,第 5 节 (捕获鼠标)中,发现一个很不妥的问题.矩形永远不能画到窗口左边.有什么解决方案?
- 对一段代码总是不放心,大家帮着看看。
- 如何判断当前计算机是否登陆到局域网?
- 送分题>>>>>>>加急!!!
- ActiveX Controls中的自定义事件
- MFC打开指定文件夹
void CImageProcessingDoc::OnGrayRight()
{
// TODO: Add your command handler code here
#ifndef USE_FILE
MakeGrayFromLeft();
#else
// Load the BitMap
if(m_hBmpRight)
{
DeleteObject(m_hBmpRight);
m_hBmpRight=0;//LR_CREATEDIBSECTION |
}
m_hBmpRight=(HBITMAP)LoadImage(AfxGetInstanceHandle(),"Gray.bmp",IMAGE_BITMAP,0,0,
LR_DEFAULTSIZE | LR_LOADFROMFILE);
#endif
if(m_hBmpRight==0) return;
//
BITMAP bmp;
::GetObject(m_hBmpRight,sizeof(BITMAP),&bmp);
// tell left view to show this bitmap
CImageProcessingView *pRight=((CMainFrame*)AfxGetMainWnd())->GetRightPane(); // left ScrollView
SIZE sizeTotal;
sizeTotal.cx=bmp.bmWidth+10;//gap
sizeTotal.cy=bmp.bmHeight+10;
pRight->SetScrollSizes(MM_TEXT,sizeTotal);
pRight->Invalidate();
pRight->UpdateWindow();
}
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;
else return FALSE;
}
关键:
grey = ( pPix[2] + pPix[1] ) / 2;// (red + green) / 2;
灰度用color矩阵变换
其中转换部分的代码简单,但速度不快,适用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
}