确定的像素的颜色在一个WinForms应用程序(Determine color of a pixel

2019-06-23 13:18发布

我希望能够确定在屏幕上的某一个点一个winform的backgroundColor,所以取决于特定的颜色,我可以采取一些行动。 可悲的是System.Drawing中图书馆似乎并没有规定,使我这样做的方法。

我应该如何再确定在某一点的颜色?

Answer 1:

使用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;

namespace ColorUnderCursor
{
    class CursorColor
    {
        [DllImport("gdi32")]
        public static extern uint GetPixel(IntPtr hDC, int XPos, int YPos);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetCursorPos(out POINT pt);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);

        /// <summary> 
        /// Gets the System.Drawing.Color from under the mouse cursor. 
        /// </summary> 
        /// <returns>The color value.</returns> 
        public static Color Get()
        {
            IntPtr dc = GetWindowDC(IntPtr.Zero);

            POINT p;
            GetCursorPos(out p);

            long color = GetPixel(dc, p.X, p.Y);
            Color cc = Color.FromArgb((int)color);
            return Color.FromArgb(cc.B, cc.G, cc.R);
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;
        public POINT(int x, int y)
        {
            X = x;
            Y = y;
        } 
    }
}


Answer 2:

假如你想远离Win32 API的时候,你可以使用Graphics.CopyFromScreen()到屏幕上的内容绘制到一个Bitmap对象。 从那里,你只需要使用Bitmap.GetPixel()来检索Color与正确的颜色对象。

下面是一些代码,你可以用它来获取完整的桌面(多显示器的工作原理):

public Image GetScreenshot()
{
    int screenWidth = Convert.ToInt32(System.Windows.SystemParameters.VirtualScreenWidth);
    int screenHeight = Convert.ToInt32(SystemParameters.VirtualScreenHeight);
    int screenLeft = Convert.ToInt32(SystemParameters.VirtualScreenLeft);
    int screenTop = Convert.ToInt32(SystemParameters.VirtualScreenTop);

    Image imgScreen = new Bitmap(screenWidth, screenHeight);
    using (Bitmap bmp = new Bitmap(screenWidth, screenHeight, PixelFormat.Format32bppArgb))
    using (Graphics g = Graphics.FromImage(bmp))
    using (Graphics gr = Graphics.FromImage(imgScreen))
    {
        g.CopyFromScreen(screenLeft, screenTop, 0, 0, new Size(screenWidth, screenHeight));
        gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        gr.DrawImage(bmp, new Rectangle(0, 0, screenWidth, screenHeight));
    }

    return imgScreen;
}


Answer 3:

这是一个稍微不同的看法上已经提供如你只说,你要确定的“色”,但没有明确表示你想要的RGB值,其他的答案。

这种区别是必需的,因为可能存在变型的颜色是察觉不到的人的眼睛。 例如,让我们假设你有兴趣检测的颜色“蓝色”。 值(5,5,240)和(10,10,255)只能从(0,0,255)非常微妙的不同。 事实上,不同的是很微妙你需要通过侧到色板面比较分开,即使如此,它取决于你的显示器的品质告诉他们。 他们是我的桌面显示器上略有不同,但都在我的笔记本电脑没有什么区别。 为了削减长话短说,RGB值是决定颜色的好方法。

有许多方法计算的颜色,最常见的是三角洲-E方法之间的差异,以帮助。 然而,这可能是过来杀掉,如果你只是想要一个快速和肮脏的方法。 转换RGB空间变成HSV和使用的不同色调确定颜色。 修改阿门的例子,你会得到如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;

class CursorHue
    {
        [DllImport("gdi32")]
        public static extern uint GetPixel(IntPtr hDC, int XPos, int YPos);

        public static float GetHue(Point p)
        {           
            long color = GetPixel(dc, p.X, p.Y);
            Color cc = Color.FromArgb((int)color);
            return cc.GetHue();
        }
    }

纯蓝色具有240色调值前面的例子(5,5,240)和(10,10,255)均具有240这色调是个好消息,因为它意味着色调是一个措施,是相当宽容为RGB的差异,不同的是还快速计算(即只取的色调值的绝对差值)。 在这一点上,我们也应该出台支配可接受的误差色差另一个参数。 15度的色调宽容会使系统相当强劲。

下面是比较两种颜色,以确定它们是否可接受类似的示例代码

public static bool AreSimilar(Color c1, Color c2, float tolerance = 15f)
{
  return Math.Abs(c1.GetHue() - c2.GetHue() <= tolerance;
}

有关为何工作的更深入的说明,请参阅本维基百科文章的HSV色彩空间。



文章来源: Determine color of a pixel in a winforms application