当前位置:  编程技术>c/c++/嵌入式

C++基于Directx MMX实现的图像灰度转换代码

    来源: 互联网  发布时间:2014-10-27

    本文导语:  本文实例讲述了基于Directx MMX 编写的实现图像灰度处理的方法,要编译此程序需DirectX SDK5.0,代码中所需要的ddutil.h与ddutil.cpp文件,请自行下载加入工程。在WindowNT4.0+SP3环境中编译通过,代码已经过整理,包含有注释。如下所示...

本文实例讲述了基于Directx MMX 编写的实现图像灰度处理的方法,要编译此程序需DirectX SDK5.0,代码中所需要的ddutil.h与ddutil.cpp文件,请自行下载加入工程。在WindowNT4.0+SP3环境中编译通过,代码已经过整理,包含有注释。如下所示:

#include 
#include 
#include 
#include 
#include 
#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(*pByteGetEntries(0,0,256,Pal);
 switch(Method)
 {
 case MAXIMUM_GRAY:
  //最大值法转换
  for(i=0; iRelease();
      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++项目开发起到一定的帮助作用。


    
 
 

您可能感兴趣的文章:

 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • windows10玩游戏怎么样?唯一支持DirectX 12的windows
  • 哪位网友用过DirectX for java的,今天学习DirectX的时候看到的这些api,呵呵,好奇啊!
  • DirectX To OpenGL 翻译层 TOGL
  • directx 和 linux
  • DirectX 的封装库 SharpDX
  • 混合语言编程—C#使用原生的Directx和OpenGL绘图的方法


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3