Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Edge Detection Using C,Win32 SDK and GDI+

0.00/5 (No votes)
19 Apr 2002 2  
This article shows how to perform edge detection using C,Win32 SDK and GDI+

Sample Image - Edge_Detection.jpg

Introduction

This article is an adaptation of Christian Graus article on the same topic which was in C#. I was keen to do the same in C and hence this article. Though simple I had lot of trouble porting the code from C# to C. I want to take this opportunity to thank Christian for his help in making this program work.

Initializing GDI+

Take the November 2001 platform SDK CD and straight away install the whole thing. Make sure to have gdiplus.dll in your application directory. Also go to tools/options/directories in Visual Studio to point to the GDI+ lib and header files. Important: :They should be at the top of the include list to avoid conflicts.

Includes

  1. Create a simple Win32 application - select empty project  
  2. Add a new file Main.cpp
  3. Include the following:
    • ws2_32.lib in the project/settings/link 
    • Add this code to your cpp file:
      #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. Your WinMain should look like this
    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. Your Window procedure should look like this:
    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. Your OnPaint() looks like this:
    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);      
    
    }

That's It

Write to me for any problems/explanation. I will be glad to respond.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here