屏幕图像轮廓抓取程序
[編輯] [转简体] (简体译文)
|
作者:huidong
| 分類:【編程】EasyX
[
10 瀏覽
0 評論
3 贊
3 踩
]
概要
正文
/////////////////////////////////////////////////////// // // 代码简介: // 在原作者实现的桌面截图函数的基础上 // 修改而成的多扩展屏的桌面截图 // // 修改为了屏幕轮廓抓取程序,附带有简单的鼠标远程操作相应 // 修改为在不同电脑上运行的程序后,可以丰富鼠标操作内容 // 支持多屏幕 // // // 编译环境:Visual Studio 2022 | EasyX_20220116 // // 原作者:yangw80 <yw80@qq.com> // 修改者:huidong <mailhuid@163.com> // 最后修改:2022.06.03 // #include <Windows.h> #include <WinUser.h> #include <EasyX.h> // 存储整个屏幕的大小信息(多显示器) struct ScreenSize { int left; // 多显示器的左上角 x 坐标 int top; // 多显示器的左上角 y 坐标 int w; // 多显示器的总和宽度 int h; // 多显示器的总和高度 }; ScreenSize s; // 屏幕信息 const float ratio = 0.5; // 画面缩放比例 // 获取多显示器大小信息 ScreenSize GetScreenSize() { int left = GetSystemMetrics(SM_XVIRTUALSCREEN); int top = GetSystemMetrics(SM_YVIRTUALSCREEN); int w = GetSystemMetrics(SM_CXVIRTUALSCREEN); int h = GetSystemMetrics(SM_CYVIRTUALSCREEN); return { left,top,w,h }; } // 抓取桌面图像到 *pimg 对象中 void CaptureDesktop(IMAGE* pimg) { Resize(pimg, s.w, s.h); HDC srcDC = ::GetDC(NULL); HDC dstDC = GetImageHDC(pimg); BitBlt(dstDC, 0, 0, s.w, s.h, srcDC, s.left, s.top, SRCCOPY); } // 图片拉伸 // width, height 拉伸后的图片大小 // img 原图像 void ImageToSize(int width, int height, IMAGE* img) { IMAGE* pOldImage = GetWorkingImage(); SetWorkingImage(img); IMAGE temp_image(width, height); StretchBlt( GetImageHDC(&temp_image), 0, 0, width, height, GetImageHDC(img), 0, 0, getwidth(), getheight(), SRCCOPY ); Resize(img, width, height); putimage(0, 0, &temp_image); SetWorkingImage(pOldImage); } // 是否为边缘点 // b 灰度差阈值 bool isEdgePoint(DWORD* pBuf, int w, int h, int x, int y, int b) { POINT t[4] = { {0,1}, {0,-1}, {1,0}, {-1,0} }; int r = GetRValue(pBuf[y * w + x]); for (int i = 0; i < 4; i++) { int x2 = x + t[i].x, y2 = y + t[i].y; if (x2 >= 0 && x2 < w && y2 >= 0 && y2 < h && GetRValue(pBuf[y2 * w + x2]) - r > b) { return true; } } return false; } // 彩色图像转换为灰度图像 void ColorToGray(IMAGE* pimg) { DWORD* p = GetImageBuffer(pimg); // 获取显示缓冲区指针 COLORREF c; // 逐个像素点读取计算 for (int i = pimg->getwidth() * pimg->getheight() - 1; i >= 0; i--) { c = BGR(p[i]); c = (GetRValue(c) * 299 + GetGValue(c) * 587 + GetBValue(c) * 114 + 500) / 1000; p[i] = RGB(c, c, c); // 由于是灰度值,无需再执行 BGR 转换 } } // 将图像处理为轮廓图像并绘制 // img 原图像 // b 轮廓扫描阈值 void ImageProcess(IMAGE* img, int b = 30) { IMAGE imgGray = *img; int w = img->getwidth(); int h = img->getheight(); POINT* pEdge = new POINT[w * h]; int sum = 0; ColorToGray(&imgGray); DWORD* pBuf = GetImageBuffer(&imgGray); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { if (isEdgePoint(pBuf, w, h, j, i, b)) { pEdge[sum] = { j, i }; sum++; } } } //putimage(0, 0, img); cleardevice(); for (int i = 0; i < sum; i++) { putpixel((int)(pEdge[i].x * ratio), (int)(pEdge[i].y * ratio), GREEN); } FlushBatchDraw(); if (pEdge && sum) { delete pEdge; } } // 处理鼠标消息 // 简单模拟鼠标操作 void MouseMsgProcess() { ExMessage msg; while (peekmessage(&msg, EM_MOUSE)) { if (msg.message == WM_LBUTTONUP) { // 坐标映射到系统,兼容多屏情况 SetCursorPos((int)(msg.x / ratio) + s.left, (int)(msg.y / ratio) + s.top); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); } } } // 主函数 int main() { s = GetScreenSize(); // 创建绘图窗口 initgraph((int)(s.w * ratio), (int)(s.h * ratio)); BeginBatchDraw(); // 定义 IMAGE 对象 IMAGE img; while (true) { // 调用抓取桌面图像的函数 CaptureDesktop(&img); // 输出图像 ImageProcess(&img); // 响应鼠标消息 MouseMsgProcess(); Sleep (10); } // 按任意键退出 getmessage(EM_KEY); EndBatchDraw(); closegraph(); return 0; }