匯東網


屏幕图像轮廓抓取程序

[編輯] [转简体]
|
作者:huidong | 分類:【編程】EasyX
[ 22 瀏覽 0 評論 7 贊 9 踩 ]

概要

正文

///////////////////////////////////////////////////////
//
//    代码简介:
//    在原作者实现的桌面截图函数的基础上
//    修改而成的多扩展屏的桌面截图
// 
//    修改为了屏幕轮廓抓取程序,附带有简单的鼠标远程操作相应
//    修改为在不同电脑上运行的程序后,可以丰富鼠标操作内容
//    支持多屏幕
//
//
//    编译环境: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;
}


[ 7] [ 9]


 評論區  0 條評論

+ 添加評論