C# Перерисовать / воссоздать изображение снаружи с помощью кисти

Фу, первое бремя здесь, чтобы объяснить, что я ищу в коротком названии.

По сути, я хочу улучшить свой существующий бот для рисования пикселей. Основная цель: это должно быть быстро.

Я довольно доволен его производительностью, но он может быть лучше. То, что я делаю в двух словах, очень примитивно; подвести итог:

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

Моя главная (производительность) касается сейчас, я не знаю, как решить:

  • В настоящее время я все еще нажимаю 500 раз подряд для рисования черной линии на изображении, например, вместо того, чтобы щелкнуть и перетащить один раз с x1 на x2
  • Использование System.Threading.Sleep(1): Если я этого не сделаю, целевое приложение не будет обрабатываться и не будет рисовать, за исключением нескольких пикселей (тестирование в MS Paint). Разве я не должен работать с асинхронным ожиданием и т.д.? Я так и не узнал, как успешно заменить Sleep();
  • Я слышал, img.GetPixel(x, y) - медленный подход, и его следует заменить на Bitmap.LockBits()? Соглашения, проблемы?
  • Я импортирую RegisterHotKey через user32.dll и переопределяю WndProc для прослушивания глобальной системной горячей клавиши (чтобы начать процесс рисования). Может ли это быть лучше решено с помощью собственных элементов C#? Иногда я замечаю, что при создании решения или при отладке требуется несколько секунд, пока моя программа не запустится изначально.

Наконец, самое главное - код Z:

Рисование:

    void Draw()
    {

        Bitmap imgClipBoard = MakeBlackAndWhite((Bitmap)Clipboard.GetImage());

        Point startPos = Cursor.Position;
        ClickMouse(MouseButtons.Left, startPos.X, startPos.Y, true);
        ClickMouse(MouseButtons.Left, startPos.X, startPos.Y, false);

        for (int y = 0; y < img.Height; y++)
        {
            for (int x = 0; x < img.Width; x++)
            {
                Color c = img.GetPixel(x, y);

                if (c.B == 0)
                {
                    int drawX = startPos.X + x;
                    int drawY = startPos.Y + y;
                    MoveMouse(drawX, drawY);
                    ClickMouse(MouseButtons.Left, drawX, drawY, true);
                    ClickMouse(MouseButtons.Left, drawX, drawY, false);
                    Thread.Sleep(1);
                }
                if (Keyboard.IsKeyDown(Keys.Escape))
                    return;
            }
        }
    }

Что мне также интересно: есть ли более разумные способы перерисовать изображение программно, чем попиксельное? Например, определение путей (линий) в изображении для отслеживания одним штрихом вместо зацикливания сверху вниз и щелчка пикселей, или это уже что-то очень продвинутое?

Редактировать № 1:

Вот демонстрация в формате GIF, касающаяся моей первой проблемы с производительностью: щелчок и перетаскивание бесконечно быстрее, чем нажатие пиксель за пикселем (этот тест все еще использует GetPixel()).

Редактировать № 2

- Снип -

Давайте пока забудем о LockBits ().

Моя главная задача заключается в следующем: как я могу сканировать каждый пиксель "массой", либо по линии, либо в идеале по всей картинке, чтобы я мог сказать своей программе: Хорошо, вот это черно-белое изображение: я не хочу, чтобы вы нажимали сотни Количество раз подряд для каждого черного пикселя, но вместо этого я хочу эту логику: сканирование -> первый черный пиксель -> удерживайте мышь -> продолжайте, пока вы не нажмете белый пиксель -> отпустить. Промыть и повторить.

Пожалуйста, проверьте Редактировать 1, чтобы понять, почему я считаю, что это имеет смысл: намного быстрее печать изображений!

Этот следующий тест слишком медленный для моих целей! Посмотреть анимированный GIF

Редактировать № 3:

Я ожидаю хорошего прямоугольника, но получаю зигзаги

    private void DrawRect()
    {
        int x = Cursor.Position.X;
        int y = Cursor.Position.Y;

        for (int counter = 0; counter < 100; counter++)
        {
            MoveMouse(x, y + counter);
            ClickMouse(MouseButtons.Left, x, y + counter, true);
            Thread.Sleep(1);
            MoveMouse(x + 100, y + counter);
            Thread.Sleep(1);
        }
        Thread.Sleep(15);
        ClickMouse(MouseButtons.Left, 0, 0, false);

    }

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

0 ответов

Другие вопросы по тегам