c # экстрактор цвета, часто возвращающий белый - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть программа, в которой есть небольшая графическая часть, где вы можете посмотреть и сохранить цвет определенных пикселей экрана.

Проблема в том, что когда я извлекаю цвет, иногда я получаю нужный мне цвет ... иногда я просто получаю белый или какой-то другой случайный цвет (обычно белый, но я также использую белый фон для тестирования) ,

Можете ли вы определить причину, почему это будет? Я также полностью открыт для возможных улучшений.

У меня есть окно для картинок под названием Canvas, и я могу нажать «Захват изображения», чтобы сделать снимок экрана следующим образом:

    private void CaptureImage_Click(object sender, EventArgs e)
    {
        this.Visible = false;
        Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
        Graphics graphics = Graphics.FromImage(bitmap as Image);
        graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
        Canvas.SizeMode = PictureBoxSizeMode.AutoSize;
        Canvas.Image = bitmap;
        graphics.Dispose();
        this.Visible = true;
    }

Или я могу загрузить файл изображения, хотя для этого теста я просто делаю захват.

Когда я щелкаю правой кнопкой мыши где-то на изображении, в моем событии mousedown я делаю:

        if (e.Button == MouseButtons.Right)
        {
            pointPoint = e.Location;
            Debug.WriteLine("right mouse: " + e.Location.ToString());
            ContextMenuStrip cm = new ContextMenuStrip();
            cm.Items.Add("Flag this as Point");
            cm.Items.Add("Extract Color");
            Canvas.ContextMenuStrip = cm;
            cm.ItemClicked += new ToolStripItemClickedEventHandler(Cm2Click);
        }

(pointPoint - это объект Point)

Как видите, я проверяю место, где щелкнул, используя окно отладки. В моем контекстном меню я также проверяю это снова, чтобы убедиться, что оно не изменилось перед вызовом. Контекстное меню делает:

   private void Cm2Click(object sender, ToolStripItemClickedEventArgs e)
    {
        //var clickedMenuItem = sender as MenuItem;
        ToolStripItem menuText = e.ClickedItem;
        Debug.WriteLine(menuText);
        if (menuText.ToString() == "Extract Color")
        {
            string input = "Default";
            bool testBox = false;
            do
            {
                if (InputBox.inputBox("ColorName", "You must provide a unique name for this color", ref input) == DialogResult.OK)
                {
                    if (!String.IsNullOrWhiteSpace(input) && input != "Default")
                    {
                        Debug.WriteLine("location changed to: " + pointPoint);
                        colorExtractor = Functions.GetColorAt(pointPoint);
                        ColorData clr = new ColorData(input, colorExtractor);
                        string expression;
                        expression = $"Name = '{clr.Name}'";
                        DataRow[] foundRows;
                        DataTable dt = _allEventData.Tables["ColorData"];
                        foundRows = dt.Select(expression);
                        if (foundRows.Length > 0) {
                            testBox = false;
                            Debug.WriteLine("Color Found");
                        }
                        else {
                            dt.Rows.Add(clr.Name, clr.R, clr.G, clr.B);
                            dt.AcceptChanges();
                            testBox = true;
                        }
                    }
                } else
                {
                    return;
                }
            } while (testBox == false);
        }
    }

и ColorData - это просто класс, который я определил для хранения данных:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace EventClicker
{
    public class ColorData : EventArgs

    {
        public string Name { get; set; }
        public int R { get; set; }
        public int G { get; set; }
        public int B { get; set; }
        public bool Found { get; set; }

        public ColorData(String name, Color color)
        {
            this.Name = name;
            this.R = color.R;
            this.G = color.G;
            this.B = color.B;
        }

        public ColorData(String name, String r, String g, String b)
        {
            this.Name = name;
            this.R = Int32.Parse(r);
            this.G = Int32.Parse(g);
            this.B = Int32.Parse(b);
        }
    }
}

Последнее, но не менее важное, метод, который я вызываю (Functions.GetColorAt), определен здесь (и я определенно украл это у кого-то в сети). Редактировать: Это где-то здесь, Как прочитать Цвет экрана Pixel

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace EventClicker
{
    public static class Functions
    {

        private static Bitmap screenPixel = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);

        public static Color GetColorAt(Point location)
        {
            using (Graphics gdest = Graphics.FromImage(screenPixel))
            {
                using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero))
                {
                    IntPtr hSrcDC = gsrc.GetHdc();
                    IntPtr hDC = gdest.GetHdc();
                    int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, location.X, location.Y, (int)CopyPixelOperation.SourceCopy);
                    gdest.ReleaseHdc();
                    gsrc.ReleaseHdc();
                }
            }

            return screenPixel.GetPixel(0, 0);
        }
    }
}
...