Mozete mi prosim poradit ako mam porovnat dve bitmapy? aby bol vysledok true alebo false..
Skusal som if Bitmap1 <> Bitmap2 then ..... zrejme je to blbost ja viem necudo ze to nefunguje .. co by som v tom asi mal porovnavat? pls....
Fórum › Delphi
Ako porovnam 2 BItmapy?
To KIIV :
s pracou s binarnymi datami moc nemam skusenosti.. mozes mi napisat akoby som to mal urobit? popripade aj nejaku ukazku ..
To KIIV :
na nete som nasiel len toto.... problem je ze tomu moc nerozumiem.. no programovaniu sa venujem vaznejsie len asi tak 4 - 5 mesiacov.. cize mam iste medzery ... nejaky jednoduchsi sposob by nebol?
procedure CalcBitmapCRC32(Bitmap: TBitmap; lCRC: PlArrayCRC);
var i, j, k, l, lSquareHeight, lSquareWidth: Cardinal;
Lines: Array[0..lSquare-1]of Pointer;
begin
if (Bitmap.Height<=0) or (Bitmap.Width<=0) then Exit;
if ((Bitmap.Height mod lSquare)>0) or ((Bitmap.Width mod lSquare)>0) then
Exit;
lSquareHeight:=Bitmap.Height div lSquare;
lSquareWidth:=Bitmap.Width div lSquare;
for i:=0 to (lSquareHeight-1) do // 1 průběh pro každý řádek čtverců.
begin
for j:=0 to (lSquare-1) do
Lines[j]:=Bitmap.ScanLine[i*lSquare+j];
for j:=0 to (lSquareWidth-1) do // 1 průběh pro každý čtverec v 1 řádku.
begin
lCRC^[j,i]:=$FFFFFFFF;
for k:=0 to (lSquare-1) do // 1 průběh pro každý blok dat = 1 řádek
// v 1 čtverci.
for l:=0 to (lSquare-1) do // 1 průběh pro každý pixel v 1 řádku
// 1 čtverce.
lCRC^[j,i]:=UpdateCrc32(Byte(Pointer(
Cardinal(Lines[k])+j*lSquare+l)^),lCRC^[j,i]);
lCRC^[j,i]:=not lCRC^[j,i];
end;
end;
end;
A jestli to máš na ty přenášené screenshoty, tak můžeš ušetřit nějaký čas tím, že nebudeš porovnávat všechny řádky, ale např. jenom každý 8. a stejně tak nemusíš porovnávat všechny barvy, ale můžeš to testovat co 4. bajt.
Nebo můžeš dělat z řádků něco jako kontrolní součet, možná by to bylo rychlejší.
Pokud ovšem chceš naprosto přesný výsledek, tak musíš porovnat všechny bajty.
A jestli to máš na ty přenášené screenshoty, tak můžeš ušetřit nějaký čas tím, že nebudeš porovnávat všechny řádky, ale např. jenom každý 8. a stejně tak nemusíš porovnávat všechny barvy, ale můžeš to testovat co 4. bajt.
Nebo můžeš dělat z řádků něco jako kontrolní součet, možná by to bylo rychlejší.
Pokud ovšem chceš naprosto přesný výsledek, tak musíš porovnat všechny bajty.
To KIIV :
no jo ale tomu algoritmu moc nerozumiem.. napr co je to LSquare alebo ICRC.. no a nebolo by jednoduchsie porovnavat 2 jpg obrazky?? ide tu o to ze robim screeny obrazovky a posielam do aplikacie druheho pocitaca.. cize najprv urobim bitmapu potom z toho jpg a potom to hodim do memorystreamu a preposlem .. aked sa obrazovka nememi aby som neposielal zbytocne screeny.. alebo ako casto sa meni handle obrazovky? (funkcia GetWindowDC(GetDesktopWindow)) to handle sa zmeni len vtedy ak sa nieco na obrazovke prekresli? alebo je handle ine vzdy ked tu funkciu zavolam .. napadlo ma ze by som porovnaval to handle a tak zistil ci mam znovu poslat novy screen alebo ci nie..
k tomu jpg.. provonavam ich velkost... vzdy je ina ak sa obrazok zmeni ale k tomu potrebujem ten obrazok dostat do nejakeho streamu a to hlavne nechcem robit..
ok zistil som ze to handle mam furt rovnake (65556) cize asi zla moznost.. este ma napadlo .. ze trebars odchytavat nejake spravy ktore by prekreslovali okna a podla toho zistil ci mam poslat dalsi screen.. len k tomu neviem ako odchytavat spravy inych aplikacii a aku spravu bych mal asi odchytavat.. zacina sa mi to zbytocne komplikovat.. asi sa na to vybodnem
To Míša :
Keby to bolo tak jednoduche plakal bych od radosti. :D
Ale ono to je jednoduché. Chceš použít hash, tak ho použij. Nedostaneš k celému obrázku najednou? Tak porovnávej hash jednotlivých řádků a můžeš i některé přeskočit, jak jsem psal výše. Výšku a šířku obrázku znáš, počet bajtů na pixel taky, takže spraví jeden for cyklus.
k celemu obrazku naraz sa dostanem.. .. a co je to ten hash? ja nemam ani v najmensom ponatia co to je.. :D ako by som ho mal pouzit? mozte mi napisat nejaku jednoduchu ukazku v kode?
To Patrik Skoupý [: kdyby tak existovalo neco, kam zadam neco, co hledam, a ono to naslo co to je... nj jenze nic takoveho proste neni...
btw: hash je shodou okolnosti napriklad to CRC32, MD5, ..... a spooooousty dalsich..
idealni hash je stejny jen pro stejne soubory (data), ze kterych je vytvoren.. realne je pak kvalita hashe umerna mnozstvi kolizi.. (ruzne soubory, ktere maji stejny hash)
a ano.. z hashe se neda ziskat puvodni soubor (data)
To KIIV :
a nieje v delphi nejaka uz zabudovana funkcia hashu? trebars ze tam hodim tu bitmapu a vypluje nejake cislo alebo nejaky kod alebo nieco tak ak som tomu teda spravne pochopil.. pretoze nechcem tam vkladat dlhy kod tej funkcie trebars co je vyssie napisana ked jej nerozumiem..
To KIIV :
no na to aby som tomu algoritmu rozumel zrejme este niesom dostatocne daleko v znalosti delphi.. a ako som vravel nerad by som daval do svojho programu kody ktore neviem ako pracuju.. mimochodom .. skusal som porovnanie bitmap tak ze som porovnaval farbu jednotlivych pixelov...(canvas.pix[x,y]) ale pri obrazku 100x100 a volani tej funkcie asi 20 x za sekundu mi to procesor vytazovalo na 43 percent a .. je tu fakt ze pri porovnavani obrazkov z fullscreenu co je dost vysoke rozlisenie optimalnu hodnotu vytazenia procesoru by som mal mozno len vtedy tebz som porovnaval kazdy 100 pixel a to uz by bola docela blbost robit.. to uz je fakt realnejsie nacitat to jpg do streamu a potom len porovnat velkost (stream.size) ..
To KIIV :
inak ak chcem porovnavat trebars kazdy 4 bajt v tom pointri scanline ako mam trebars do premenej typu byte dostat stvrty bajt z pointru? viem ze ak chcem dostat prvy tak pouzijem nieco take ze ziskanybajt:=byte(pointer^); ale ako ziskat dalsie? trebars stvrty osmy , dvanasty atd atd... este ma v tomto trosku nakopnite pls..
skusal som ale nefunguje to, v delphi je to zrejme nejak inak..
To KIIV :
skusal som ale nefunguje to, v delphi je to zrejme nejak inak.
To KIIV : to mi taktiez nefunguje...
To Patrik Skoupý : http://www.delphi3000.com/articles/article_2224.asp tady tvrdi ze jede inc() a dec()..
To KIIV : no skusal som ale nefunguje mi to na premennu typu pointer.. iba na tie co mam typu byte alebo proste typovy nejakz pointer.... zrejme by fungovalo nieco ako ked zadefinujem PByte:^Byte; a potom kod bude takyto PByte:=Pointer; inc(PByte); potom by som vlastne precital z PByte druhy bajt Pointeru.. ale tak ta funkcia inc by tam musela byt dost vela krat aby som proste presiel cely obrazok tak ze budem porovnavat kaydy 4 popripade 8 bajt... potom bych tam tu funkciu musel davat 8x v nejakom cikle a tiez by mi procesor pritom nejasal radostou . :D
To TooM7 : aaaa funguje.. vdaka..
To Patrik Skoupý :
no vytvoril som takuto porovnavaciu funkciu
function tform1.porovnaj(var bitm1,bitm2:TBitmap):boolean;
var i,j:integer;
bt1,bt2:^byte;
begin
result:=true;
for j:=1 to (r.Bottom div 8)-1 do
begin
bt1:=bitm1.ScanLine[j*8];
bt2:=bitm2.ScanLine[j*8];
for i:=1 to (r.Right div 2) do
begin
inc(bt1,8);
inc(bt2,8);
if bt1^ <> bt2^ then result:=false;
end;
end;
end;
no a nastal dalsi problem.. tuto funkciu vyvolavam asi tak 20 x za sec .. a pri asi prvom vyvolani mi procesor vystupi na otrasnych 46 percent na niekolko sekund asi 10 potom klesne na asi 12 percent.. no v hentom pripade je skenovany kazdy osmy riadok a v tom riadku kazdy ôsmy Byte.. nuz ide o to ze ak tie atributy zmenim trebars tak ze bude skenovany len kazdy druhy riadok ..pricom sa pocet porovnavani zostvornasobi ale . vytazenost procesora je furt okolo 12 percent... iba v provom volani tejto funkcie ked je nejako 46 percent tak netrva 10 sec ale dlhsie .. v com je problem?
no a mimochodom ak funkciu volam asi tak 10 x za sec ..co je o polovicu menej krat.. tak sa aj vytazenost procesora znizi na 6 percent.. co je vlastne pochopitelne... .. ale nic ine v tom programe mi procesor nezere pretoze ak som funkciu odfiltroval tak program zral 0% proc... (podotikam ze program je novy skusobny nejedna sa o povodny program ktory mam na prenos screenshotov) pripada mi to celkom divne ..
kod som trosku pozmenil ale ziadna zmena furt..
function tform1.porovnaj(var bitm1,bitm2:TBitmap):boolean;
var i,j:integer;
bt1,bt2:^byte;
begin
result:=false;
for j:=1 to (r.Bottom div 8)-1 do
begin
bt1:=bitm1.ScanLine[j*8];
bt2:=bitm2.ScanLine[j*8];
for i:=1 to (r.Right div 2) do
begin
inc(bt1,8);
inc(bt2,8);
if bt1^ <> bt2^ then exit;
end;
end;
result:=true;
end;
Řekl bych, že je to podobný problém jako u to převodu do/z JPG. Prostě těch dat je hodně na to, aby to nebralo strojový čas. Můžeš klidně vynechat více řádek (co se stane na 4, 8, 16, 32 pixlech?) podle toho, jak přesně chceš detekovat změnu. Je potřeba si uvědomit, že změna polohy okna apod. se ti projeví i při delším "vzorkování". Kdyby si detekoval každý 32. řádek a každý 32. pixel, tak nezjistíš pouze pohybu uvnitř těchto čtverců. Ale je vůbec reálné, aby ti to někdo zkoušel tak malými okny? :smile1: Leda tak kurzor, ale ten asi posíláš stejně extra, ne? A další možností, jak to trochu vylepšit, je netestovat to pravoúhlou mřížkou, ale buď náhodně nebo kosodelníky.
Druhá věc ovšem je, jestli na takové věci je vhodně Delphi. Určitě je to nástroj, ve které uděláš danou věc rychle. Ale neřekl bych (po zkušenostech s Borland produkty), že to i rychle poběží.
To liborb :
ja porovnavam kazdy osmy bajt to znamena kazdy druhy pixel ale vnom iba jeden bajt.. a kazdy osmy riadok ale ak to zmenim trebars tak ze bude porovnavat 2x viac bajtob alebo 2x menej bajtov vytazenost procesora je furt rovnaka.. a aj sa mi meni aktivne velkost ukladanej bitmapy ale v tom to neni.. problem je v tom ze staci raz vyvolat pri novej bitmape funkciu scanline a vtedy ta vytazenost stupne.. potom uz nezalezi na tom kolko krat tu funkciu volam... procesor uz mi to nezere.. az ked bitmapu zmenim (novy screenshot) a znovu vyvolam funkciu scanline... keby som mal proceduru ktoru vyvolavam 20x za sekundu a bola by v nej iba nova bitmapa a 1x funkcia scanline vytazovalo by mi to procesor tak isto ako teras..
a ktej druhej veci.. Delphi je asi jedina vec v ktorej viem robit.. pretoze je tam jazyk pascal.. ja pouzivam delphi 7 ale teras som si neni isty ci delphi 2009 je produktom borland.. ten som mal tiez ale vobec som to nepouzival ... delphi 7 je o dost prehladnejsi.
Zkus kdyžtak funkci GETDIBITS místo toho volání scanline obejde to Delphi, je to přímo win api.
nějak takhle:
GetDIBits( parametry:
handle of device context,
handle of bitmap ,
first scan line to set in destination bitmap ,
number of scan lines to copy ,
ukazatel - address of array for bitmap bits ,
address of structure with bitmap data (bi:BITMAPINFO),
RGB or palette index (napr. dib_rgb_colors)
);
var bi:BITMAPINFOHEADER;
bi.biSize := sizeof(BITMAPINFOHEADER);
bi.biWidth := SplashInfo.bmWidth;
bi.biHeight := SplashInfo.bmHeight;
bi.biPlanes := 1;
bi.biBitCount := 24;
bi.biCompression := BI_RGB;
To Patrik Skoupý : Nechtěl jsem ti Delphi rozmlouvat nebo tak něco. Jenom jsem chtěl říct, že jsi "zajatcem" postupů, které vymyslel někdo jiný. To je samozřejmě u všech knihoven, ale u Borlandu mi často přišlo, že zrovna ten jejich postup je skoro ten nejhorší (nebo jinak - málokdy mi přišel vhodný pro moje účely). A toto je podobná situace. Ty se divíš, že ti to při prvním volání scanline bere strojový čas a při dalších už ne. To bude nejspíš způsobené tím, že se při prvním volání natahuje do paměti celá bitmapa a při těch dalších už se data jenom prochází. A to je to, co se ti nehodí. Jednak nepotřebuješ všechna data a taky je nepotřebuješ najednou. Takže pokud se s tím nechceš smířit, tak to budeš muset obejít např. přes výše zmiňovanou funkci GetDIBits. Její volání pro jednotlivé řádky ti bude vytěžovat procesor rovnoměrně :-).
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
ZObrazeni bitmapy — založil _Radek_
Ako spolahlivo zistit ci je subor novsi ako druhy — založil marioff
Ako docielit nieco ako dynamicku tabulku — založil Dee