С Новым годом! Форум программистов, компьютерный форум, киберфорум
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. Показов 24582. Ответов 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
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 18:32
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Kastaneda Посмотреть сообщение
На этот цикл потребовалось где 6-7 сек
действительно очень долго, в чем причина даже ума не приложу.
вопрос, по какой причине таким оброзом ищиш окно игры?
не проще ли FindWinowEx.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
20.02.2011, 19:26  [ТС]
Цитата Сообщение от bobrovskii Посмотреть сообщение
не проще ли FindWinowEx.
Браузерная игра написанная на flash. Мне нужно определить край окна, а от него уже дальше ищу кнопки в окне, тоже по цвету пикслелей. Т.к. у них нет своих handle'ов.

Добавлено через 56 секунд
Но меня уже не столько мой бот интересует, сколько время, затраченное на GetPixel() в Windows7.
0
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 20:09
Kastaneda, попробуй с CreateCompatibleDC, CreateCompatibleBitmap как предложил turboq, тоже вариант. может что получится.
П.С. ЛС Event`s.
1
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
20.02.2011, 20:55  [ТС]

Не по теме:

bobrovskii, с сигналами все понятно, удобная вещь)



Добавлено через 39 минут
Может глупый вопрос, но все же: может GetPixel() тормозить из-за некорректного драйвера для видеокарты?
0
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 21:01
Kastaneda, в таком случае большинство приложений используйших эту функцию имели бы такойже глюк. тут что то в твоем коде. если время будет скину в ЛС вариант с CreateCompatibleBitmap может поможет.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
20.02.2011, 21:06  [ТС]
Цитата Сообщение от bobrovskii Посмотреть сообщение
в таком случае большинство приложений используйших эту функцию имели бы такойже глюк
Ну да, логично, не подумал.

Цитата Сообщение от bobrovskii Посмотреть сообщение
если время будет скину в ЛС вариант с CreateCompatibleBitmap может поможет
Не уверен, что это то, что мне нужно. Мне в дальнейшем нужно в life режиме работать с пикселями (мнгновенно реагировать на изменение цвета определенного пикселя), а с CreateCompatibleBitmap, на сколько я понял, такого не получится. Хотя я не так много про CreateCompatibleBitmap почитал.
0
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
20.02.2011, 21:13
Kastaneda, Скорость практически таже, кода больше)
в любом случае ничего не теряеш.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
20.02.2011, 21:16  [ТС]
Цитата Сообщение от bobrovskii Посмотреть сообщение
Kastaneda, Скорость практически таже, кода больше)
Значит я не правильно понял цель применения CreateCompatibleBitmap, тогда можно попробовать)
0
4 / 4 / 5
Регистрация: 16.04.2010
Сообщений: 10
22.02.2011, 17:56
Используйте GetDIBits.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
24.02.2011, 12:07  [ТС]
В общем написал свою ф-цию MyGetPixel(), выкладываю код, на случай если когда-нибудь кто-нибудь столкнется с похожей проблемой и воспользуется поиском по форуму:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
COLORREF MyGetPixel(HWND hGame,int x,int y){//на входе хэндл нужного окна и координаты x,y
    COLORREF pixel;
    BITMAPINFO BMI={0};
    HDC hGDC=GetDC(hGame);
    int Bitp=GetDeviceCaps(hGDC, BITSPIXEL);
    HDC hTmpDC=CreateCompatibleDC(hGDC);
    HBITMAP hTmpBmp=CreateCompatibleBitmap(hGDC,1,1);
    SelectObject(hTmpDC,hTmpBmp);
    BitBlt(hTmpDC,0,0,1,1,hGDC,x,y,SRCCOPY);
    BMI.bmiHeader.biSize = sizeof(BMI.bmiHeader);
        BMI.bmiHeader.biWidth = 1;
        BMI.bmiHeader.biHeight = 1;
        BMI.bmiHeader.biPlanes = 1;
        BMI.bmiHeader.biBitCount = Bitp;
        BMI.bmiHeader.biCompression = BI_RGB;
    BMI.bmiHeader.biSizeImage=Bitp/8;
    BMI.bmiHeader.biClrUsed = 0;
    BMI.bmiHeader.biClrImportant = 0;
    int TMP=GetDIBits(hTmpDC,hTmpBmp,0,1,&pixel,&BMI, DIB_RGB_COLORS);
    pixel&=0xFFFFFF;
    ReleaseDC(hGame,hGDC);
    return pixel;
}
Все работает очень быстро))

Не по теме:

Сегодня установил на семерку SP1, там стандартный GetPixel() прекрасно работает, вот же блиннн...

2
59 / 59 / 2
Регистрация: 22.01.2011
Сообщений: 187
24.02.2011, 12:16
Kastaneda, код хороший), ReleaseDC присутствует а DeleteDC забыл.
1
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
24.02.2011, 13:41  [ТС]
Ну я так подумал, что поскольку HDC hTmpDC локальная переменная, то нет смысла вызывать DeleteDC() для нее, все равно при выходе из MyGetPixel() она уничтожется. Или все таки нужно?

Добавлено через 7 минут
Да, наверное все таки нужно, хендл удаляется, а устройство в памяти все равно наверно висит.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
24.02.2011, 16:02
Цитата Сообщение от Kastaneda Посмотреть сообщение
хендл удаляется, а устройство в памяти все равно наверно висит
Удаляется не хэндл, а локальная переменная, содержащая значение хэндла. Точно так же, если ты вызовешь malloc и результат запишешь в локальную переменную, то после завершения процедуры память не освободится
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
24.02.2011, 17:39  [ТС]

Не по теме:

Цитата Сообщение от Evg Посмотреть сообщение
Удаляется не хэндл, а локальная переменная, содержащая значение хэндла.
Ну да, я это и подразумевал)



Добавлено через 43 минуты
Цитата Сообщение от Kastaneda Посмотреть сообщение
Сегодня установил на семерку SP1, там стандартный GetPixel() прекрасно работает, вот же блиннн...
Это я погарячился) В общем ситуация такая - если получать пиксель используя хэдл рабочего стола (или контекст ус-ва, связанный с раб. столом в случае с GetPixel()), то тупит и моя ф-ция и стандартная, если использовать например хэндл браузера, то обе ф-ции работают быстро. Вот такая вот магия...
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
24.02.2011, 17:46
Цитата Сообщение от Kastaneda Посмотреть сообщение
Это я погарячился) В общем ситуация такая - если получать пиксель используя хэдл рабочего стола (или контекст ус-ва, связанный с раб. столом в случае с GetPixel()), то тупит и моя ф-ция и стандартная, если использовать например хэндл браузера, то обе ф-ции работают быстро. Вот такая вот магия...
По-моему это +1 к догадке из поста #6. Попробуй всё-таки работать и читать сразу весь экран в промежуточную память за одно обращение к устройству, а дальнейшую работу с точками уже выполнять над этой памятью (без обращения к устройству на каждую точку)
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
24.02.2011, 18:35  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
По-моему это +1 к догадке из поста #6.
Да, по-моему так и есть.
Цитата Сообщение от Evg Посмотреть сообщение
читать сразу весь экран в промежуточную память за одно обращение к устройству, а дальнейшую работу с точками уже выполнять над этой памятью (без обращения к устройству на каждую точку)
Для меня не вариант, на сколько я понял в памяти сохранится "мнгновенный снимок" экрана, т.е. через секунду снимок в памяти не будет соответствовать реальному состоянию экрана, а мне нужно реагировать на события в реальном времени. Поэтому я каждый раз создаю битмап в памяти размером 1 пиксель, и копирую в него пиксель, находящийся в нужных мне координатах на экране.

Evg, а почему ты отсюда:

Цитата Сообщение от Kastaneda Посмотреть сообщение
В общем ситуация такая - если получать пиксель используя хэдл рабочего стола (или контекст ус-ва, связанный с раб. столом в случае с GetPixel()), то тупит и моя ф-ция и стандартная, если использовать например хэндл браузера, то обе ф-ции работают быстро.
сделал такие выводы:

Цитата Сообщение от Evg Посмотреть сообщение
По-моему это +1 к догадке из поста #6.
?
Я вот связи не вижу. Браузер развернут на весь экран (т.е. он не на много меньше всего рабочего стола), но при этом работать с браузером в разы (наверное в сотни, а то и в тысячи раз) быстрее, чем со столом. Вообще не понимаю почему так, тем более я только с одной точкой в своей ф-ции работаю.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
24.02.2011, 20:09
Цитата Сообщение от Kastaneda Посмотреть сообщение
т.е. через секунду снимок в памяти не будет соответствовать реальному состоянию экрана
За эту секунду ты можешь несколько тысяч раз обработать снимок всего экрана. Причём самая тяжёлая по времени операция - это перегнать снимок экрана в буффер. Когда ты достаёшь одну точку, то этот процесс по времени несильно отличается.

Если на пальцах, то ситуация примерно такая (цифры взяты от балды, чисто чтобы показать соотношение). Миллион тактов уходит на то, чтобы сделать снимок экрана, тысячу тактов уходит на то, чтобы снимок обработать. Практически тот же миллион тактов уходит на то, чтобы сделать снимок одной точки. И один такт на то, чтобы точку обработать. Т.е. при непосредственном обращении к устройству нет разницы, делать снимок всего экрана или снимок одной точки. При снимке одной точки всё равно делается снимок всего экрана, только ты этого не видишь.

Когда ты работаешь с одним окном, то при повторном вызове снимок всего жкрана уже не делается, а используется закэшированный. А потому на обработку тысячи раз одной точки у тебя уходит миллион тактов плюс тысячу раз по одной точке (т.е. столько же, как если бы ты делал снимок всего экрана и обрабатывал тысячу точек). Когда работаешь с целым рабочим столом, то кэширование по каким-то причинам не делается и на обработку тысячу раз одной точки у тебя получается тысяча снимков экрана (от чего так всё и тормозит).

Чем принципиально лучше вариант с получением снимка всего экрана. По скорости работы он принципиально не должен отличаться от варианта, когда за раз достаётся одна точка. Только при этом управление процессом находится в гораздо более полной мере в твоих руках, чем руках системы. Другими словами, ты перестаёшь зависеть от капризов работы GetPixel (которую, кстати говоря, не очень-то и рекомендуют к использованию): тут она работает так, там работает сяк, с таким хэндлом работает быстро, с таким медленно. Вместо кода, живучесть которого выясняется методом тыка и массового тестирования, ты получаешь код, которые независимо ни от чего и ни от кого работает везде одинаково быстро.

Естественно, всё это в предположении, что догадка верна

Цитата Сообщение от Kastaneda Посмотреть сообщение
вот связи не вижу
Как я уже говорил - кэширование. За окно (хоть оно во весь экран, хоть не во весь) отвечает только один процесс. За рабочий стол - туева хуча процессов, включая системные и те, что отображены в tray. Возможно, что там для подтстраховки нет кэширования, возможно - что действительно что-то там меняется.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
24.02.2011, 20:40  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
За эту секунду ты можешь несколько тысяч раз обработать снимок всего экрана.
Либо я не понимаю, что ты хочешь до меня донести, либо ты не понимаешь, что мне нужно) Мне нужно каждую долю секунды получать новый снимок экрана, это важно.

Когда ты работаешь с одним окном, то при повторном вызове снимок всего жкрана уже не делается, а используется закэшированный.
Но ведь в таком случае, я бы не смог отследить изминения цвета в определенной точке, но у меня получается), значит снимок экрана делается каждый раз. Моя ф-ция MyGetPixel() вызывается в непрерывном цикле в отдельном потоке и при изменении цвета определенного пикселя шлет сигнал в параллельный поток. Если бы при этом использовался кэшированный снимок экрана, то я бы не смог реализовать то, что я хочу.


Цитата Сообщение от Evg Посмотреть сообщение
Как я уже говорил - кэширование. За окно (хоть оно во весь экран, хоть не во весь) отвечает только один процесс. За рабочий стол - туева хуча процессов, включая системные и те, что отображены в tray. Возможно, что там для подтстраховки нет кэширования, возможно - что действительно что-то там меняется.
Это похоже на правду, но тогда (если все таки снимок действительно хэшируется) я не понимаю, как можно отловить изменение цвета в захешированном снимке?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
24.02.2011, 21:25
Впервые за время пользования фатально накрылся Chrome. И, естественно, в тот момент, когда было написано много текста

Вкратце вот что написал.

Кэшируется изображение, естественным образом, только тогда, когда оно не меняется. Система "знает" о том, когда картинка поменялась, а потому в нужный момент кэш инвалидирует, делает новый снимок экрана и кэширует его.

Моя идея сводилась к тому, что с небольшими интервалами (например, 50 или 100 раз в секунду), ты делаешь снимок экрана, а дальше весь анализ делаешь на снимке. В процессе анализа (я смотрю на код из первого поста) у тебя много раз вызывается GetPixel, а в новом варианте вместо этого у тебя будет просто чтение значения из буффера памяти
1
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
25.02.2011, 04:13  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
Кэшируется изображение, естественным образом, только тогда, когда оно не меняется. Система "знает" о том, когда картинка поменялась, а потому в нужный момент кэш инвалидирует, делает новый снимок экрана и кэширует его.
А, ну теперь дошло)))
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
25.02.2011, 04:13
Помогаю со студенческими работами здесь

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 на ноутбуках разных производителей. И я заметил одну не...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru