C++基于Directx MMX實(shí)現(xiàn)的圖像灰度轉(zhuǎn)換代碼
本文實(shí)例講述了基于Directx MMX 編寫(xiě)的實(shí)現(xiàn)圖像灰度處理的方法,要編譯此程序需DirectX SDK5.0,代碼中所需要的ddutil.h與ddutil.cpp文件,請(qǐng)自行下載加入工程。在WindowNT4.0+SP3環(huán)境中編譯通過(guò),代碼已經(jīng)過(guò)整理,包含有注釋。如下所示:
#include <windows.h> #include <windowsx.h> #include <stdio.h> #include <ddraw.h> #include <math.h> #include "ddutil.h" #define MEAN_GRAY 0//平均值法 #define MAXIMUM_GRAY 1//最大值法 #define WEIGHT_GRAY 2//加權(quán)平均值法 #define TITLE "灰度轉(zhuǎn)換" //窗口標(biāo)題 #define CLASSNAME "Gray" //窗口類(lèi)名 #define WIDTH 640 #define HEIGHT 480 #define COLORS 8 #define STEP 1 #define SCANLINE 16 HINSTANCE hInst; //應(yīng)用程序?qū)嵗浔? HWND hWndMain; //主窗口句柄 LPDIRECTDRAW lpDD; // DirectDraw對(duì)象 LPDIRECTDRAWSURFACE lpDDSPrimary; // 主頁(yè)面 LPDIRECTDRAWSURFACE lpDDSBack; // 后臺(tái)緩沖區(qū) LPDIRECTDRAWSURFACE lpDDSPic1; // 離屏頁(yè)面1 LPDIRECTDRAWPALETTE lpDDPal; // 調(diào)色板 BOOL bActive; // 應(yīng)用程序是否活躍? int Key=0; bool Contrast=false; bool Gray=false; //函數(shù)聲明 void FreeObjects( void ); BOOL InitDDraw(void); BOOL InitPalette(void); BOOL InitSurfaces(void); void UpdateFrame(void); void MakeRect(RECT *rect, long left, long top, long right, long bottom); void IncreaseContrast(BYTE *pByte,const int Low,const int Hight, const float Grad) { if(*pByte<=Low) *pByte=0; else if((Low<*pByte)&&(*pByte<Hight)) *pByte=(BYTE)((*pByte-Low)/Grad); else *pByte=255; } void ChangeContrast(int nDelta) { LPPALETTEENTRY Pal = (LPPALETTEENTRY) LocalAlloc( LPTR, sizeof( PALETTEENTRY ) * 256 ); //獲取調(diào)色板 lpDDPal->GetEntries(0,0,256,Pal); int Low,High; float Grad; for(int i=0; i<256; i++) { if(nDelta>=0) { Low=0+nDelta; High=255-nDelta; Grad=((float)(High-Low))/255; IncreaseContrast(&Pal[i].peRed ,Low,High,Grad); IncreaseContrast(&Pal[i].peGreen ,Low,High,Grad); IncreaseContrast(&Pal[i].peBlue ,Low,High,Grad); } else { Pal[i].peRed=(BYTE)((int)(Pal[i].peRed/Grad))-nDelta; Pal[i].peGreen=(BYTE)((int)(Pal[i].peGreen/Grad))-nDelta; Pal[i].peBlue=(BYTE)((int)(Pal[i].peBlue/Grad))-nDelta; } } //更新調(diào)色板 lpDDPal->SetEntries(0,0,256,Pal); } //灰度轉(zhuǎn)換函數(shù)--本程序的關(guān)鍵 //函數(shù):ConvertToGrayScale //參數(shù):Method為轉(zhuǎn)換灰度的方式,值可為: // MAXIMUM_GRAY=最大值法,MEAN_GRAY=平均值法, // WEIGHT_GRAY=加權(quán)平均值法 // Color目前只能為8即只能處理8位調(diào)色板方式 //返值:無(wú) void ConvertToGrayScale(unsigned short Method,unsigned short Color) { BYTE Convert; int i; switch(Color) { case 8: LPPALETTEENTRY Pal = (LPPALETTEENTRY) LocalAlloc( LPTR, sizeof( PALETTEENTRY ) * 256 ); //獲取調(diào)色板 lpDDPal->GetEntries(0,0,256,Pal); switch(Method) { case MAXIMUM_GRAY: //最大值法轉(zhuǎn)換 for(i=0; i<256; i++) { //計(jì)算的公式為:R=G=B=max(R,G,B) Convert=( max(max(Pal[i].peRed ,Pal[i].peGreen),Pal[i].peBlue)); Pal[i].peRed=Pal[i].peGreen=Pal[i].peBlue=Convert; } break; case MEAN_GRAY: //平均值法轉(zhuǎn)換 for(i=0; i<256; i++) { //計(jì)算的公式為:R=G=B=(R+G+B)/3 Convert=((Pal[i].peRed +Pal[i].peGreen+Pal[i].peBlue)/3); Pal[i].peRed=Pal[i].peGreen=Pal[i].peBlue=Convert; } break; case WEIGHT_GRAY: //加權(quán)平均值法轉(zhuǎn)換 for(i=0; i<256; i++) { //計(jì)算的公式為:R=G=B=(R*0.3+G*0.59+B*0.11) //為不使用浮點(diǎn)乘法,現(xiàn)公式為: //R=G=B=(R*3+G*6+B)/10 //些許的誤差可以不計(jì) Convert=( Pal[i].peRed * 3 + Pal[i].peGreen *6 + Pal[i].peBlue ) / 10; Pal[i].peRed=Pal[i].peGreen=Pal[i].peBlue=Convert; } break; } //更新調(diào)色板 lpDDPal->SetEntries(0,0,256,Pal); break; } } //********************************** //函數(shù):FreeObject //功能:釋放所有DirectDraw對(duì)象 void FreeObjects( void ) { if( lpDD != NULL )//釋放DirectDraw對(duì)象 { if( lpDDSPrimary != NULL )//釋放主頁(yè)面 { lpDDSPrimary->Release(); lpDDSPrimary = NULL; } if( lpDDSPic1 != NULL )//釋放離屏頁(yè)面1 { lpDDSPic1->Release(); lpDDSPic1 = NULL; } if( lpDDPal != NULL )//釋放調(diào)色板 { lpDDPal->Release(); lpDDPal = NULL; } lpDD->Release(); lpDD = NULL; } } //************************************ //函數(shù):RestoreAll //功能:頁(yè)面丟失后,恢復(fù)頁(yè)面內(nèi)存 HRESULT RestoreAll( void ) { HRESULT ddrval; //恢復(fù)主頁(yè)面,這也將恢復(fù)換頁(yè)鏈中的所有頁(yè)面 ddrval = lpDDSPrimary->Restore(); //恢復(fù)離屏頁(yè)面 ddrval = lpDDSPic1->Restore(); //重新繪制頁(yè)面圖象 InitSurfaces(); return ddrval; } //************************************** //函數(shù):WindowProc //功能:主窗口的消息處理過(guò)程 LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ) { case WM_SETCURSOR: SetCursor(NULL); return TRUE; case WM_ACTIVATEAPP://應(yīng)用程序激活消息 bActive = wParam; break; case WM_KEYDOWN://擊鍵消息 switch( wParam ) { case VK_ESCAPE: PostMessage(hWnd, WM_CLOSE, 0, 0); break; case VK_F1: Gray=true; Key=MEAN_GRAY; InitPalette(); break; case VK_F2: Gray=true; Key=MAXIMUM_GRAY; InitPalette(); break; case VK_F3: Gray=true; Key=WEIGHT_GRAY; InitPalette(); break; case VK_F4: Gray=false; Key=0; InitPalette(); break; case VK_F5: Contrast=!Contrast; if(false==Contrast) { InitPalette(); } break; case VK_F6: break; } break; case WM_DESTROY://銷(xiāo)毀窗口消息 FreeObjects(); PostQuitMessage(0); break; } //調(diào)用缺省的過(guò)程處理過(guò)程 return DefWindowProc(hWnd, message, wParam, lParam); } //********************************* //函數(shù):InitWindow() //功能:創(chuàng)建主窗口。 BOOL InitWindow( HINSTANCE hInstance, int nCmdShow ) { WNDCLASS wc; //窗口類(lèi)結(jié)構(gòu) //填充窗口類(lèi)結(jié)構(gòu) wc.style = 0; wc.lpfnWndProc = WinProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION ); wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);//選擇黑色刷做為窗口背景 wc.lpszMenuName = NULL; wc.lpszClassName = CLASSNAME; //注冊(cè)窗口類(lèi) RegisterClass( &wc ); //創(chuàng)建主窗口 hWndMain= CreateWindowEx( 0, CLASSNAME, //窗口的類(lèi)名稱,必須與上面的wc.lpszClassName一致 TITLE, //窗口的標(biāo)題名 WS_POPUP, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ), NULL, NULL, hInstance, NULL ); if( !hWndMain ) return FALSE; //顯示并更新窗口 ShowWindow( hWndMain, nCmdShow ); return TRUE; } //********************************* //函數(shù):InitDDraw() //功能:初始化DirectDraw環(huán)境,創(chuàng)建換頁(yè)鏈(主頁(yè)面,一個(gè)后臺(tái)緩沖區(qū)) // 以及創(chuàng)建一個(gè)定時(shí)器。 BOOL InitDDraw(void) { DDSURFACEDESC ddsd; DDSCAPS ddscaps; HRESULT ddrval; //創(chuàng)建DirectDraw對(duì)象 ddrval = DirectDrawCreate( NULL, &lpDD, NULL ); if( ddrval != DD_OK ) return FALSE; //取得全屏獨(dú)占模式 ddrval = lpDD->SetCooperativeLevel( hWndMain, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ); if( ddrval != DD_OK ) return FALSE; //設(shè)置顯示器顯示模式為640x480x8 ddrval = lpDD->SetDisplayMode( WIDTH, HEIGHT, COLORS); if( ddrval != DD_OK ) return FALSE; //填充換頁(yè)鏈結(jié)構(gòu) ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; //后臺(tái)緩沖區(qū)數(shù)量為1 ddsd.dwBackBufferCount = 1; //創(chuàng)建換頁(yè)鏈,包括了主頁(yè)面及其后臺(tái)緩沖區(qū) ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ); if( ddrval != DD_OK ) return FALSE; //獲得指向后臺(tái)緩沖區(qū)的頁(yè)面指針 ddscaps.dwCaps = DDSCAPS_BACKBUFFER; ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack); if( ddrval != DD_OK ) return FALSE; //創(chuàng)建離屏頁(yè)面 ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwWidth = WIDTH; ddsd.dwHeight = HEIGHT; if (lpDD->CreateSurface(&ddsd, &lpDDSPic1, NULL) != DD_OK) return FALSE; //調(diào)用頁(yè)面初始化函數(shù) if( !InitSurfaces() ) return FALSE; return TRUE; } //********************************** //函數(shù):WinMain() //功能:應(yīng)用程序入口 int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow) { MSG msg; hInst=hInstance; //初始化主窗口 if (!InitWindow( hInstance, nCmdShow)) return FALSE; //初始化DirectDraw環(huán)境 if (!InitDDraw()) { MessageBox(hWndMain, "初始化DirectDraw過(guò)程中出錯(cuò)!", "Error", MB_OK); FreeObjects(); DestroyWindow(hWndMain); return FALSE; } //進(jìn)入消息循環(huán) while(1) { if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if(!GetMessage(&msg, NULL, 0, 0 )) return msg.wParam; TranslateMessage(&msg); DispatchMessage(&msg); } else if(bActive) { UpdateFrame(); } else WaitMessage(); } return msg.wParam; } BOOL InitPalette(void) { //從磁盤(pán)文件中載入調(diào)色板 lpDDPal = DDLoadPalette(lpDD, "back.bmp"); //將調(diào)色板設(shè)置給主頁(yè)面 if (lpDDPal) { lpDDSPrimary->SetPalette( lpDDPal ); return TRUE; } return FALSE; } //**************************** //函數(shù):InitSurfaces() //功能:初始化頁(yè)面圖象 BOOL InitSurfaces( void ) { HBITMAP hbm; InitPalette(); //從磁盤(pán)文件中將我們所需要的圖象載入到一個(gè)hbm位圖對(duì)象中 hbm = (HBITMAP)LoadImage(hInst, "back.bmp", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE); if (hbm == NULL) return FALSE; DDCopyBitmap(lpDDSPic1, hbm, 0, 0, WIDTH, HEIGHT); //釋放hbm位圖對(duì)象 DeleteObject(hbm); return TRUE; } //更新屏幕 void UpdateFrame( void ) { HRESULT ddrval; //計(jì)算刷新率 static int fps=0, frame=0, nt=0, ot=0; frame++; nt=timeGetTime(); if (nt > ot+1000) { ot=nt; fps=frame; frame=0; } //清屏后臺(tái)緩沖區(qū) DDBLTFX ddBltFx; ddBltFx.dwSize = sizeof(DDBLTFX); ddBltFx.dwFillColor = DDColorMatch(lpDDSBack, RGB(0,0,0)); lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddBltFx); //調(diào)用灰度的實(shí)現(xiàn)函數(shù) if(true==Gray) { ConvertToGrayScale(Key,COLORS); Gray=false; } //增加對(duì)比度 if(true==Contrast) { ChangeContrast(2); } RECT srect, drect; MakeRect(&srect, 0, 0, WIDTH, HEIGHT); MakeRect(&drect, 0, 0, WIDTH, HEIGHT); //將背景圖象Blit到后臺(tái)緩沖區(qū) lpDDSBack->Blt(&drect, lpDDSPic1, &srect, DDBLT_WAIT, NULL); //打印刷新率fps HDC hdc; char temp[50]; lpDDSBack->GetDC(&hdc); SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, RGB(0,255,255)); sprintf(temp, "fps=%d", fps); TextOut(hdc, 0, 0, temp, strlen(temp)); sprintf(temp,"圖象特效----灰度轉(zhuǎn)換"); TextOut(hdc, 30, 400, temp, strlen(temp)); lpDDSBack->ReleaseDC(hdc); // 換頁(yè) while( 1 ) { ddrval = lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );//調(diào)用換頁(yè)函數(shù) if( ddrval == DD_OK )//成功則退出while循環(huán) break; else if( ddrval == DDERR_SURFACELOST )//如果頁(yè)面丟失,則恢復(fù)頁(yè)面,再繼續(xù)while循環(huán) RestoreAll(); else break; } } void MakeRect(RECT *rect, long left, long top, long right, long bottom) { rect->left=left; rect->top=top; rect->right=right; rect->bottom=bottom; }
感興趣的朋友可以調(diào)試運(yùn)行一下本文實(shí)例,相信會(huì)對(duì)大家進(jìn)行C++項(xiàng)目開(kāi)發(fā)起到一定的幫助作用。
上一篇:VC++中HTControl控件類(lèi)的CHTSlider控制桿控件類(lèi)簡(jiǎn)介
欄 目:C語(yǔ)言
下一篇:VC++中HTControl控件類(lèi)之CHTRichEdit富文本編輯控件實(shí)例
本文標(biāo)題:C++基于Directx MMX實(shí)現(xiàn)的圖像灰度轉(zhuǎn)換代碼
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3519.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類(lèi)算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式詳解
- 01-10基于atoi()與itoa()函數(shù)的內(nèi)部實(shí)現(xiàn)方法詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什