光标周围的位图屏幕| CopyFromScreen

时间:2015-03-01 16:59:31

标签: c# bitmap

什么吗

我有一个应用程序,它通过颜色代码扫描我的屏幕图像。

问题!

此过程耗时太长,因为搜索整个屏幕。

我的目标

我想搜索当前鼠标位置周围的区域。 但是我该怎么做?

代码

这是我的代码:

  1. 创建一个屏幕

    private Bitmap CaptureScreen()
    {
       //Point a = new Point();
       //a = Control.MousePosition;   
    
        Bitmap b = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
        using (Graphics g = Graphics.FromImage(b))
        {
            g.CopyFromScreen(new Point(0, 0), new Point(0, 0), b.Size);
        }
    
        return b;
    }
    
  2. 搜索颜色代码

    public Point GetPixelPosition(Color SearchColor, bool IgnoreAlphaChannel)
    {
        //Point a = new Point();
        //a = Control.MousePosition;
    
    
        _ColorFound = false;
        Point PixelPt = new Point(0, 0);
    
        using (Bitmap b = CaptureScreen())
        {
            for (int i = 0; i < b.Width; i++)
            {
                if (this._ColorFound)
                    break;
    
                for (int j = 0; j < b.Height; j++)
                {
                    if (this._ColorFound)
                        break;
    
                    Color tmpPixelColor = b.GetPixel(i, j);
                    if (((tmpPixelColor.A == SearchColor.A) || IgnoreAlphaChannel)
                        && (tmpPixelColor.R == SearchColor.R)
                        && (tmpPixelColor.G == SearchColor.G)
                        && (tmpPixelColor.B == SearchColor.B)
                        )
                    {
                        PixelPt.X = i;
                        PixelPt.Y = j;
                        this._ColorFound = true;
                    }
                }
            }
        }
    
        return PixelPt;
    }
    

2 个答案:

答案 0 :(得分:0)

我认为你的扫描方式非常有效......但在这个答案中,我的目标是通过使用你的代码来完成你想要的东西(我还没有完全优化)任何东西):

public Point GetPixelPosition(Color SearchColor, bool IgnoreAlphaChannel, int pixelsToSearchAround)
    {
        Point mousePosition = Cursor.Position;

        _ColorFound = false;
        Point PixelPt = new Point(0, 0);

        using (Bitmap b = CaptureScreen())
        {
            int minX = mousePosition.X - pixelsToSearchAround;
            int maxX = mousePosition.X + pixelsToSearchAround;
            int minY = mousePosition.Y - pixelsToSearchAround;
            int maxY = mousePosition.Y + pixelsToSearchAround;
            if(minX < 0) minX = 0;
            if(minY < 0) minY = 0;
            if(maxX > b.Width) maxX = b.Width;
            if(maxY > b.Height) maxY = b.Height;

            for (int i = minX; i < maxX; i++)
            {
                if (this._ColorFound)
                    break;

                for (int j = minY; j < maxY; j++)
                {
                    if (this._ColorFound)
                        break;

                    Color tmpPixelColor = b.GetPixel(i, j);
                    if (((tmpPixelColor.A == SearchColor.A) || IgnoreAlphaChannel)
                        && (tmpPixelColor.R == SearchColor.R)
                        && (tmpPixelColor.G == SearchColor.G)
                        && (tmpPixelColor.B == SearchColor.B)
                        )
                    {
                        PixelPt.X = i;
                        PixelPt.Y = j;
                        this._ColorFound = true;
                    }
                }
            }
        }

        return PixelPt;
    }

这应该以一种非常不优化的方式做你想要的事情:它不是我在屏幕上搜索像素组件所做的。

您可以使用第三个参数来确定要搜索的光标周围的像素数。

为了进一步优化,您只能捕获您想要捕获的屏幕区域,但我会将其留给您(提示:而不是在GetPixelPosition中执行此操作,您可以执行此操作在CaptureScreen中,修改g.CopyFromScreen的参数,而不是修改循环边界。)

答案 1 :(得分:0)

您可以改善颜色检查方法的性能,而不是限制区域。

不要使用Bitmap.GetPixel!请改用Bitmap.UnlockBits

public static unsafe Point GetPoint (Bitmap bmp, Color c) {
    BitmapData bmd = bmp.LockBits (new Rectangle(0,0,bmp.Width,bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    try {
        int s = bmd.Stride;
        int search = (c.A<<0x18)|(c.R<<0x10)|(c.G<<0x08)|c.B;
        int* clr = (int*)(void*)bmd.Scan0;
        int tmp;
        int* row = clr;
        for (int i = 0; i < bmp.Height; i++) {
            int* col = row;
            for (int j = 0; j < bmp.Width; j++) {
                tmp = *col;
                if(tmp == search) {
                    return new Point(j,i);
                }
                col++;
            }
            row += s>>0x02;
        }
        return new Point(-1,-1);
    } finally {
        bmp.UnlockBits (bmd);
    }
}

如果找不到颜色,此方法将返回(-1,-1)。您可以对其进行调整以忽略alpha - 频道:

public static unsafe Point GetPoint (Bitmap bmp, Color c, bool ignoreAlpha = false) {
    BitmapData bmd = bmp.LockBits (new Rectangle(0,0,bmp.Width,bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    try {
        int s = bmd.Stride;
        int search = (c.A<<0x18)|(c.R<<0x10)|(c.G<<0x08)|c.B;
        if(ignoreAlpha) {
            search &= 0xffffff;
        }
        int* clr = (int*)(void*)bmd.Scan0;
        int tmp;
        int* row = clr;
        for (int i = 0; i < bmp.Height; i++) {
            int* col = row;
            for (int j = 0; j < bmp.Width; j++) {
                tmp = *col;
                if(ignoreAlpha) {
                    tmp &= 0xffffff;
                }
                if(tmp == search) {
                    return new Point(j,i);
                }
                col++;
            }
            row += s>>0x02;
        }
        return new Point(-1,-1);
    } finally {
        bmp.UnlockBits (bmd);
    }
}

GetPixel较慢的原因是您不批量处理它们。这是因为该方法始终需要解码图像并等待您查询的像素走过。使用UnlockBits只解码一次,然后迭代所有像素。