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






4.56/5 (16投票s)
本文档展示了如何使用 C、Win32 SDK 和 GDI+ 进行边缘检测。
引言
本文是对 Christian Graus 关于相同主题的 C# 文章的改编。我渴望用 C 实现相同的功能,因此写了这篇文章。虽然很简单,但我将代码从 C# 移植到 C 时遇到了很多麻烦。我想借此机会感谢 Christian 帮助我使这个程序正常工作。
初始化 GDI+
取出 2001 年 11 月的平台 SDK CD 并直接安装整个内容。确保在您的应用程序目录中包含 gdiplus.dll。 此外,在 Visual Studio 中转到“工具/选项/目录”以指向 GDI+ 库和头文件。 重要提示::它们应该位于包含列表的顶部,以避免冲突。包含
- 创建一个简单的 Win32 应用程序 - 选择空项目
- 添加一个新文件 Main.cpp
- 包含以下内容
- 在项目/设置/链接中包含 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
- 您的
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
- 您的窗口过程应该如下所示
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
- 您的
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); }