程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++基於Directx MMX完成的圖象灰度轉換代碼

C++基於Directx MMX完成的圖象灰度轉換代碼

編輯:關於C++

C++基於Directx MMX完成的圖象灰度轉換代碼。本站提示廣大學習愛好者:(C++基於Directx MMX完成的圖象灰度轉換代碼)文章只能為提供參考,不一定能成為您想要的結果。以下是C++基於Directx MMX完成的圖象灰度轉換代碼正文


本文實例講述了基於Directx MMX 編寫的完成圖象灰度處置的辦法,要編譯此法式需DirectX SDK5.0,代碼中所須要的ddutil.h與ddutil.cpp文件,請自行下載參加工程。在WindowNT4.0+SP3情況中編譯經由過程,代碼曾經過整頓,包括有正文。以下所示:

#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//加權均勻值法
#define TITLE "灰度轉換" //窗口題目
#define CLASSNAME "Gray" //窗口類名
#define WIDTH 640
#define HEIGHT 480
#define COLORS 8
#define STEP 1
#define SCANLINE 16
HINSTANCE hInst; //運用法式實例句柄
HWND hWndMain; //主窗口句柄
LPDIRECTDRAW      lpDD;      // DirectDraw對象
LPDIRECTDRAWSURFACE   lpDDSPrimary;  // 主頁面
LPDIRECTDRAWSURFACE   lpDDSBack;   // 後台緩沖區
LPDIRECTDRAWSURFACE   lpDDSPic1;   // 離屏頁面1
LPDIRECTDRAWPALETTE   lpDDPal;    // 調色板
BOOL          bActive;    // 運用法式能否活潑?
int Key=0;
bool Contrast=false;
bool Gray=false;
//函數聲明
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 );
 //獲得調色板
 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;
 }
 }
 //更新調色板
 lpDDPal->SetEntries(0,0,256,Pal);
}
//灰度轉換函數--本法式的症結
//函數:ConvertToGrayScale
//參數:Method為轉換灰度的方法,值可為:
// MAXIMUM_GRAY=最年夜值法,MEAN_GRAY=均勻值法,
// WEIGHT_GRAY=加權均勻值法
// Color今朝只能為8即只能處置8位調色板方法
//返值:無
void ConvertToGrayScale(unsigned short Method,unsigned short Color)
{
 BYTE Convert; 
 int i;
 switch(Color)
 {
 case 8:
 LPPALETTEENTRY Pal = (LPPALETTEENTRY) LocalAlloc( LPTR, sizeof( PALETTEENTRY ) * 256 );
 //獲得調色板
 lpDDPal->GetEntries(0,0,256,Pal);
 switch(Method)
 {
 case MAXIMUM_GRAY:
  //最年夜值法轉換
  for(i=0; i<256; i++)
  {
  //盤算的公式為: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:
  //均勻值法轉換
  for(i=0; i<256; i++)
  {
  //盤算的公式為: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:
  //加權均勻值法轉換
  for(i=0; i<256; i++)
  {
  //盤算的公式為:R=G=B=(R*0.3+G*0.59+B*0.11)
  //為不應用浮點乘法,現公式為:
  //R=G=B=(R*3+G*6+B)/10
  //些許的誤差可以不計
  Convert=( Pal[i].peRed * 3 + Pal[i].peGreen *6 + Pal[i].peBlue ) / 10; 
  Pal[i].peRed=Pal[i].peGreen=Pal[i].peBlue=Convert;
  } 
  break;  
 }
 //更新調色板
 lpDDPal->SetEntries(0,0,256,Pal);
 break;
 }
}
//**********************************
//函數:FreeObject
//功效:釋放一切DirectDraw對象
void FreeObjects( void )
{
  if( lpDD != NULL )//釋放DirectDraw對象
  {
    if( lpDDSPrimary != NULL )//釋放主頁面
    {
      lpDDSPrimary->Release();
      lpDDSPrimary = NULL;
    }
    if( lpDDSPic1 != NULL )//釋放離屏頁面1
    {
      lpDDSPic1->Release();
      lpDDSPic1 = NULL;
    }
    if( lpDDPal != NULL )//釋放調色板
    {
      lpDDPal->Release();
      lpDDPal = NULL;
    }
    lpDD->Release();
    lpDD = NULL;
  }
} 
//************************************
//函數:RestoreAll
//功效:頁面喪失後,恢復頁面內存
HRESULT RestoreAll( void )
{
  HRESULT   ddrval;
 //恢復主頁面,這也將恢復換頁鏈中的一切頁面
  ddrval = lpDDSPrimary->Restore();
 //恢復離屏頁面
  ddrval = lpDDSPic1->Restore();
 //從新繪制頁面圖像
 InitSurfaces();
  return ddrval;
}
//**************************************
//函數:WindowProc
//功效:主窗口的新聞處置進程
LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
  switch( message )
  {
  case WM_SETCURSOR:
 SetCursor(NULL);
 return TRUE;

  case WM_ACTIVATEAPP://運用法式激活新聞
    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://燒毀窗口新聞
    FreeObjects();
    PostQuitMessage(0);
    break;
  }

 //挪用缺省的進程處置進程
  return DefWindowProc(hWnd, message, wParam, lParam);
}
//*********************************
//函數:InitWindow()
//功效:創立主窗口。
BOOL InitWindow( HINSTANCE hInstance, int nCmdShow )
{
  WNDCLASS wc; //窗口類構造
 //填充窗口類構造
  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;
 //注冊窗口類
  RegisterClass( &wc );
  //創立主窗口
  hWndMain= CreateWindowEx(
 0,
 CLASSNAME, //窗口的類稱號,必需與下面的wc.lpszClassName分歧
 TITLE, //窗口的題目名
 WS_POPUP,
 0,
 0,
 GetSystemMetrics( SM_CXSCREEN ),
 GetSystemMetrics( SM_CYSCREEN ),
 NULL,
 NULL,
 hInstance,
 NULL );
  if( !hWndMain ) 
 return FALSE;
 //顯示並更新窗口
  ShowWindow( hWndMain, nCmdShow );
 return TRUE;
}
//*********************************
//函數:InitDDraw()
//功效:初始化DirectDraw情況,創立換頁鏈(主頁面,一個後台緩沖區)
// 和創立一個准時器。
BOOL InitDDraw(void)
{
  DDSURFACEDESC    ddsd;
  DDSCAPS       ddscaps;
  HRESULT       ddrval;

  //創立DirectDraw對象
 ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
  if( ddrval != DD_OK )
    return FALSE;
  //獲得全屏獨有形式
  ddrval = lpDD->SetCooperativeLevel( hWndMain, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  if( ddrval != DD_OK )
    return FALSE;
  //設置顯示器顯示形式為640x480x8
  ddrval = lpDD->SetDisplayMode( WIDTH, HEIGHT, COLORS);
  if( ddrval != DD_OK )
    return FALSE;
  //填充換頁鏈構造
  ddsd.dwSize = sizeof( ddsd );
  ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
             DDSCAPS_FLIP |
             DDSCAPS_COMPLEX;
 //後台緩沖區數目為1
  ddsd.dwBackBufferCount = 1;
 //創立換頁鏈,包含了主頁面及厥後台緩沖區
  ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
  if( ddrval != DD_OK )
    return FALSE;
  //取得指向後台緩沖區的頁面指針
 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);
  if( ddrval != DD_OK )
    return FALSE;
 //創立離屏頁面
 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;
 //挪用頁面初始化函數
 if( !InitSurfaces() )
    return FALSE;
  return TRUE;
}
//**********************************
//函數:WinMain()
//功效:運用法式進口
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
  MSG msg;
 hInst=hInstance;
 //初始化主窗口
 if (!InitWindow( hInstance, nCmdShow))
  return FALSE;
 //初始化DirectDraw情況
 if (!InitDDraw())
 {
 MessageBox(hWndMain, "初始化DirectDraw進程中失足!", "Error", MB_OK);
 FreeObjects();
 DestroyWindow(hWndMain);
 return FALSE;
 }
 //進入新聞輪回
 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)
{
  //從磁盤文件中載入調色板
 lpDDPal = DDLoadPalette(lpDD, "back.bmp");
 //將調色板設置給主頁面
  if (lpDDPal)
 {
    lpDDSPrimary->SetPalette( lpDDPal );
 return TRUE;
 }
 return FALSE;
}
//****************************
//函數:InitSurfaces()
//功效:初始化頁面圖像
BOOL InitSurfaces( void )
{
  HBITMAP hbm;
 InitPalette();
  //從磁盤文件中將我們所須要的圖像載入到一個hbm位圖對象中
  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位圖對象
  DeleteObject(hbm);
  return TRUE;
}
//更新屏幕
void UpdateFrame( void )
{
 HRESULT ddrval;
 //盤算刷新率
 static int fps=0, frame=0, nt=0, ot=0;
 frame++;
 nt=timeGetTime(); 
 if (nt > ot+1000)
 {
 ot=nt;
 fps=frame;
 frame=0;
 }
 //清屏後台緩沖區
 DDBLTFX ddBltFx;
 ddBltFx.dwSize = sizeof(DDBLTFX);
 ddBltFx.dwFillColor = DDColorMatch(lpDDSBack, RGB(0,0,0));
 lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddBltFx);
 //挪用灰度的完成函數
 if(true==Gray)
 {
 ConvertToGrayScale(Key,COLORS);
 Gray=false;
 }
 //增長比較度
 if(true==Contrast)
 {
 ChangeContrast(2);
 }

 RECT srect, drect;
 MakeRect(&srect, 0, 0, WIDTH, HEIGHT);
 MakeRect(&drect, 0, 0, WIDTH, HEIGHT);
 //將配景圖像Blit到後台緩沖區
 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,"圖像殊效----灰度轉換");
 TextOut(hdc, 30, 400, temp, strlen(temp));
 lpDDSBack->ReleaseDC(hdc);
  // 換頁
  while( 1 )
  {
    ddrval = lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );//挪用換頁函數
    if( ddrval == DD_OK )//勝利則加入while輪回
      break;
    else if( ddrval == DDERR_SURFACELOST )//假如頁面喪失,則恢復頁面,再持續while輪回
      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;
}

感興致的同伙可以調試運轉一下本文實例,信任會對年夜家停止C++項目開辟起到必定的贊助感化。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved