PDA

Просмотр полной версии : [Помогите!] Pixels[x,y] слишком медленный


Илья333777
26.08.2012, 13:25
Мне надо подсчитать количество пикселей определённого цвета на экране (например цвета 16777215 - чисто белый). Я у каждого пикселя в области проверяю функцией Pixels[x,y] цвет, но это слишком долго. Например в программе clickermann есть тоже такая функция и она подсчитывает пиксели хоть на всём экране за 1/3 секунды (может и быстрее). Мне вот и нужна такая скорость. А у меня подсчёт происходит оооочень долго (несколько секунд), и это в маленькой области!
Вот мой код для подсчёта по клику кнопки:

procedure TForm1.Button1Click(Sender: TObject);
begin
dtc:=TCanvas.Create;
dtc.Handle:=GetDC(Hwnd_Desktop);
xn:=1000; /х начальный
xk:=1050; /х конечный
yn:=300; /у начальный
yk:=350; /у конечный
x:=xn; /сначала идём в первый пиксель, который слева по х
y:=yn; /сначала идём в первый пиксель, который сверху по у
count:=0; /счётчик равен 0
while y<=yk do /пока у меньше у конечного
begin
temp:= dtc.Pixels[x,y]; /считываем цвет и заводим в переменную
if temp=16777215 then /если он белый, то
count:=count+1; /прибавляем к счётчику 1
if x>xk then begin /если х подошёл к конечному, то
y:=y+1; /спускаемся вниз на 1 пиксель по у
x:=xn; /и переходим в начало по х
end;
x:=x+1; /сдвигаемся по х на следующий пиксель

end;
Label1.Caption:=inttostr (count); /выводим в лейбл кол-во найденных пикселей заданного цвета
end;

Вот приведите мне пожалуйста другую функцию, желательно по-проще и с комментариями, как у меня. Ну и чтобы быстрей работало.
Жду ваших ответов и помощи :sceptic: может я что-то не так сделал.

J-Fobos
26.08.2012, 14:23
Закиньте скрин экрана в TStream и проверяйте цвета в нем, сравнивая байты.

Илья333777
26.08.2012, 18:42
J-Fobos, а по-проще никак нельзя? Или хотя бы приведите примерный код как это сделать, а то я в потоках ещё не разбираюсь =((.
Кстати видел код на эту тему:

function GetColorXY(Graphic: TGraphic; Color: TColor; var X, Y: Integer): Boolean;
var
Bmp: TBitmap;
i, j: Integer;
Pixel, CmpColor: Cardinal;
Scan: Pointer;
R, G, B: Byte;
begin
Result:=false;
CmpColor:=ColorToRGB(Color);
Bmp:=TBitmap.Create;
try
Bmp.Assign(Graphic);
Bmp.PixelFormat:=pf24bit;
for i:=0 to Bmp.Height - 1 do begin
Scan:=Bmp.ScanLine[i];
for j:=0 to Bmp.Width - 1 do begin
Pixel:=PCardinal(Integer(Scan) + j*3)^;
R:=GetBValue(Pixel);
G:=GetGValue(Pixel);
B:=GetRValue(Pixel);
if RGB(R, G, B) = CmpColor then begin
Result:=true;
X:=j + 1;
Y:=i + 1;
Exit;
end;
end;
end;
finally
Bmp.Free;
end;
end;

Только не очень понимаю, он быстрей работает, или медленней (строк то больше) и вообще это может ли как-нибудь мне помочь.

J-Fobos
26.08.2012, 19:38
Илья333777, зачем по-проще если нужна скорость?

Илья333777
26.08.2012, 19:43
Ну я не сильно в таких функциях разбираюсь, а что думаете по второму коду??

J-Fobos
26.08.2012, 21:00
По принципу работы то же что и первый. Только вытягивает значение цвета не из канваса, а из bmp.

VeTaL_UA
27.08.2012, 00:16
Наиболее быстрый вариант это гразвнуть снимок экрана в стрим и побайтово разобрать. Да, это многокода :)

Илья333777
27.08.2012, 10:11
Хм, кстати, по-моему в clickermann там и делается.

Softwarer
27.08.2012, 11:05
Все, что ты нашел в нете - почти бред.

по-моему, достаточно просто отсканить сверху-вниз слева-направо. Я так понял, если как кликерман, то это для ДО => найденных предметов будет [0; 8] є N. (провернуть это твоим кодом можно за 1сек) - как ускорить, сказали, но найденного кода будет достаточно для нормального продвижения.

Илья333777
29.08.2012, 11:14
Softwarer, в том то и дело, что мой код сканит даже 2500 пикселей за секунд 10 где-то.

Добавлено через 2 минуты
Ну всё-таки может мне кто-нибудь примерный код даст, чтобы в стрим экран загонять и считывать?