65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C、Win32 SDK 和 GDI+ 进行边缘检测

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.56/5 (16投票s)

2002年4月19日

CPOL
viewsIcon

172645

downloadIcon

1531

本文档展示了如何使用 C、Win32 SDK 和 GDI+ 进行边缘检测。

Sample Image - Edge_Detection.jpg

引言

本文是对 Christian Graus 关于相同主题的 C# 文章的改编。我渴望用 C 实现相同的功能,因此写了这篇文章。虽然很简单,但我将代码从 C# 移植到 C 时遇到了很多麻烦。我想借此机会感谢 Christian 帮助我使这个程序正常工作。

初始化 GDI+

取出 2001 年 11 月的平台 SDK CD 并直接安装整个内容。确保在您的应用程序目录中包含 gdiplus.dll。 此外,在 Visual Studio 中转到“工具/选项/目录”以指向 GDI+ 库和头文件。 重要提示::它们应该位于包含列表的顶部,以避免冲突。

包含

  1. 创建一个简单的 Win32 应用程序 - 选择空项目  
  2. 添加一个新文件 Main.cpp
  3. 包含以下内容
    • 在项目/设置/链接中包含 ws2_32.lib 
    • 将此代码添加到您的 cpp 文件
      #define UNICODE
      #include <windows.h>
      #include <gdiplus.h>
      #include <math.h>
      #include <stdio.h>
      using namespace Gdiplus;
      LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //WinProc prototype

  4. 您的 WinMain 应该如下所示
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow)
    {
       HWND                hWnd;
       MSG                 msg;
       WNDCLASS            wndClass;
       GdiplusStartupInput gdiplusStartupInput;
       ULONG_PTR           gdiplusToken;
    
       // Initialize GDI+.
       GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    
       wndClass.style          = CS_HREDRAW | CS_VREDRAW;
       wndClass.lpfnWndProc    = WndProc;
       wndClass.cbClsExtra     = 0;
       wndClass.cbWndExtra     = 0;
       wndClass.hInstance      = hInstance;
       wndClass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
       wndClass.hCursor        = LoadCursor(NULL, IDC_ARROW);
       wndClass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
       wndClass.lpszMenuName   = NULL;
       wndClass.lpszClassName  = TEXT("Edge Detection");
    
       RegisterClass(&wndClass);
    
       hWnd = CreateWindow(
          TEXT("Edge Detection"),   // window class name
          TEXT("Edge Detection"),  // window caption
          WS_OVERLAPPEDWINDOW,      // window style
          CW_USEDEFAULT,            // initial x position
          CW_USEDEFAULT,            // initial y position
          CW_USEDEFAULT,            // initial x size
          CW_USEDEFAULT,            // initial y size
          NULL,                     // parent window handle
          NULL,                     // window menu handle
          hInstance,                // program instance handle
          NULL);                    // creation parameters
    
       ShowWindow(hWnd, iCmdShow);
       UpdateWindow(hWnd);
    
       while(GetMessage(&msg, NULL, 0, 0))
       {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
       }
    
       GdiplusShutdown(gdiplusToken);
       return msg.wParam;
    }  // WinMain
    
    
  5. 您的窗口过程应该如下所示
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, 
       WPARAM wParam, LPARAM lParam)
    {
       HDC          hdc;
       PAINTSTRUCT  ps;
    
       switch(message)
       {
       case WM_CREATE:
    		//OnCreate();
    		return 0;
    
       case WM_PAINT:
          hdc = BeginPaint(hWnd, &ps);
          OnPaint(hdc);
          EndPaint(hWnd, &ps);
          return 0;
    
       case WM_DESTROY:
          PostQuitMessage(0);
          return 0;
    
       default:
          return DefWindowProc(hWnd, message, wParam, lParam);
       }
    } // WndProc
    
    
  6. 您的 OnPaint() 如下所示
    VOID OnPaint(HDC hdc)
    {	
       Graphics graphics(hdc);
    
       Bitmap b(L"Calvin.jpg");
       Bitmap* b2;
    
       INT iWidth = b.GetWidth();
       INT iHeight = b.GetHeight();
    
       Rect rect(0,0,iWidth,iHeight);
       b2 = b.Clone(rect,PixelFormat24bppRGB); 
    
      
       BitmapData bmData;
       BitmapData bmData2;
    
       b.LockBits(&rect,ImageLockModeRead | ImageLockModeWrite,
                  PixelFormat24bppRGB,&bmData);
       b2->LockBits(&rect,ImageLockModeRead |ImageLockModeWrite,
                    PixelFormat24bppRGB,&bmData2);
       
       int stride = bmData.Stride;
    
       unsigned char * p = (unsigned char *)bmData.Scan0;
       unsigned char * p2 = (unsigned char *)bmData2.Scan0;
       
       
       int nOffset = stride - iWidth*3; 
       int nWidth = iWidth * 3;
    
       int nPixel = 0, nPixelMax = 0;
    
       p += stride;
       p2 += stride;
       int nThreshold = 0;
       
      for(int y=1;y < (iHeight-1);++y)
      {
         p += 3;
         p2 += 3;
    
         for(int x=3; x < (nWidth-3); ++x )
         {  			
    		
            nPixelMax = abs((p2 - stride + 3)[0] - (p2+stride-3)[0]);
            nPixel = abs((p2 + stride + 3)[0] - (p2 - stride - 3)[0]);
            if (nPixel>nPixelMax)
               nPixelMax = nPixel;
    
            nPixel = abs((p2 - stride)[0] - (p2 + stride)[0]);
            if (nPixel>nPixelMax)
                nPixelMax = nPixel;
    
            nPixel = abs((p2+3)[0] - (p2 - 3)[0]);
            if (nPixel>nPixelMax)
                nPixelMax = nPixel;
    
            if (nPixelMax < nThreshold) 
    	    nPixelMax = 0;							
    		
            p[0] = (byte) nPixelMax;
    
            ++ p;
            ++ p2;
                
         }
    
         p += 3 + nOffset;
         p2 += 3 + nOffset;
    }
        
       
       b.UnlockBits(&bmData);
       b2->UnlockBits(&bmData2);
    
       graphics.DrawImage(b2,0,0,iWidth,iHeight);
       graphics.DrawImage(&b, iWidth+10, 0, iWidth, iHeight);      
    
    }

就这些

如有任何问题/解释,请与我联系。我将很乐意回复。
© . All rights reserved.