Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.51/125: Рейтинг темы: голосов - 125, средняя оценка - 4.51
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2

GetPixel() работает нереально медленно на Windows 7

17.02.2011, 10:48. Показов 24557. Ответов 67
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Написал программу (бот для онлайн игры), вся его работа заключается в получении цвета пикселя в нужных координатах и совершения тех или иных деййствий в зависимости от полученного цвета. Стояла ХР, все работало прекрасно, но вот решил попробовать семерку и столкнулся с необъяснимой вещью - бот нереально тупит. Например в самом начале он ищет окно игры в браузере (всмысле его координаты) а потом в этом окне находит нужную кнопку по ее цвету:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void find_button(POINT& but,HDC dc){
    HWND desktop=GetDesktopWindow();
    RECT rect;
    GetWindowRect(desktop,&rect);//получаем разрешение экрана
    const COLORREF buttonc=(10142681&0x00FCFCFC);//цвет кнопки, слегка загрубленный, на всякий случай
    but.x=rect.right-30;
    but.y=rect.bottom/2-100;
    while((GetPixel(dc,but.x,but.y)&0x00FCFCFC)==0x00FCFCFC)
        but.x--;//находим окно игры
    but.x-=112;
    bool f=false;
    while(!f){//находим кнопку
        clf=((GetPixel(dc,but.x,but.y))&0x00FCFCFC);
        for(int i=1;i<=10;i++){
            if(clf!=buttonc)
                break;
            else if(i==10)//если 10 пикселей подряд одного цвета, то похоже это кнопка
                f=true;
 
        }
        but.y++;
    }
    SetCursorPos(but.x,but.y+20);
    but.y+=23;
}
слегка быдлокод, т.к. писал "лишь бы работало" )) Но не об этом речь. В общем на ХР все эти действия происходят мнгновенно (для человеческого глаза), а на семерке на это уходит 5-6 секунд. По-моему нереальное время. Пробовал в диспетчере задач менять приоритет процесса - непомогло. Далее вся работа бота сводится к считываню цветов в определенных местах и реагированию на произошедшие события (цвет изменился - значит что-то случилось)), но естественно с такими темпами ни чего не работает. Вот сижу и думаю - почему на Win7 так медленно работают обычные API ?

Добавлено через 9 минут
поечему я решил что тормозит именно GetPixel()? - потому, что больше тут тормозить не чему)
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.02.2011, 10:48
Ответы с готовыми решениями:

Несколько GetPixel с экрана - код работает слишком медленно
Собственно в данный момент я использую этот код. int GetPixel(int X, int Y) { Bitmap bmp = new Bitmap(1, 1,...

Ноутбук начал нереально медленно работать (Acer aspire 5750g)
Поставил на ноутбук windows 10.Ставил через USB-флешку, активировал через kms.Все вроде было отлично.Поставил драйвера Nvidia,поиграл в...

Медленно работает Windows 7
Почему при включении плеера,текстового редактора и инета винда начинает тормозить. Windows 7 AMD 6000+ 2x 3ГГц DDR2 - 2x2048MB GeForce...

67
5 / 5 / 1
Регистрация: 16.01.2011
Сообщений: 28
17.02.2011, 10:50
попробуй CDC::GetPixel или CImage::GetPixel
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
17.02.2011, 20:47  [ТС]
Anton_Grey, на сколько я понял это MFC, я пишу пока без этого.

Добавлено через 48 минут
Да, еще забыл упомянуть, все это дело происходит в созднном потоке, в основном потоке у меня обработка сообщений главного окна.

Добавлено через 8 часов 59 минут
Попробовал такой код:
C++
1
2
for(int i=0;i<1000;i++)
   GetPixel(bla,bla,bla);
перед этими двумя строчками и после них поставил breakpoint, чтоб посмотреть сколько этот код будет выполняться. На это ушло где-то около минуты. Это выходит за все допустимые рамки, в чем может быть дело?
0
5 / 5 / 1
Регистрация: 16.01.2011
Сообщений: 28
17.02.2011, 22:12
Попробовал у себя, такая же проблема. Даже не знаю с чем связано.
Попробую на Wasm'e спросить.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
18.02.2011, 09:24  [ТС]
Цитата Сообщение от Anton_Grey Посмотреть сообщение
Попробую на Wasm'e спросить.
ОК)
При чем вот что еще интересно, я бота выкинул в инет, люди качают и пишут отзывы, так вот у некоторых на семерке все отлично работает Я вот уже думаю, может в самой ОС нужно какие-то настройки сделать, не может быть, чтоб к системным бибилиотекам был такой медленный доступ и ф-ции из этих бибилиотек так сильно тупили. Разаработчики тогда бы просто прокляли семерку и ни кто под нее бы не писал)
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
20.02.2011, 16:18
Я не специалист по графике. И практически не имею опыта работы под Windows. Но из общих соображений могу высказать причину тормозов. Тем более, что с похожей проблемой мы сталкивались с #pragma'ой, когда он использовал библиотеку SDL.

Любая работа с графикой - это работа с устройством (видеокартой) посредством драйвера. Видеокарта и драйвер как правило настроены таким образом, что самый эффективный способ обращения - страничный. Т.е. одним махом записывается целый кадр (экран) или одним махом считывается значение кадра. При таком раскладе чтобы отобразить точку делается чтение всего экрана, замена одной точки и потом запись всего экрана. Поэтому чтобы по точкам прорисовать экран при разрешении 640 на 480 требуется соответствующее количество последовательных чтений-записей всего экрана. Поэтому правильная работа заключается в том, что сначала в памяти формируется образ всей картинки, а потом оно одним махом отправляется на устройство.

Обратная работа (чтение точки с экрана), скорее всего, построена по тому же принципу. Читается весь экран, а потом выдаётся информация об одной точке. Тот факт, что на разных системах GetPixel работает с разной скоростью скорее всего говорит о следующем. При первом вызове GetPixel прочитается весь экран и выдастся значение конкретной точки. При последующем вызове делается проверка, изменилось ли состояние экрана с предыдущего вызова. Если не изменилось, то считываем значение точки в образе памяти, оставшемся от предыдущего вызова GetPixel (т.е. без обращения к устройству, которое очень медленное). Если изменилось, то ничего не остаётся делать, как заново прочитать весь экран. И в твоём случае проблема скорее всего растёт из того, что при последующем вызове считается, что состояние экрана изменилось. Это может зависет от конкретной реализации конкретного драйвера. В принципе, это может зависеть и от того, распахнуто окно программы во весь экран или нет, имеется ли какая-нибудь фигня в tray и прочей всякой лажи. Понятно, что в случае оконного приложения данные считываются не с экрана, а с виртуального устройства (оно Device Context или что-то в этом духе вроде бы называется), а потому возникает ещё куча программных прослоек, в которых могут возникать эти самые непонятки.

На мой взгляд проблему надо решать тем, что вместо кучи вызовов GetPixel нужно сделать один вызов, который читает весь образ экрана (а точнее, весь образ Device Context'а) в память, а дальше уже ковыряться в этой памяти. Независимо ни от чего такой вариант был бы куда более правильный, чем то, что у тебя написано, а потому даже если это не поможет, лучше работать именно так

Добавлено через 6 минут
Кстати, цикл в строках 14-20 - это какой-то мёртвый код, который 10 раз сравнивает две переменные, которые внутри цикла не меняются. По логике "clf=..." и "but.y++" должны находиться внутри цикла, а не снаружи. Ну вобщем ладно, это уже твоя кухня...
1
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
20.02.2011, 16:40  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
Кстати, цикл в строках 14-20 - это какой-то мёртвый код, который 10 раз сравнивает две переменные, которые внутри цикла не меняются. По логике "clf=..." и "but.y++" должны находиться внутри цикла, а не снаружи. Ну вобщем ладно, это уже твоя кухня...
Точно, просто я 500 раз код переписывал, в процессе переписывания мог напортачить)

Добавлено через 4 минуты
Evg, скажи еще, разумно ли так делать:
C++
1
while(GetPixel(dc,but.x,but.y)==somecolor);//просто ожидание смены цвета
где-то читал, что подобные циклы очень грузят ЦП.
0
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 17:23
Kastaneda, если не против могу ответить я)
Это действительно очень сильно загрузит ЦП. Обычно я поступаю так, если необходимо оперативно в реальном времени снимать какие то данне. создаю для этих нужд отдельный поток, в потоковой функции у меня следуйший код:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
DWORD WINAPI thread(void *parg)
{
    HWND hwnd = (HWND)parg;
    
    while (TRUE) {
        COLORREF color;
        HDC dc = GetDC(hwnd);
        if ((color = GetPixel(dc, 0, 0)) == somecolor) {
            // ...
            // my_func_color_changed(dc, ......);
        }
        
        ReleaseDC(hwnd, dc);
        Sleep(500); // заморозим поток, на нужное время. иначе ЦП сойдет ссума.
    }
    
    return 0;
}
П.С. как пример, решения задачи.

Добавлено через 2 минуты
Так же можно приципить Event. То есть при необходимости дать знать потоку, что пора закончить работу.
1
160 / 159 / 13
Регистрация: 14.01.2010
Сообщений: 1,497
20.02.2011, 17:35
Когда то делал GetPixel на vc++ на xp очень медленно пполучалось, перевел на делфи и скорость резко возраста. Это просто наблюдение мое частное.
На api не делал ни чего, но думаю можно создать свой dc CreateCompatibleDC и bitblt скопировать в него экран, а потом GetPixel.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
20.02.2011, 17:37  [ТС]
Цитата Сообщение от bobrovskii Посмотреть сообщение
если необходимо оперативно в реальном времени снимать какие то данне
Как раз есть такая необходимость, ну думаю если вставить Sleep(10); , то процессору это даст передышку (а для человеческого глаза будет незаметно). Еще пару вопросов:
По WInAPI ни чего не читал (вернее когда-то начинал читать книгу, потом забросил), осваиваю методом тыка, поэтому не понимаю, зачему нужно:
C++
1
ReleaseDC(hwnd, dc);
и еще
Так же можно приципить Event. То есть при необходимости дать знать потоку, что пора закончить работу.
Что такое Event ?
0
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 17:43
ReleaseDC если быть точным, то:
The ReleaseDC function releases a device context (DC), freeing it for use by other applications. The effect of the ReleaseDC function depends on the type of device context. It frees only common and window device contexts. It has no effect on class or private device contexts.
то есть освободить контекст, так то это обязательная процедура.
Event, CreateEvent сигналы.
Подробнее тоже можно узнать в MSDN, если есть время чуть поэже скину ЛС как пользоваться.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
20.02.2011, 17:49  [ТС]
А чем чревато "забыть" включить в код ReleaseDC(). У меня в коде этого ни где не делается)
Вот твой код
C++
1
2
3
4
5
6
7
8
9
10
11
 while (TRUE) {
                COLORREF color;
                HDC dc = GetDC(hwnd);
                if ((color = GetPixel(dc, 0, 0)) == somecolor) {
                        // ...
                        // my_func_color_changed(dc, ......);
                }
                
                ReleaseDC(hwnd, dc);
                Sleep(500); // заморозим поток, на нужное время. иначе ЦП сойдет ссума.
        }
Если ReleaseDC(hwnd, dc); вынести за цикл, чтоб каждый раз не получать HDC заново HDC dc = GetDC(hwnd);, чем это опасно?
0
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 17:58
Kastaneda, чем это черевато я точно тебе сказать не могу. вот что пишет тот же MSDN
в описании GetDC
After painting with a common device context, the ReleaseDC function must be called to release the device context. Class and private device contexts do not have to be released. The number of device contexts is limited only by available memory.
Это почти то же что, если бы ты вызвал malloc и не освободил память free, когда она тебе уже не нужна.
Короче дурной тон так поступать, возможно в этом и причина тормозов на семерке.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
20.02.2011, 18:02  [ТС]
Да, но в пределах цикла HDC dc еще нужен. Думаю можно освободить его после цикла. Ладно, сейчас попробую сделать так, потом отпишусь)
0
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 18:05
Kastaneda, за приделами вызывай GetDC, думаю система не будет против)
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
20.02.2011, 18:08
Цитата Сообщение от Kastaneda Посмотреть сообщение
Если ReleaseDC(hwnd, dc); вынести за цикл, чтоб каждый раз не получать HDC заново HDC dc = GetDC(hwnd);, чем это опасно?
Цикл while у тебя, грубо говоря, бесконечный. Чревато это тем, что ты никогда не освободишь. Пример из поста 12 как бы содержит 2 цикла: первый цикл while - он грузит процессор. Второй цикл - это sleep и он процессор не грузит. Так вот вся работа с контекстом у тебя находится вне второго цикла, но внутри первого. Рабочая часть кода (тело внутри первого цикла, кроме sleep'а) занимает гораздо меньшее время, чем второй цикл (sleep). Поэтому захват и освобождение контекста должны быть именно внутри этого короткого интервала времени, чтобы на период длительного второго цикла (а 500 миллисекунд с точки зрения процессора - это целая вечность) контекст находился в свободном состоянии
1
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 18:08
влзможно после обноления окна сторонего процесса, HDC уже будет не актуален.
так что для строховки повторный вызов и освобождение.
понимаю, хочется уменьшить код, но для коректной работы это не выход.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
20.02.2011, 18:14
Цитата Сообщение от bobrovskii Посмотреть сообщение
понимаю, хочется уменьшить код, но для коректной работы это не выход.
Если я правильно понимаю постановку вопроса, то Kastaneda хочет не укоротить код, а ускорить его работу. Но при этом у него нет чёткого понимания, что и насколько тормозит работу его программы, а потому начинаются методы тыка. Одна из вещей, кажущихся очевидной - это вынос из цикла того, что как бы не нужно делать в цикле. Потому он и спрашивает, чем это чревато
0
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 18:20
Evg, Respekt)
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
20.02.2011, 18:22  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
Но при этом у него нет чёткого понимания, что и насколько тормозит работу его программы
Уверен на 100% тормозит именно GetPixel(). Переписал код:
C++
1
2
3
4
5
6
7
8
9
10
11
while(true){//поиск начала окна игры
                HDC hdc=GetDC(0);
                if((GetPixel(hdc,but.x,but.y)&0x00FCFCFC)==0x00FCFCFC)
                        but.x--;
                else {
                        ReleaseDC(desktop, dc);
                        break;
                }
                ReleaseDC(desktop, dc);
                Sleep(10);
}
Быстрей не стало. На этот цикл потребовалось где 6-7 сек. (ну так, на глаз) При чем происходит где-то 150-200 итераций (это я тоже на глаз определил, исходя из моего разрешения экрана и местоположения окна игры). Ну не может быть такого , но факты говорят об обратном...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
20.02.2011, 18:22
Помогаю со студенческими работами здесь

Windows XP медленно работает
Помогите пожалуйста, ситуация следующая...Винда начала глючить, комп не хотел выключаться и я переустановил ее с форматированием. Теперь...

USB работает медленно (Windows 7)
Операционная система: Windows 7 Ultimate x64 (original, RTL, не сборка). Motherboard: ASUS P5QL-CM Драйвера после установки Windows...

Windows XP работает слишком медленно
Добрый день. Есть дома второй компьютер, на нём батя вся в шашки играет) Я не чайник, с 15 лет ставил ХP сам и чем только не...

Медленно работает Аксесс 97 под Windows 7
База работает под Акс97. Кратко алгоритм таков. Открывается связанная таблица как рекордсет. Организуется цикл по записям в ВБА. ...

После переустановки Windows 7 медленно работает система
Здравствуйте! Так случилось что мне доводится часто переустанавливать Windows на ноутбуках разных производителей. И я заметил одну не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru