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

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

17.02.2011, 10:48. Показов 24848. Ответов 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 / 3206 / 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 / 3206 / 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 / 3206 / 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 / 3206 / 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 / 3206 / 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 / 3206 / 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 / 3206 / 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
Ответ Создать тему
Новые блоги и статьи
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
Запрет удаления строк ТЧ документа при определенном условии
Maks 19.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "Аккумуляторы", разработанного в конфигурации КА2. У данного документа есть ТЧ, в которой в зависимости от прав доступа. . .
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru