【图像】简单的高斯模糊实例
原理很简单,就是把一个图像横着模糊一下,然后把这个横向模糊过的图像再纵向模糊一下,就是高斯模糊了。#include<Windows.h>
#include<stdlib.h>
#define 模糊程度 32
typedef struct
{
HINSTANCE hInst;
HWND hWnd;
HDC hWindowDC;
//原图
HDC hImgDC;
HBITMAP hImgBmp;
//原图信息
BITMAP ImgBmp;
LONG BmpWidth;
LONG BmpHeight;
//横向模糊过的图
HDC hDrawPad1DC;
HBITMAP hDrawPad1Bmp;
void*pDrawPad1Bits;
//最终图
HDC hFinalDrawPadDC;
HBITMAP hFinalDrawPadBmp;
void*pFinalDrawPadBits;
}GaussianDemo_t,*GaussianDemo_p;
//============================================================================
//函数:ShowLastError
//描述:弹出对话框显示GetLastError的文本信息
//----------------------------------------------------------------------------
void ShowLastError(HWND hWnd)
{
LPVOID lpMsgBuf;
FormatMessage
(
FORMAT_MESSAGE_ALLOCATE_BUFFER | //返回一个已分配的内存
FORMAT_MESSAGE_FROM_SYSTEM |//系统消息
FORMAT_MESSAGE_IGNORE_INSERTS, //无视插入信息
NULL,
GetLastError(),
0, //默认语言
(LPTSTR)&lpMsgBuf, //错误信息指针
0,
NULL
);
MessageBox(hWnd,(LPCTSTR)lpMsgBuf,NULL,MB_OK|MB_ICONINFORMATION);
LocalFree(lpMsgBuf);//释放内存
}
//============================================================================
//函数:Create24BitDIBBmp
//描述:在内存中生成一个空的24位位图,用作“画板”
//----------------------------------------------------------------------------
HBITMAP Create24BitDIBBmp(HDC hDC,UINT Width,UINT Height,void**ppBits)
{
BITMAPINFOHEADER BMIF={sizeof(BITMAPINFOHEADER),Width,Height,1,24,0,0,0,0,0,0};
return CreateDIBSection(hDC,(LPBITMAPINFO)&BMIF,DIB_PAL_COLORS,ppBits,
NULL,0);
}
//============================================================================
//函数:DrawGaussianBlur
//描述:生成高斯模糊图
//----------------------------------------------------------------------------
void DrawGaussianBlur(GaussianDemo_p pData,LONG BlurSize)
{
LONG x,y;
BLENDFUNCTION bf;
LONG BlurOffset=BlurSize;
bf.BlendOp=AC_SRC_OVER;
bf.BlendFlags=0;
bf.AlphaFormat=0;
BlurSize*=2;
//第一步:将图像横着模糊一遍,然后存入第一个画板
for(x=0;x<BlurSize;x++)
{
bf.SourceConstantAlpha=(BYTE)(255/(x+1));
AlphaBlend(pData->hDrawPad1DC,x-BlurOffset,0,pData->BmpWidth,pData->BmpHeight,
pData->hImgDC,0,0,pData->BmpWidth,pData->BmpHeight,bf);
}
//第二步:将画板中横着模糊的图片再纵向模糊一下,然后存入最终画板
for(y=0;y<BlurSize;y++)
{
bf.SourceConstantAlpha=(BYTE)(255/(y+1));
AlphaBlend(pData->hFinalDrawPadDC,0,y-BlurOffset,pData->BmpWidth,pData->BmpHeight,
pData->hDrawPad1DC,0,0,pData->BmpWidth,pData->BmpHeight,bf);
}
}
//============================================================================
//函数:DeleteDrawPad
//描述:删除画板
//----------------------------------------------------------------------------
void DeleteDrawPad(GaussianDemo_p pData)
{
if(pData->hImgBmp)DeleteObject(pData->hImgBmp);
pData->hImgBmp=NULL;
if(pData->hDrawPad1Bmp)DeleteObject(pData->hDrawPad1Bmp);
pData->hDrawPad1Bmp=NULL;
if(pData->hFinalDrawPadBmp)DeleteObject(pData->hFinalDrawPadBmp);
pData->hFinalDrawPadBmp=NULL;
if(pData->hImgDC)DeleteDC(pData->hImgDC);
pData->hImgDC=NULL;
if(pData->hDrawPad1DC)DeleteDC(pData->hDrawPad1DC);
pData->hDrawPad1DC=NULL;
if(pData->hFinalDrawPadDC)DeleteDC(pData->hFinalDrawPadDC);
pData->hFinalDrawPadDC=NULL;
}
//============================================================================
//函数:SetupDrawPad
//描述:设置画板,用于绘制高斯模糊图
//----------------------------------------------------------------------------
BOOL SetupDrawPad(GaussianDemo_p pData)
{
HWND hWnd=pData->hWnd;
//分析位图
GetObject(pData->hImgBmp,sizeof(pData->ImgBmp),&(pData->ImgBmp));
//取得尺寸
pData->BmpWidth=pData->ImgBmp.bmWidth;
if(pData->ImgBmp.bmHeight<0)
pData->BmpHeight=-pData->ImgBmp.bmHeight;
else
pData->BmpHeight=pData->ImgBmp.bmHeight;
SelectObject(pData->hImgDC,pData->hImgBmp);
//创建第一个画板
if(pData->hDrawPad1Bmp)DeleteObject(pData->hDrawPad1Bmp);
pData->hDrawPad1Bmp=Create24BitDIBBmp(pData->hDrawPad1DC,
pData->BmpWidth,pData->BmpHeight,&(pData->pDrawPad1Bits));
if(!pData->hDrawPad1Bmp)
{
ShowLastError(hWnd);
DeleteDrawPad(pData);
return FALSE;
}
SelectObject(pData->hDrawPad1DC,pData->hDrawPad1Bmp);//组装
//创建第二个画板
if(pData->hFinalDrawPadBmp)DeleteObject(pData->hFinalDrawPadBmp);
pData->hFinalDrawPadBmp=Create24BitDIBBmp(pData->hFinalDrawPadDC,
pData->BmpWidth,pData->BmpHeight,&(pData->pFinalDrawPadBits));
if(!pData->hFinalDrawPadBmp)
{
ShowLastError(hWnd);
DeleteDrawPad(pData);
return FALSE;
}
SelectObject(pData->hFinalDrawPadDC,pData->hFinalDrawPadBmp);
return TRUE;
}
//============================================================================
//函数:LoadPictureFileA
//描述:加载一个图像文件,并生成高斯模糊图
//----------------------------------------------------------------------------
BOOL LoadPictureFileA(CHAR*szFileName,GaussianDemo_p pData)
{
HWND hWnd=pData->hWnd;
//加载文件
if(pData->hImgBmp)DeleteObject(pData->hImgBmp);
pData->hImgBmp=(HBITMAP)LoadImageA(NULL,szFileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
if(!pData->hImgBmp)
{
if(!GetLastError())
MessageBox(hWnd,TEXT("不是bmp文件。"),NULL,MB_OK|MB_ICONINFORMATION);
else
ShowLastError(hWnd);
DeleteDrawPad(pData);
return FALSE;
}
//设置好画板就进行模糊处理
SetupDrawPad(pData);
DrawGaussianBlur(pData,模糊程度);
return TRUE;
}
BOOL LoadPictureFileW(WCHAR*szFileName,GaussianDemo_p pData)
{
HWND hWnd=pData->hWnd;
//加载文件
if(pData->hImgBmp)DeleteObject(pData->hImgBmp);
pData->hImgBmp=(HBITMAP)LoadImageW(NULL,szFileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
if(!pData->hImgBmp)
{
if(!GetLastError())
MessageBox(hWnd,TEXT("不是bmp文件。"),NULL,MB_OK|MB_ICONINFORMATION);
else
ShowLastError(hWnd);
DestroyWindow(hWnd);
DeleteDrawPad(pData);
return FALSE;
}
//设置好画板就进行模糊处理
SetupDrawPad(pData);
DrawGaussianBlur(pData,模糊程度);
return TRUE;
}
#ifdef UNICODE
#define LoadPictureFile LoadPictureFileW
#else
#define LoadPictureFile LoadPictureFileA
#endif
LRESULT CALLBACK WndProc(HWND hWnd,UINT Msg,WPARAM wp,LPARAM lp)
{
GaussianDemo_p pUserData;
switch(Msg)
{
case WM_CREATE:
//创建窗口的时候设置窗口的属性和附加的内容
//接收文件拖放
DragAcceptFiles(hWnd,TRUE);
//附加内容
pUserData=(GaussianDemo_p)malloc(sizeof(GaussianDemo_t));
if(!pUserData)
return -1;
//填写附加内容
memset(pUserData,0,sizeof(GaussianDemo_t));
pUserData->hInst=GetModuleHandle(NULL);
pUserData->hWnd=hWnd;
pUserData->hImgDC=CreateCompatibleDC(pUserData->hWindowDC=GetWindowDC(hWnd));
pUserData->hDrawPad1DC=CreateCompatibleDC(pUserData->hWindowDC);
pUserData->hFinalDrawPadDC=CreateCompatibleDC(pUserData->hWindowDC);
//设置附加内容
SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG_PTR)pUserData);
if(__argc>1)
LoadPictureFileA(__argv,pUserData);
break;
case WM_DROPFILES:
{
TCHAR szFile;
RECT rc;
//取得窗口附加信息
pUserData=(GaussianDemo_p)GetWindowLongPtr(hWnd,GWLP_USERDATA);
//取得拖拽入的文件名
DragQueryFile((HDROP)wp,0,szFile,MAX_PATH);
LoadPictureFile(szFile,pUserData);
GetClientRect(hWnd,&rc);
InvalidateRect(hWnd,&rc,TRUE);
}
break;
case WM_PAINT:
{
HDC hPaintDC;
RECT rc;
PAINTSTRUCT ps;
GetClientRect(hWnd,&rc);
//取得窗口附加信息
pUserData=(GaussianDemo_p)GetWindowLongPtr(hWnd,GWLP_USERDATA);
hPaintDC=BeginPaint(hWnd,&ps);
BitBlt(hPaintDC,0,0,rc.right-rc.left,rc.bottom-rc.top,pUserData->hFinalDrawPadDC,0,0,SRCCOPY);
EndPaint(hWnd,&ps);
}
break;
case WM_DESTROY:
pUserData=(GaussianDemo_p)GetWindowLongPtr(hWnd,GWLP_USERDATA);
DeleteDrawPad(pUserData);
free(pUserData);
SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG_PTR)NULL);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,Msg,wp,lp);
}
return 0;
}
void CreateInst(HINSTANCE hInst,int ShowCmd)
{
WNDCLASSEX WCEx={sizeof(WNDCLASSEX),0,WndProc,0,0,hInst,LoadIcon(NULL,MAKEINTRESOURCE(IDI_APPLICATION)),LoadCursor(NULL,MAKEINTRESOURCE(IDC_ARROW)),(HBRUSH)COLOR_BTNFACE,NULL,TEXT("tuttb"),NULL};//窗口类
HWND hWnd=CreateWindowEx(0,MAKEINTATOM(RegisterClassEx(&WCEx)),TEXT("请将文件拖拽进来"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,400,300,NULL,NULL,hInst,NULL);//窗口句柄
ShowWindow(hWnd,ShowCmd);
UpdateWindow(hWnd);
}
int APIENTRY WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR szCmd,int ShowCmd)
{
MSG msg;
CreateInst(hInst,ShowCmd);
while(GetMessage(&msg,NULL,0,0))//消息循环
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
SRC:
BIN: 这个用于什么啊?打马赛克?
FFFFFFFE 发表于 2015-9-6 15:55
这个用于什么啊?打马赛克?
嗯。 →_→3Q 原来你是这种癖好 为什么是这张图。。。 __star__ 发表于 2015-9-11 13:19
为什么是这张图。。。
为什么不能是这张图? 我想知道如何用DirectX来处理高斯模糊。另外。实现高斯模糊还有种更简单的方法,使用GDI+的Effect类。 Kiss丿Huryo 发表于 2016-1-7 14:41
我想知道如何用DirectX来处理高斯模糊。另外。实现高斯模糊还有种更简单的方法,使用GDI+的Effect类。 ...
GDI+没有显卡加速,效率不高。我这个虽然用的是GDI,但是它是有显卡性能加成的。
DX的话,渲染方式也一样。重复绘制,每层透明度值减少。
0xAA55 发表于 2016-1-7 14:46
GDI+没有显卡加速,效率不高。我这个虽然用的是GDI,但是它是有显卡性能加成的。
DX的话,渲染方式也一样 ...
GDI+确实有点慢。用它处理一张700x700的图片 Round为20的图片竟然要400ms。。也可能是我电脑不好吧。。=_= Kiss丿Huryo 发表于 2016-1-7 14:51
GDI+确实有点慢。用它处理一张700x700的图片 Round为20的图片竟然要400ms。。也可能是我电脑不好吧。。=_ ...
GDI+没有显卡性能加成,它都是靠的CPU处理。再快的电脑,用GDI+处理图片还是慢。 丫丫的,废话代码全部贴出来了,什么加载文件,什么DC位图的,谁不知道啊,一句一语的都有。
这核心代码就:
bf.SourceConstantAlpha=(BYTE)(255/(x+1)); 变模糊,代码在哪里:@
我来来看模糊算法的,结果就给我这个:funk:
页:
[1]