Edge Detection Using C,Win32 SDK and GDI+






4.56/5 (16 votes)
This article shows how to perform edge detection using C,Win32 SDK and GDI+
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
- Create a simple Win32 application - select empty project
- Add a new file Main.cpp
- 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
- Your
WinMain
should look like thisINT 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
- 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
- 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); }