Tad, Думаю, что дело в другом. Такое впечатление, что это не его картинка! Если это не так, то вопрос звучал-бы по другому. Человек владеющий всем циклом функций в одном кадре задал-бы вопрос иначе. Wabi-Sabi, 100-500 ответов на твой вопрос (смотреть не только "Программирование игр" https://gamedev.ru/forum/ и вот https://www.redblobgames.com/ . Разбивай общую задачу на подзадачи и говори суть - где не клеится, или ты хочешь чтобы за тебя концепцию решили? Иначе, по простому, на картинке можно искать по шаблону: По части картинки. Add(MainForm,10552383,231,84) { Width=435 Height=214 Position=1 Point(onChar) link(onCreate,12795964:doEvent1,[]) } Add(Button,3884042,259,210) { Left=170 Top=5 link(onClick,8282293:doStart,[]) } Add(Image,5758247,532,140) { Left=120 Top=120 Width=40 Height=40 AutoSize=0 ViewStyle=4 Point(doTop) Point(doLeft) Point(onMouseDown) Point(Handle) link(onMouseDown,16176673:doMove,[(578,153)(578,237)(529,237)(529,202)]) } Add(InlineCode,2366711,378,210) { WorkPoints=#12:doFindBitmap| EventPoints=#8:onResult|8:SumError| DataPoints=#6:Bitmap|9:subBitmap| Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses Windows,kol,Share,Debug;|0:|4:type|40: TByteArray = array [0..32767] of Byte;|27: PByteArray = ^TByteArray;|35: TBuf = array of array of integer;|15: FRes = record|19: found: boolean;|17: x,y: integer;|17: percent:real;|6: end;|14: WH2 = record|43: Width1,Height1,Width2,Height2: integer;|6: end;|2: |28: THiAsmClass = class(TDebug)|10: private|0:|9: public|12: Bitmap,|15: subBitmap,|35: onResult, SumError: THI_Event;|57: procedure doFindBitmap(var _Data:TData; Index:word);|65: function CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2): FRes;|5: end;|0:|14:implementation|0:|40:function LoagIMG(var Bmp:PBitmap) :TBuf;|3:var|17: x,y,c: integer;|16: p: pByteArray;|15: buffer: TBuf;|5:begin|36: Bmp.PixelFormat:=pf24Bit;//pf8Bit;|43: SetLength(buffer, Bmp.Height, Bmp.Width);|35: for y:=0 to Bmp.Height-1 do begin|23: p:=Bmp.ScanLine[y];|36: for x:=0 to Bmp.Width-1 do begin|52: c:=((p[x*3+0] shl 8+p[x*3+1]) shl 8)+p[x*3+2];|21: buffer[y,x]:=c;|8: end;|6: end;|19: Result := buffer;|4:end;|0:|72:function THiAsmClass.CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2): FRes;|3:var|29: y, x, yy, xx, err: integer;|23: sumerr, sum: LongInt;|5:begin|58: //maxerr:=200; //максимальная ошибка = в диапазоне 0-726|21: sum:=High(LongInt);|22: Result.found:=false;|7: y:=0;|8: repeat|9: x:=0;|10: repeat|25: Result.found:=true;|16: sumerr:=0;|12: yy:=0;|12: repeat|14: xx:=0;|14: repeat|55: //Result.found:=buf1[y+yy, x+xx]=buf2[yy,xx];|71: err:=abs(byte(buf1[y+yy, x+xx]) - (buf2[yy,xx] and $0000ff))+|91: abs((buf1[y+yy, x+xx] and $00ff00 shr 8) - (buf2[yy,xx] and $00ff00 shr 8))+|93: abs((buf1[y+yy, x+xx] and $ff0000 shr 16) - (buf2[yy,xx] and $ff0000 shr 16));|51: //if err>maxerr then Result.found:=false;|29: sumerr:=sumerr+err;|49: if sumerr>sum then Result.found:=false;|18: inc(xx);|52: until (xx>=WH.Width2) or (Not Result.found);|16: inc(yy);|51: until (yy>=WH.Height2) or (Not Result.found);|30: if sumerr<sum then begin|21: sum:=sumerr;|21: Result.x:=x;|21: Result.y:=y;|59: Result.percent:=sumerr/(726*WH.Width2*WH.Height2);|10: end;|13: inc(x);|34: until (x>WH.Width1-WH.Width2);|11: inc(y);|34: until (y>WH.Height1-WH.Height2);|21: Result.found:=true;|30: //if Result.found then begin|20: //Result.x:=x-1;|20: //Result.y:=y-1;|8: //end;|4:end;|0:|35:procedure THiAsmClass.doFindBitmap;|3:var|24: Bmp, subbmp:PBitmap;|21: FindResult: FRes;|21: buf1, buf2: TBuf;|12: WH: WH2;|16: dt,di:TData;|5:begin|36: Bmp := ReadBitmap(_Data,Bitmap);|42: if (Bmp = nil) or Bmp.Empty then exit;|42: subbmp := ReadBitmap(_Data,subBitmap);|48: if (subbmp = nil) or subbmp.Empty then exit;|73: if (Bmp.Width<subbmp.Width) or (Bmp.Height<subbmp.Height) then exit;|4: |25: buf1 := LoagIMG(Bmp);|25: WH.Width1:=Bmp.Width;|27: WH.Height1:=Bmp.Height;|15: //Bmp.Free;|4: |28: buf2 := LoagIMG(subbmp);|28: WH.Width2:=subbmp.Width;|30: WH.Height2:=subbmp.Height;|22: //subbmp.Free; |4: |43: FindResult:=CompareIMG(buf1, buf2, WH);|4: |15: dtNull(dt);|15: dtNull(di);|34: if FindResult.found then begin|57: dtInteger(dt,FindResult.x);//+(WH.width2 div 2));|58: dtInteger(di,FindResult.y);//+(WH.height2 div 2));|24: dt.ldata := @di;|34: _hi_onEvent(onResult, dt);|50: _hi_onEvent(SumError, FindResult.percent);|8: end;|4:end;|4:end.| link(onResult,13902867:doEvent1,[]) link(SumError,4467059:doCalc,[(424,223)(424,258)]) link(Bitmap,3103349:ImageBitmap,[]) link(subBitmap,5758247:ImageBitmap,[(391,180)(538,180)]) } Add(MT_Part,15868768,490,154) { link(onSplit,5758247:doTop,[]) link(onPart,5758247:doLeft,[]) } Add(MoveWindow,16176673,539,196) { link(Handle,5758247:Handle,[]) } Add(Label,7469250,616,252) { Left=230 Top=10 Width=115 } Add(FormatStr,8296708,574,252) { DataCount=1 Mask="Минимальная ошибка - %1 %" link(onFString,7469250:doText,[]) } Add(Hub,13902867,434,210) { link(onEvent1,8282293:doStop,[(466,216)(466,265)(319,265)(319,223)]) link(onEvent2,15868768:doSplit,[(459,223)(459,160)]) } Add(TimeCounter,8282293,329,210) { link(onStart,2366711:doFindBitmap,[]) link(onStop,6823186:doString,[(368,223)(368,286)]) } Add(Label,15385577,434,280) { Left=230 Top=35 } Add(FormatStr,6823186,385,280) { DataCount=1 Mask="Время поиска - %1 Millisecond" link(onFString,15385577:doText,[]) } Add(MathParse,4467059,525,252) { DataCount=1 MathStr="round(%1*100,0.01)" link(onResult,8296708:doString,[]) } Add(Hub,12795964,280,98) { link(onEvent1,9570550:doBitmap,[]) link(onEvent2,9881532:doBitmap,[(312,111)(312,160)]) } Add(Image,3103349,378,84) { Width=160 Height=155 AutoSize=0 ViewStyle=4 } Add(Jpeg,9570550,329,84) { Jpeg=[ZIP690E000078DA9DD16558D38DD707F0DF60309808821BD2E18811D270A31202C26E24878C492825C824478980204A4B88843A900E41E99006699472E42825A56F06A326F1D7FFF5C49BE7C5F33CDFF3F29CEB5CE7739DB389B31FC0855B3ABA3A000804026C7E177036056801F4603A7A3A303D3D1D3D0442CF00BD008532324261CC2C4C172EC138382EC1D8D9B97885F9B9B8113CECEC0292020811513171314EFE2B32579032C24831E49F252008040265805E84422F22B9D8B990FFE79CB502AC0C801FE0470BBA0CD0B082685941671D003F0080E840FF0EF01F01D1D0FEBE17C2C0083DF77BA0FA024003A2A5A501D3D2D181C1BFBB4F7EF701302B1D9BA0AC06FD45B42DE4321E26179290C580D02CFF0C37F9B62D246FE7F98C11CA7E8983934B5844142926AEA0A8F497F2D56B5A37B575507FEBDEBA6D8A31C3DE31B7B0BFEFE0F8C009F7D0CBDBC7F791DF63FFE7A161E1119151D1AF129392535EBF794BC8CEC9CDCB2F785F58545159555DF3A9B6AEBEADBDA3B3ABBBA7F70B717864746C7C82343937BFB0B8B4FC7365758DBCB34BD9DB3F383CA2FE7181005AD07FE67F74B1FE76D180C1B460C81F1788E6D19F0156309DA02C3D9B061A628BBF78592E8401A6999055FE9911216FB20DB7F3FC06651752981326FFA1FD5BF6BF833DFB7FC9FE0BF6DFAE49808916F4FB79B4AC803AF05C617A5757D73A5B4722999F45EC7A7907D1588CB1E0FE255B4AFEA726A927B8826235CC8454DB9B6ED8D71791C539728673171E290ECEF8D577D1736227FCE56538A9CCD5BD915D73655BA34289D7566C25C6B1CF8656747F3629504A82BE77FA267E01E32B7574B410F4CA7B53A73C638BB7BB559C850C79B96BAF1E8BD9EE322909EF0C279330DB98ED7542F6103EDF31898053C1BA8B6FE077653986753BC5148689719889C0BE58EAB7BF47B07C6252F77D8CFDE51D5F52F2E613D7EFA20FD19D5726AAF870C8417FA8261F9DA4EEB29232E0A9BB81FC11BF6AD512AB6856A6E7ECFDB27BF9A2500CCB76DCF758FC02599A4513C37EC2DCC8CE8B2DE6508D6E967D79D4057731F8E4A1D5A3BD61544729613EED2C9EEEF5EDCC0DF24DF949562796E2083195B3D3F7FAFA258B0FB0BC542475BCE1507EAEEB1DEF476C7D9FB5CBC8226826EDDDFBE0FA9C21ECF21E9939AD2E7F8B745025733AA6145D810AC1F90765FFF84A97D6A6C81D6283EF2E8057E63ABB3EF0AA5F0DD57BF791E12A623AD882AAF6CBA0DAD2374683239EA3D50A744F9BCCDDEEDBE2F06A0E96C5B3ED2CA9A6862ECAAD721CDDD9DB20B8AD10883BB33B32FBC32824425D6C31082E817DEBA773DBA13872D27D46FD0B269EBE499E87C95382F2B1928BEC5D9757AF462BD3F651510FE5A84070E6C2AF1BB825AFF22063EBD11AABDAF8F966211F6352AAEAEAB5E54491E79FA963647F440A7AF405413F4163F95549C753C5A51636B773EBC4F7031399986323F5B12634FD9D0705FE3B2CDC328956230E2A2102A6D626F4909DD2F4C10FC2BAB7B7061F89644FCFE8A8CF1D9072C637084789BD4FDF4E5F0FA58BD048ECB6A0226E906B3202CF800761223A2A34AD70515252C23DC6ED44BDB2D1BDBAE23D0C1B42BB55B4D97F7CA866923E35C77C99246774D080FD794892F2ADCFF009096D2238DBB544071AD7DB1DE19C0E2EDA94A35BD16B1E8CC7618F4F4E9BF823B3029C7688217543961574D61F78324A2486F3C327174C9C4A16C07F47EBA0ACA0CB8D6E9341613933AA1FC5D836253B512265B9449CE5EDEC5C4B038A9A276E7610FB9DBF0F113C085F27384CDE9B6857F19B5C4F97E8FE273F6EFFE740556827370F9DA8E8FABD173F32C916BAE77E3AB54B2F8C35FF23508C1CF158198C1C10D3315E6EEEBEE93F6C207141DE4094A6B9F12849B19E4B8C63DBA944C5A823AE9E5BDE5A21027CDB8B8ACEB8B5F2C20C2551FF08A684AA5D37C2487AFA01A637F91B73327E1AEA484D5328948F457AC9AA0685ED6F8B691E8F8183FF5A6AFB67D04EA2BBF1E6ACEB0631F831A945F65EC48233A57A5808A7B67B3EB26E91B02B9231807114DAB2BA98EEA94E1DDDF63BD62BBDDB3083D894A1C0B9C4952A1D3240D6E7E53B953611B0D8A9AF5756D3238EA9E344F74299613DC5C6D7E884F09D091A7539F55B47B68238B7211D8F3E9DF34F04E70EB77E0C0BA44FC935B70A874C7DB07F55F069386BBF34A3CFC4C444B5B1C228B97323CABEA57352B53AB4FF7A6CD672C32CEC891C7EAFE4DC82D2C797ABDFED76FFB21AD0DC843CBD4ED8ACB686AB369EE7B1B0D4BE7A06A4475ECAB0F6DFFECEF124FFA799F38BA6A91ED1658E7E1D563153038A52F7C801D7B3F2B087608F38AF88D57B0559D9E7FC1663D238920D51056780B5E25251D6656BABE58678C6B57564DC251BCEDACF2A6EFC0B2712EB1569A648CC013543F48DED92C5BB9CA175235185614381B82603851389CD05A1D1ADC0B4ECE1EA70D9E3955C1BA7122BBD515E187BCC1816CB093675BD2630C0F9BA94A668D65C0F56C4D29FA1D5737CFDB4DAC407CAFC6BE7A957F9764BFAE31389B83B9D70FB8A7496D47BE1512D61E1B703F86F84BF19CF83D9C9092786F138D6A56EA2ED7E0E9AD1FEAAEBA5329D0161569F6A65563D1FBEB696DC50430F4C8C1F075347774925CEA2FC0E90BAAD2592B7A0344EB8FC4BA066F32FEDF91B1CAC2C9CA7E42DE7B7319BB18672DC3501D4E1BD80F8AA1995686662C041C987CFCD6CAFADAAE356BF9EF3AE8D63B207127B7B379FAA5B902FEE7B34C69D3C1C19FA4CCCF41DD9C4D8FB4AB6D24175111358E2290FD2255BE0A5D25C08D8CB2A23B40A1D30BF5AAD01158E8D09BE5F35E9C91B316BBB7115BE8AB48F824ADAD078111B635CB53139A436F4BE6E92DB4B5D6E57955F3EA54C8711F9562299C3B9263DA19B92B0B24572CF0F6C53A8A96B7B9EC968F1FC88C0AB73617D6EB5CAEB1B41D5B1D0F42F565D7B85017F4F1C395C9ECE0AF891D0EFE4A4C6DF3282684834745A22CCE8F7BB262EBBF29AA3B4A2D78EEDE704F38FDC99CDE6D2E235948CE8505E1321837377D963E7F68955A9AA6632DFBE9B5BE9ECB8BAF0E6D5949D78A05AAAFDBFC208666B8FD9DAAAF656BCF838C89C8D5338EF2F5210DA9A7F06A9585D411B3F0C7FAC4730DC7BA5AA94D3BA9810B980638ACEC91C3456E77ADDE63FD3517E8415EA67B39734BC0BD9835348660F7A9D06EDDBFA64D4C6EF14A3279582A3920240DA2850B44D6014A8DB588EE104591A54ED67D82FDF1EC6D8B69A933B2279BC08AAEBD64F0B428D9529220DEA834E977DD0DF78EE67E48320DB25BD09FE7CA83C9B7582A49CA5917063655BA757051C223A61AF9E005FC634E6780DE548999BA7638B66840E720D1002E7AB31D4F8407FA233B5AC29CA2E6ADAA283A68832FDC469A44AECA3A89897CBBABCAC47075B6DB7FE816288B24D4954CA29CFAF83EE756B798BF3033BAA2BA60792D18B97B8CBE3DD5AB1C4EF5085EB012DE1D4C0C4F6B4E9861A23C855606135FAA8872E6E1C07C1DB1E61C75A18BFE51DE29C52AF6A72A2CA686AC96EE4259421BBD26BD902DE5CDF954236F1CB31400E00B54F1EEC131F21513EAE56BEF2BAC75DB7A9BD728735273E2533853722B3135BD3B8B3F58DFB69373CC7F791D2A5CCEC395FFB59D2D474896894106DFED280DADB1277CB70858A44C317825211C9D586869E0C27DA3E5E5D138A51E793AB6BAA1FF81A57A290EEEF48E5832EE91216EE966F4D47EF9007E38A04C9A38BE05D0E8DF822B1D3FCDA6096B52BF96B787DFAC5014EAF11BEEAD9A0216865A0C9480762AB9335917F76A7CBB9FF4ACACD5A13781498B5F389081F592FE9686D60737AAF47710A0C4854A10A756164CA19B08EC634AAE66B0717685DEBEA89537DEB35ED6A73E318C86E9AC2E0AEA7BBE4195CBF43392DF8346790AE0193EC33A5E314DA16ABEBA2F5DE83C3DE87854079E2341079DEC89A2AE561DD9934A348C1864669A16DB9B7033D981EE3C8ABD301A5A5EAC4DA6284A6732CC6CEA6AE875F9F7222E73CE6EE3DDE5CC7AD875002B9D5F225EB196C37A48E91B8BE9094E5D860F89884E3BB46BCEBCBF2B8FA8B956B4F943006D8B05F7C96F882DCC435C3374EC55A2EB6DF9A5D68A9E36367C03901BD607ADC1CF392D36EF7D28944A774A0828B62A45D2467566D0AC2F3BEBEF4F9E17406153EE50538852FAA46C26F3ED64C79C4168305053DF52E5534DD4F71DA2834227D6049D57574944D12F7BF7F06EC7D50DAD5737A99A2092945DFBD25439BC7D4FA4C4ED6FC56CC7DD65264BAC1BC9012BE6A215E7A799058CF2BAC36EE127F3247A85C90666A2E2FF8CA1B5A082E91D18A4F88084269E96FA7BC7E6FD16AD3A4C1847F57B41422A55A16FCCEEBD673936B0B7795ADF0C3B9E9060952F891F4671FA6578CA72AFAE51B63227C47DB9EC739971B8923F73301682B194E511AABE89500E0BA6A872593A6A68F948BC6936AD4EE1F3E07B590F74BBD04A72B2AB65C3C0063F53797E3999DD83F5D4BD55FFD1556C37ADC7E1877755F35B8B7A466B65F3A3CEBF1658799A899EFAF0CC567C2EA3F3B73DDA429910F59739EEDE52A35D3A5A834CE4AC522A70A35BB0DC367CC6115BA69356DA67F35432C248CDFCFEC06D94553AF25DCEAD91614D9736C0D4BF0048E2B1EEAC3ADC2C01916C812646F953B3236D6EA4B28403F4798AC0C958CC1C719DD429612E6F9FD8DEB28E6B4F89853ED2B38B4D02701A6A39028AAD7DDAED4BA056C5884E1BB5818364393606ADA489A894AF5E17A12EBB4F83A47E7FBD34235DFB5E243B236BC38CE326A4976AD3328694C13D4DE32EF89CCCEEF8ACC7ADFAB825E549A9B60D92E953E7CEE8357CC7C2A2F7540EBEEB5498C16275471DCAE7C1F31B19AE1F8AD031CB8E8165C9AE77023CC160849E85ED286CFB413F1C50A0D3CA435C3186B47B91BF87E18DA1A63E6B672F45EE3CE19E95F4E6AF589] Point(doBitmap) link(onBitmap,3103349:doLoad,[]) } Add(Jpeg,9881532,343,140) { Jpeg=[ZIP5F03000078DAFB7FE3FF0306012F374F370646464686042064F87F9BC199818D85958D95858D8D958D9D9D8D834B808B8B93934B848F9F47405C4442425C444C4C4A56555E4A5A59464C4C414741594D5D534B53525ED74057C340554353036408233B3B3B170797301797B08694989406C9E0FF0106410E06790659664625062641466641C6FF47807C0646564630608002462666A07BD93938B9B8810AB60A303031323333B130B3B2B2B000656B81F20C2C82AC428A868E6CC28189EC4A8522468D131772283B6D3C281A74F1838A71525113279798B884A494AA9ABA86A69689A999B985A595B38BAB9BBB87A7577048685878446454724A6A5A7A4666567149695979456555734B6B5B7B4767D7A4C953A64E9B3E63E6AC458B972C5DB67CC5CA559B366FD9BA6DFB8E9DBB0E1D3E72F4D8F113274F5DBA7CE5EAB5EB376EDE7AF8E8F193A7CF9EBF78F9EAE3A7CF5FBE7EFBFEE3E72F90BF181998196100ABBF0481FE62626161666107F98B91A91CA440908555D1904DC831903DB15058C9A89143C469E2C28D0739958D833E8826155DE412533179A8FA11E435B0CF88F35813593E837B0CE1AF5B0C3CCC8CC0C8631664B067F830BBBAD6EDD4FDB76AD7421CCAFE1C787EFDD2EE78B68A6DD26111FAE91E5777324F62FC37DFEBCBDBBC439C8A3755BC6AF90CE30C1FAFE5E2B6BCE6D1AD985FC5F0AD3A7AC7BB8777B917AFFF3EE1B9A9BAD767F996EB6792A75DCBDCFED632E0F8C4B8390F9E3558FE6710AE38A9BB34E3D19634D7DCB5D6DA46CD2F441DD53F2AEDA817BEE7BAF665709CD3D1451DC995DDA77F6E7E39B97F69D5D2B5735B9F18A95EE17A66E4C85235EB819D469658546A53F4DFF9DF59B7755CEEF967C278E0077BB855DEB636079BE5D67ED5697BFF498685F05855879F95CAE1D55BD4E876B57882F185AAF0FD157191F2AEDBF5FC3E98CD3FBC94A1FEFF4D00C79F3DA5] Point(doBitmap) link(onBitmap,5758247:doLoad,[]) }
По части картинки на картинке. Add(Button,3183747,266,231) { Left=20 Top=20 Caption="Искать" link(onClick,8282293:doStart,[]) } Add(Bitmap,8059100,406,112) { @Hint=#8:Где ищем| AddHint(-21,-26,65,13,@Hint) } Add(DoData,9296008,406,168) { link(onEventData,10552383:doPicture,[]) link(Data,16257815:Var2,[]) } Add(Image,5758247,539,224) { @Hint=#8:Что ищем| Left=120 Top=120 Width=40 Height=40 WinStyle=2 AutoSize=0 ViewStyle=4 Picture=[ZIPD60B000078DA5556D9561BD915ED3CE707F296D77C413E20EFF984ACA0B9464D0833191BF00062B2DD606CA3A94AB30061A0B18D26C0066C26A9541A40129A80D8068CBB57C776A79D7656675FC96175B48EEEBA5575B5F7D9FB9E734B7FF9EBFEEFBF697CFE8CEF9FF0FDE3D7EFEFBEF943E3BEF0F5F96F3F5D91B39EE8596FE2BC2F717E237EDA1FFD47F762E54AB868F2E738FB8EEED12BEAD14BEDC426757F533DB1A199D8D4DEDFE41DA9367FB17DBA680E14F4DE1CEFDB37F80F78FF01E72F1883457DA0C078F39C37C77A65E0B3BEBC7EA6D4B670D4F5F44D5FECBC3FFEAE8F709D5D8BBCB9BA58EB9C2B9BBD19DE99A41E6D69263735131BDA890DD5B7EBDA8997CCC32DCE9134FB72AD817D4BB06404973FCFBBC155D0070EF43E72097C832FCB7BB3B43BC3F872FA60D1F2F8A873F9F43AA1787773F5A22F7A767DF975CFD2517BB80428CE99D23E780521BAC94DEDF8BAFADB17D4E44BCC597BCAE0CE80A8D55F40E8BDFBAC3B6FF01781CF8849DE2BEBFD32EF93594F1A5CAC27CB070AE670ADFDC99B6BB18BFEC4FBDEF8BB1B608CBCB9FEE4B863EED012C8F3424AF7704B737F93816390D3E08234FAD1B651485B02FBE6C081C97740F0853DDAB1ABB36FB3AE3DDE93D6FB32BC47E6BD19CA2D339E2CE3CF9967AB9D4BAFAFC5CE7B1317FDF1F3BED82951F45DB563A668816458F7F095F63E4C7BA1BEF75C73F7B976625D3BF98AB125F5AE86FFAE248271EE51B61D9D7D47EBD8E1843D564C716E9958E7966951A20499F1E50D33E5F6C5939EC8DBEBB1B31B702F7EDE1F7BDBB354EF9EAF9803FB4651A6A776E0957AFC054275178A9E137CB78CA0DD12617125693149DB7728C72EE5DA659CBB8C98E2BD300D0B644A4C53A2CCF90E8C33E52B8B27579F9DF6C641849238EB7DF6F6DAD249D77CC512DAE7450944F04AF3ED0B82EFC9D0BE2CE3931B44694A9018570AB03A2728F62047E36C7089295694184F1AEB41A41532284243A8D4367FD4FDF46D6FEC7D5FFCA22F7ED61F39ED5D3A69877581BCC9936EE40FABD394472644A0F066582489B990A25C49AD2BA971EEE91CBBB47357E720068214696083886A41D60A69AD887A285AE66A9D4B27D72367FDF18BFE18FAE8B4E7C909C11700986108788616D38C47E6480965C8E8CD420E6E52D844A8B0EF30F0CDB6ADB36D634E0BF03365C4CAA6C382AC13B3ACFFC014AE763E412B5DDC5879077CDA956505129C90635D589C65C182EDF0910C8928729941D132429A7649942B453B93B483541D3DB5053A6C136A8F1325D603168926C9EC3162C6102C019FF31EB0628E1173BC33C33A64C6217382AC872241E6D174A2CC886998C6340CC42514E95CB02ECD3853B43D097CCA411469A7B6B4A4C85328458C2C921124E09B67AA0853A86C4047BBF7F5428E7165696786B1A739478675C92C761CBD20A4C9E89675420A7218779616B14719DA2951F65D688163C4B4A92D9D8D88C21DAE816F9AAD9B666B96F091257C6C99A999A72B7A5F89F31639310F2E0EA29C32583807C634E112538C90E23CE042B191BA259E346DB1EF32533B8C6D87826FE4607C057C7DA8649C3E34872A084BB8DE3A5B6B0D1F99C275D374C5182C1BC1E53E0017EBCC32CE3444310E84C44197287162B3AA256C318286390E89B6A7903C5868DB16D95F62290E841CFC31E2180C964CA18A098ECD56DBE68E2C73C7A6E91A2E8D81B2317068F01659C295010BD185D1251158E822D2245E206229679AC64968DB053EEFC9EB9A25E1440765F5DEBCD15F44E8C1153A344C97506F1D4F8EBB96DF5C8B9C767C77027683AFA8F714788110913D020B44B950C612EB4C312E0891692782F4D7D5C5A3EE85FA95D992C9871295184284DD44B5E45AE70FADEBE753B98F62E5B378F8F3D4FE87F1E40FB737CE6EAD9E772CD48CA18AD1736870970C428173E4396716E5C73A329C931888407B92FE7AB8D3EACD764E977A166A3D0BF58E70D980B78F98A15C52CFD36357E18BAFFAD95FFB97AFFA93B7F22974FC2570F2ABEFE8D709E9A3395C37CFD4CDA1BAD15735FACA064F8915F639679E736439478E475B8919E0AB8657D5A36B8ABB6B9AC9970621DD162C5C5DA8753DAE763EAE5C992BF645EBF6FC474FF9274FF993EBE0477BF67BD7FE8F984CE53F752D9F1A67ABC6E9AA79B66E9939699D3E32FA2B066F85174A9CABC0D873B4839CCF9A9135F5F02A5814645C518DADA8C7D7F1E2B3F8F35D7395F6F9CACDC46B7BEE83A7F4C95DFAE8C87EFF487AEFC8FDF3DECEFB2B4B752E80B76D491F281B021543B0664484EAA6C684872237E95FCDE873E06B479F6BC75E6847D7B463ABAA11B0AC2AC656B5E31BF4D4EECDC8B1B7FC4BE8F8DF33AF11FF09D43FFB2B3F3F903FB42F5429B4187C70E7F5DE03DE5334F8CB467FD514AC9882554214AA031F98AAA115927933FFE1B86674453D92688E7F1F8A691F6CDCD93873173F07EABF90A87D110A9FEF6CFFD03A5BE03C59CA9ED2D9249A34050E961C4E00A3B760F01D1AFC95D6608DE43FB60A1CD5700CA37A7445F9FFF8AA9184F2EE9AC99DEE5DACF42E956FC58E7B9F55DA42797330DFF1B8D2335FEF0A972DF8E78093135507221BCE2519270C873F129E02F0096C232E012F25A886A3EAD184626405BC8AB10442756745311A6F198EC13DE5BD3506B5E7C13695BB1F1FB7876BAD81A241CCD17689B225695B8AB6490D7CE289C21A6DC2FE061C13A248359C203112472887E278048D78AA1E4E2886627FB3465A4612D4E4B649C874864A57672B5DE16A5BE8D0E8CEA1059AF8CAA1D8256C3360976634FE55144C231B14C3B246A5C5900CE64A6B4239140505E1B5AE28AC71E5485C33BECEBB5270AC3B8CF77EAD51FF71B27828D6CCB9C9D564C15C3314D72267FC7C30813220985632C1A5BA1158A01A8CAAAD312C530E465503D196DBCF5A00389AD04DBE6CE25F86F27FB93529909B9A80C7D4563C051DA012AAC1B87A68453D0470721F0B54580F0AB21823F11008C069B14609FE10711263730B94C0B7C62EE9B05E717B193F5758230467A08189188C2907224D6A05600917B983945A06238052347088FF7804F64640AC069E58570863D32B6BF4F2870DFC88726099C46004E9A9F0A801A51A882B07628A5BD1164C06E3CADB50146F1920F8FF05B9670808] Point(doTop) Point(doLeft) Point(onMouseDown) Point(Handle) link(onMouseDown,16176673:doMove,[]) AddHint(35,-30,66,13,@Hint) } Add(MoveWindow,16176673,588,231) { link(Handle,5758247:Handle,[(594,222)(580,222)(580,264)(552,264)]) } Add(MT_Part,9384028,469,238) { link(onSplit,5758247:doTop,[]) link(onPart,5758247:doLeft,[]) } Add(GetDataEx,16257815,406,154) { link(Data,8059100:Bitmap,[]) } Add(TimeCounter,8282293,329,231) { link(onStart,2366711:doFindBitmap,[]) link(onStop,6823186:doString,[(375,244)(375,293)]) } Add(Label,15385577,434,287) { Left=85 Top=20 Width=4 Height=4 Caption="" } Add(FormatStr,6823186,385,287) { DataCount=1 Mask="Время поиска - %1 Millisecond" link(onFString,15385577:doText,[]) } Add(Hub,12533344,434,231) { link(onEvent1,8282293:doStop,[(459,237)(459,272)(319,272)(319,244)]) link(onEvent2,9384028:doSplit,[]) } Add(MainForm,10552383,455,140) { Width=325 Height=230 WindowsState=2 Position=1 Point(onChar) Point(doPicture) link(onCreate,9296008:doData,[(494,160)(494,188)(396,188)(396,174)]) } Add(InlineCode,2366711,385,231) { WorkPoints=#12:doFindBitmap| EventPoints=#8:onResult|8:SumError| DataPoints=#6:Bitmap|9:subBitmap|8:minError| Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses Windows,kol,Share,Debug;|0:|4:type|40: TByteArray = array [0..32767] of Byte;|27: PByteArray = ^TByteArray;|35: TBuf = array of array of integer;|15: FRes = record|19: found: boolean;|17: x,y: integer;|17: percent:real;|6: end;|14: WH2 = record|43: Width1,Height1,Width2,Height2: integer;|6: end;|2: |28: THiAsmClass = class(TDebug)|10: private|0:|9: public|12: Bitmap,|15: subBitmap,|45: onResult, SumError, minError: THI_Event;|57: procedure doFindBitmap(var _Data:TData; Index:word);|81: function CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2; mError:Integer): FRes;|5: end;|0:|14:implementation|0:|40:function LoagIMG(var Bmp:PBitmap) :TBuf;|3:var|15: x,y: integer;|16: p: pByteArray;|15: buffer: TBuf;|5:begin|36: Bmp.PixelFormat:=pf24Bit;//pf8Bit;|45: SetLength(buffer, Bmp.Height, Bmp.Width*3);|35: for y:=0 to Bmp.Height-1 do begin|23: p:=Bmp.ScanLine[y];|38: for x:=0 to Bmp.Width*3-1 do begin|24: buffer[y,x]:=p[x];|8: end;|6: end;|19: Result := buffer;|4:end;|0:|88:function THiAsmClass.CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2; mError:Integer): FRes;|3:var|36: y, x, yy, xx, err, color: integer;|32: sumerr, sum, pmError: LongInt;|5:begin|54: //максимальная ошибка = в диапазоне 0-726 на пиксель|54: pmError:=round(726*WH.Width2*WH.Height2*mError/100);|23: //sum:=High(LongInt);|17: sum:=pmError+1;|22: Result.found:=false;|20: Result.percent:=0;|7: y:=0;|8: repeat|9: x:=0;|10: repeat|25: Result.found:=true;|16: sumerr:=0;|12: yy:=0;|12: repeat|14: xx:=0;|14: repeat|38: for color:=0 to 2 do begin|67: sumerr:=sumerr+abs(buf1[y+yy, x+xx] - buf2[yy,xx]);|24: inc(xx);|16: end;|53: if sumerr>sum then Result.found:=false; |52: until (xx>=WH.Width2) or (Not Result.found);|16: inc(yy);|51: until (yy>=WH.Height2) or (Not Result.found);|30: if sumerr<sum then begin|21: sum:=sumerr;|27: Result.x:=x div 3;|21: Result.y:=y;|60: Result.percent:= sumerr/(726*WH.Width2*WH.Height2);|10: end;|13: inc(x);|34: until (x>WH.Width1-WH.Width2);|11: inc(y);|34: until (y>WH.Height1-WH.Height2);|21: Result.found:=true;|4:end;|0:|35:procedure THiAsmClass.doFindBitmap;|3:var|24: Bmp, subbmp:PBitmap;|21: FindResult: FRes;|21: buf1, buf2: TBuf;|12: WH: WH2;|16: dt,di:TData;|89: mError : Integer; //Минимальная ошибка совпадения от 0 до 100 (0 - полное совпадение)|5:begin|36: Bmp := ReadBitmap(_Data,Bitmap);|42: if (Bmp = nil) or Bmp.Empty then exit;|42: subbmp := ReadBitmap(_Data,subBitmap);|48: if (subbmp = nil) or subbmp.Empty then exit;|73: if (Bmp.Width<subbmp.Width) or (Bmp.Height<subbmp.Height) then exit;|4: |43: mError := ReadInteger(_Data, minError);|4: |25: buf1 := LoagIMG(Bmp);|25: WH.Width1:=Bmp.Width;|27: WH.Height1:=Bmp.Height;|15: //Bmp.Free;|4: |28: buf2 := LoagIMG(subbmp);|28: WH.Width2:=subbmp.Width;|30: WH.Height2:=subbmp.Height;|22: //subbmp.Free; |4: |51: FindResult:=CompareIMG(buf1, buf2, WH, mError);|4: |15: dtNull(dt);|15: dtNull(di);|34: if FindResult.found then begin|57: dtInteger(dt,FindResult.x);//+(WH.width2 div 2));|58: dtInteger(di,FindResult.y);//+(WH.height2 div 2));|24: dt.ldata := @di;|34: _hi_onEvent(onResult, dt);|50: _hi_onEvent(SumError, FindResult.percent);|40: //_hi_onEvent(SumError, mError);|8: end;|4:end;|4:end.| link(onResult,12533344:doEvent1,[]) link(Bitmap,16257815:Var1,[(391,159)]) link(subBitmap,5758247:ImageBitmap,[(398,222)(510,222)(510,264)(545,264)]) link(minError,13965698:String,[(405,208)(524,208)]) } Add(ComboBox,13965698,511,133) { Left=20 Top=40 Height=21 Strings=#1:0|1:1|1:2|1:3|1:4|1:5|1:6|1:7|1:8|1:9|3:100|0:| Text="0" DataType=1 ReadOnly=0 }
Но если ты хочешь искать по определённым признакам, то ты должен их сформулировать - в чём и заключается работа всех программистов! - это искусство! И не важно, что это: похожее лицо в потоке, фраза музыки, или литературный плагиат. --- Добавлено в 2020-07-07 21:57:25Продолжение, а то не умещается... Поиск на экране раз. Add(Button,3183747,266,231) { Left=20 Top=20 Caption="Искать" link(onClick,8282293:doStart,[]) } Add(Bitmap,8059100,406,112) { @Hint=#8:Где ищем| AddHint(-21,-26,65,13,@Hint) } Add(DoData,9296008,406,168) { link(onEventData,10552383:doPicture,[]) link(Data,16257815:Var2,[]) } Add(Image,5758247,539,224) { @Hint=#8:Что ищем| Left=120 Top=120 Width=40 Height=40 WinStyle=2 AutoSize=0 ViewStyle=4 Picture=[ZIPD60B000078DA5556D9561BD915ED3CE707F296D77C413E20EFF984ACA0B9464D0833191BF00062B2DD606CA3A94AB30061A0B18D26C0066C26A9541A40129A80D8068CBB57C776A79D7656675FC96175B48EEEBA5575B5F7D9FB9E734B7FF9EBFEEFBF697CFE8CEF9FF0FDE3D7EFEFBEF943E3BEF0F5F96F3F5D91B39EE8596FE2BC2F717E237EDA1FFD47F762E54AB868F2E738FB8EEED12BEAD14BEDC426757F533DB1A199D8D4DEDFE41DA9367FB17DBA680E14F4DE1CEFDB37F80F78FF01E72F1883457DA0C078F39C37C77A65E0B3BEBC7EA6D4B670D4F5F44D5FECBC3FFEAE8F709D5D8BBCB9BA58EB9C2B9BBD19DE99A41E6D69263735131BDA890DD5B7EBDA8997CCC32DCE9134FB72AD817D4BB06404973FCFBBC155D0070EF43E72097C832FCB7BB3B43BC3F872FA60D1F2F8A873F9F43AA1787773F5A22F7A767DF975CFD2517BB80428CE99D23E780521BAC94DEDF8BAFADB17D4E44BCC597BCAE0CE80A8D55F40E8BDFBAC3B6FF01781CF8849DE2BEBFD32EF93594F1A5CAC27CB070AE670ADFDC99B6BB18BFEC4FBDEF8BB1B608CBCB9FEE4B863EED012C8F3424AF7704B737F93816390D3E08234FAD1B651485B02FBE6C081C97740F0853DDAB1ABB36FB3AE3DDE93D6FB32BC47E6BD19CA2D339E2CE3CF9967AB9D4BAFAFC5CE7B1317FDF1F3BED82951F45DB563A668816458F7F095F63E4C7BA1BEF75C73F7B976625D3BF98AB125F5AE86FFAE248271EE51B61D9D7D47EBD8E1843D564C716E9958E7966951A20499F1E50D33E5F6C5939EC8DBEBB1B31B702F7EDE1F7BDBB354EF9EAF9803FB4651A6A776E0957AFC054275178A9E137CB78CA0DD12617125693149DB7728C72EE5DA659CBB8C98E2BD300D0B644A4C53A2CCF90E8C33E52B8B27579F9DF6C641849238EB7DF6F6DAD249D77CC512DAE7450944F04AF3ED0B82EFC9D0BE2CE3931B44694A9018570AB03A2728F62047E36C7089295694184F1AEB41A41532284243A8D4367FD4FDF46D6FEC7D5FFCA22F7ED61F39ED5D3A69877581BCC9936EE40FABD394472644A0F066582489B990A25C49AD2BA971EEE91CBBB47357E720068214696083886A41D60A69AD887A285AE66A9D4B27D72367FDF18BFE18FAE8B4E7C909C11700986108788616D38C47E6480965C8E8CD420E6E52D844A8B0EF30F0CDB6ADB36D634E0BF03365C4CAA6C382AC13B3ACFFC014AE763E412B5DDC5879077CDA956505129C90635D589C65C182EDF0910C8928729941D132429A7649942B453B93B483541D3DB5053A6C136A8F1325D603168926C9EC3162C6102C019FF31EB0628E1173BC33C33A64C6217382AC872241E6D174A2CC886998C6340CC42514E95CB02ECD3853B43D097CCA411469A7B6B4A4C85328458C2C921124E09B67AA0853A86C4047BBF7F5428E7165696786B1A739478675C92C761CBD20A4C9E89675420A7218779616B14719DA2951F65D688163C4B4A92D9D8D88C21DAE816F9AAD9B666B96F091257C6C99A999A72B7A5F89F31639310F2E0EA29C32583807C634E112538C90E23CE042B191BA259E346DB1EF32533B8C6D87826FE4607C057C7DA8649C3E34872A084BB8DE3A5B6B0D1F99C275D374C5182C1BC1E53E0017EBCC32CE3444310E84C44197287162B3AA256C318286390E89B6A7903C5868DB16D95F62290E841CFC31E2180C964CA18A098ECD56DBE68E2C73C7A6E91A2E8D81B2317068F01659C295010BD185D1251158E822D2245E206229679AC64968DB053EEFC9EB9A25E1440765F5DEBCD15F44E8C1153A344C97506F1D4F8EBB96DF5C8B9C767C77027683AFA8F714788110913D020B44B950C612EB4C312E0891692782F4D7D5C5A3EE85FA95D992C9871295184284DD44B5E45AE70FADEBE753B98F62E5B378F8F3D4FE87F1E40FB737CE6EAD9E772CD48CA18AD1736870970C428173E4396716E5C73A329C931888407B92FE7AB8D3EACD764E977A166A3D0BF58E70D980B78F98A15C52CFD36357E18BAFFAD95FFB97AFFA93B7F22974FC2570F2ABEFE8D709E9A3395C37CFD4CDA1BAD15735FACA064F8915F639679E736439478E475B8919E0AB8657D5A36B8ABB6B9AC9970621DD162C5C5DA8753DAE763EAE5C992BF645EBF6FC474FF9274FF993EBE0477BF67BD7FE8F984CE53F752D9F1A67ABC6E9AA79B66E9939699D3E32FA2B066F85174A9CABC0D873B4839CCF9A9135F5F02A5814645C518DADA8C7D7F1E2B3F8F35D7395F6F9CACDC46B7BEE83A7F4C95DFAE8C87EFF487AEFC8FDF3DECEFB2B4B752E80B76D491F281B021543B0664484EAA6C684872237E95FCDE873E06B479F6BC75E6847D7B463ABAA11B0AC2AC656B5E31BF4D4EECDC8B1B7FC4BE8F8DF33AF11FF09D43FFB2B3F3F903FB42F5429B4187C70E7F5DE03DE5334F8CB467FD514AC9882554214AA031F98AAA115927933FFE1B86674453D92688E7F1F8A691F6CDCD93873173F07EABF90A87D110A9FEF6CFFD03A5BE03C59CA9ED2D9249A34050E961C4E00A3B760F01D1AFC95D6608DE43FB60A1CD5700CA37A7445F9FFF8AA9184F2EE9AC99DEE5DACF42E956FC58E7B9F55DA42797330DFF1B8D2335FEF0A972DF8E78093135507221BCE2519270C873F129E02F0096C232E012F25A886A3EAD184626405BC8AB10442756745311A6F198EC13DE5BD3506B5E7C13695BB1F1FB7876BAD81A241CCD17689B225695B8AB6490D7CE289C21A6DC2FE061C13A248359C203112472887E278048D78AA1E4E2886627FB3465A4612D4E4B649C874864A57672B5DE16A5BE8D0E8CEA1059AF8CAA1D8256C3360976634FE55144C231B14C3B246A5C5900CE64A6B4239140505E1B5AE28AC71E5485C33BECEBB5270AC3B8CF77EAD51FF71B27828D6CCB9C9D564C15C3314D72267FC7C30813220985632C1A5BA1158A01A8CAAAD312C530E465503D196DBCF5A00389AD04DBE6CE25F86F27FB93529909B9A80C7D4563C051DA012AAC1B87A68453D0470721F0B54580F0AB21823F11008C069B14609FE10711263730B94C0B7C62EE9B05E717B193F5758230467A08189188C2907224D6A05600917B983945A06238052347088FF7804F64640AC069E58570863D32B6BF4F2870DFC88726099C46004E9A9F0A801A51A882B07628A5BD1164C06E3CADB50146F1920F8FF05B9670808] Point(doTop) Point(doLeft) Point(onMouseDown) Point(Handle) link(onMouseDown,16176673:doMove,[]) AddHint(35,-30,66,13,@Hint) } Add(MoveWindow,16176673,588,231) { link(Handle,5758247:Handle,[(594,222)(580,222)(580,264)(552,264)]) } Add(MT_Part,9384028,469,238) { link(onSplit,5758247:doTop,[]) link(onPart,5758247:doLeft,[]) } Add(GetDataEx,16257815,406,154) { link(Data,8059100:Bitmap,[]) } Add(TimeCounter,8282293,329,231) { link(onStart,2366711:doFindBitmap,[]) link(onStop,6823186:doString,[(375,244)(375,293)]) } Add(Label,15385577,434,287) { Left=85 Top=20 Width=4 Height=4 Caption="" } Add(FormatStr,6823186,385,287) { DataCount=1 Mask="Время поиска - %1 Millisecond" link(onFString,15385577:doText,[]) } Add(Hub,12533344,434,231) { link(onEvent1,8282293:doStop,[(459,237)(459,272)(319,272)(319,244)]) link(onEvent2,9384028:doSplit,[]) } Add(MainForm,10552383,455,140) { Width=325 Height=230 WindowsState=2 Position=1 Point(onChar) Point(doPicture) link(onCreate,9296008:doData,[(494,160)(494,188)(396,188)(396,174)]) } Add(InlineCode,2366711,385,231) { WorkPoints=#12:doFindBitmap| EventPoints=#8:onResult|8:SumError| DataPoints=#6:Bitmap|9:subBitmap|8:minError| Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses Windows,kol,Share,Debug;|0:|4:type|40: TByteArray = array [0..32767] of Byte;|27: PByteArray = ^TByteArray;|35: TBuf = array of array of integer;|15: FRes = record|19: found: boolean;|17: x,y: integer;|17: percent:real;|6: end;|14: WH2 = record|43: Width1,Height1,Width2,Height2: integer;|6: end;|2: |28: THiAsmClass = class(TDebug)|10: private|0:|9: public|12: Bitmap,|15: subBitmap,|45: onResult, SumError, minError: THI_Event;|57: procedure doFindBitmap(var _Data:TData; Index:word);|81: function CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2; mError:Integer): FRes;|5: end;|0:|14:implementation|0:|40:function LoagIMG(var Bmp:PBitmap) :TBuf;|3:var|15: x,y: integer;|16: p: pByteArray;|15: buffer: TBuf;|5:begin|36: Bmp.PixelFormat:=pf24Bit;//pf8Bit;|45: SetLength(buffer, Bmp.Height, Bmp.Width*3);|35: for y:=0 to Bmp.Height-1 do begin|23: p:=Bmp.ScanLine[y];|38: for x:=0 to Bmp.Width*3-1 do begin|24: buffer[y,x]:=p[x];|8: end;|6: end;|19: Result := buffer;|4:end;|0:|88:function THiAsmClass.CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2; mError:Integer): FRes;|3:var|36: y, x, yy, xx, err, color: integer;|32: sumerr, sum, pmError: LongInt;|5:begin|54: //максимальная ошибка = в диапазоне 0-726 на пиксель|54: pmError:=round(726*WH.Width2*WH.Height2*mError/100);|23: //sum:=High(LongInt);|17: sum:=pmError+1;|22: Result.found:=false;|20: Result.percent:=0;|7: y:=0;|8: repeat|9: x:=0;|10: repeat|25: Result.found:=true;|16: sumerr:=0;|12: yy:=0;|12: repeat|14: xx:=0;|14: repeat|38: for color:=0 to 2 do begin|67: sumerr:=sumerr+abs(buf1[y+yy, x+xx] - buf2[yy,xx]);|24: inc(xx);|16: end;|53: if sumerr>sum then Result.found:=false; |52: until (xx>=WH.Width2) or (Not Result.found);|16: inc(yy);|51: until (yy>=WH.Height2) or (Not Result.found);|30: if sumerr<sum then begin|21: sum:=sumerr;|27: Result.x:=x div 3;|21: Result.y:=y;|60: Result.percent:= sumerr/(726*WH.Width2*WH.Height2);|10: end;|13: inc(x);|34: until (x>WH.Width1-WH.Width2);|11: inc(y);|34: until (y>WH.Height1-WH.Height2);|21: Result.found:=true;|4:end;|0:|35:procedure THiAsmClass.doFindBitmap;|3:var|24: Bmp, subbmp:PBitmap;|21: FindResult: FRes;|21: buf1, buf2: TBuf;|12: WH: WH2;|16: dt,di:TData;|89: mError : Integer; //Минимальная ошибка совпадения от 0 до 100 (0 - полное совпадение)|5:begin|36: Bmp := ReadBitmap(_Data,Bitmap);|42: if (Bmp = nil) or Bmp.Empty then exit;|42: subbmp := ReadBitmap(_Data,subBitmap);|48: if (subbmp = nil) or subbmp.Empty then exit;|73: if (Bmp.Width<subbmp.Width) or (Bmp.Height<subbmp.Height) then exit;|4: |43: mError := ReadInteger(_Data, minError);|4: |25: buf1 := LoagIMG(Bmp);|25: WH.Width1:=Bmp.Width;|27: WH.Height1:=Bmp.Height;|15: //Bmp.Free;|4: |28: buf2 := LoagIMG(subbmp);|28: WH.Width2:=subbmp.Width;|30: WH.Height2:=subbmp.Height;|22: //subbmp.Free; |4: |51: FindResult:=CompareIMG(buf1, buf2, WH, mError);|4: |15: dtNull(dt);|15: dtNull(di);|34: if FindResult.found then begin|57: dtInteger(dt,FindResult.x);//+(WH.width2 div 2));|58: dtInteger(di,FindResult.y);//+(WH.height2 div 2));|24: dt.ldata := @di;|34: _hi_onEvent(onResult, dt);|50: _hi_onEvent(SumError, FindResult.percent);|40: //_hi_onEvent(SumError, mError);|8: end;|4:end;|4:end.| link(onResult,12533344:doEvent1,[]) link(Bitmap,16257815:Var1,[(391,159)]) link(subBitmap,5758247:ImageBitmap,[(398,222)(510,222)(510,264)(545,264)]) link(minError,13965698:String,[(405,208)(524,208)]) } Add(ComboBox,13965698,511,133) { Left=20 Top=40 Height=21 Strings=#1:0|1:1|1:2|1:3|1:4|1:5|1:6|1:7|1:8|1:9|3:100|0:| Text="0" DataType=1 ReadOnly=0 }
Поиск на экране два. Add(MainForm,16152671,259,175) { Width=167 Height=115 } Add(Button,3183747,259,77) { Left=15 Top=10 Caption="Find" link(onClick,8272130:doEvent1,[]) } Add(Bitmap,15450061,441,77) { @Hint=#45:Сюда вставляется кусочек, который надо найти!| } Add(InlineCode,15546554,434,126) { WorkPoints=#12:doFindBitmap| EventPoints=#8:onResult|3:dbg| DataPoints=#6:Bitmap|9:subBitmap| Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses Windows,kol,Share,Debug;|0:|4:type|40: TByteArray = array [0..32767] of Byte;|27: PByteArray = ^TByteArray;|35: TBuf = array of array of integer;|15: FRes = record|19: found: boolean;|17: x,y: integer;|6: end;|14: WH2 = record|43: Width1,Height1,Width2,Height2: integer;|6: end;|2: |28: THiAsmClass = class(TDebug)|10: private|0:|9: public|12: Bitmap,|15: subBitmap,|30: onResult, dbg: THI_Event;|57: procedure doFindBitmap(var _Data:TData; Index:word);|65: function CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2): FRes;|5: end;|0:|14:implementation|0:|40:function LoagIMG(var Bmp:PBitmap) :TBuf;|3:var|17: x,y,c: integer;|16: p: pByteArray;|15: buffer: TBuf;|5:begin|36: Bmp.PixelFormat:=pf24Bit;//pf8Bit;|43: SetLength(buffer, Bmp.Height, Bmp.Width);|35: for y:=0 to Bmp.Height-1 do begin|23: p:=Bmp.ScanLine[y];|36: for x:=0 to Bmp.Width-1 do begin|52: c:=((p[x*3+0] shl 8+p[x*3+1]) shl 8)+p[x*3+2];|21: buffer[y,x]:=c;|8: end;|6: end;|19: Result := buffer;|4:end;|0:|72:function THiAsmClass.CompareIMG(var buf1:TBuf; buf2:TBuf; WH:WH2): FRes;|3:var|37: y, x, yy, xx, err, maxerr: integer;|5:begin|56: maxerr:=200; //максимальная ошибка = в диапазоне 0-726|22: Result.found:=false;|7: y:=0;|8: repeat|9: x:=0;|10: repeat|25: Result.found:=true;|12: yy:=0;|12: repeat|14: xx:=0;|14: repeat|55: //Result.found:=buf1[y+yy, x+xx]=buf2[yy,xx];|71: err:=abs(byte(buf1[y+yy, x+xx]) - (buf2[yy,xx] and $0000ff))+|91: abs((buf1[y+yy, x+xx] and $00ff00 shr 8) - (buf2[yy,xx] and $00ff00 shr 8))+|93: abs((buf1[y+yy, x+xx] and $ff0000 shr 16) - (buf2[yy,xx] and $ff0000 shr 16));|49: if err>maxerr then Result.found:=false;|18: inc(xx);|52: until (xx>=WH.Width2) or (Not Result.found);|16: inc(yy);|51: until (yy>=WH.Height2) or (Not Result.found);|13: inc(x);|52: until (x>WH.Width1-WH.Width2) or (Result.found);|11: inc(y);|52: until (y>WH.Height1-WH.Height2) or (Result.found);|28: if Result.found then begin|18: Result.x:=x-1;|18: Result.y:=y-1;|6: end;|4:end;|0:|35:procedure THiAsmClass.doFindBitmap;|3:var|24: Bmp, subbmp:PBitmap;|21: FindResult: FRes;|21: buf1, buf2: TBuf;|12: WH: WH2;|16: dt,di:TData;|5:begin|36: Bmp := ReadBitmap(_Data,Bitmap);|42: if (Bmp = nil) or Bmp.Empty then exit;|42: subbmp := ReadBitmap(_Data,subBitmap);|48: if (subbmp = nil) or subbmp.Empty then exit;|73: if (Bmp.Width<subbmp.Width) or (Bmp.Height<subbmp.Height) then exit;|4: |25: buf1 := LoagIMG(Bmp);|25: WH.Width1:=Bmp.Width;|27: WH.Height1:=Bmp.Height;|15: //Bmp.Free;|4: |28: buf2 := LoagIMG(subbmp);|28: WH.Width2:=subbmp.Width;|30: WH.Height2:=subbmp.Height;|22: //subbmp.Free; |4: |43: FindResult:=CompareIMG(buf1, buf2, WH);|4: |15: dtNull(dt);|15: dtNull(di);|34: if FindResult.found then begin|53: dtInteger(dt,FindResult.x+(WH.width2 div 2));|54: dtInteger(di,FindResult.y+(WH.height2 div 2));|24: dt.ldata := @di;|35: _hi_onEvent(onResult, dt); |8: end;|4:end;|4:end.| link(onResult,1981070:doEvent1,[]) link(Bitmap,5200148:Bitmap,[(440,117)(391,117)]) link(subBitmap,15450061:Bitmap,[]) } Add(TimeCounter,9308098,336,126) { link(onStart,15546554:doFindBitmap,[]) link(onStop,3796541:doStrCat,[(403,139)(403,188)]) } Add(Label,16719776,616,182) { Left=80 Top=10 Width=32 Height=17 Caption=" " } Add(Hub,1981070,483,126) { link(onEvent1,9308098:doStop,[(508,132)(508,174)(326,174)(326,139)]) link(onEvent2,1569587:doSeparateMT,[]) } Add(ScreenShort,4677498,336,77) { link(onCapture,5200148:doLoad,[]) } Add(Bitmap,5200148,385,77) { } Add(Hub,8272130,301,77) { link(onEvent1,4677498:doCapture,[]) link(onEvent2,9308098:doStart,[(326,90)(326,132)]) } Add(Label,2751625,616,259) { Left=10 Top=35 } Add(MouseEvent,14350900,560,210) { } Add(Timer,10241311,511,259) { Interval=100 link(onTimer,2407579:doString,[]) } Add(FormatStr,2407579,560,259) { Mask="Х = %1 | Y = %2" link(onFString,2751625:doText,[]) link(Str1,14350900:MouseX,[]) link(Str2,14350900:MouseY,[]) } Add(MT_MultiData,1569587,525,133) { link(onData1,9203703:doValue,[(564,139)(564,83)]) link(onData2,4171558:doString,[]) } Add(FormatStr,4171558,574,140) { Mask="X=%1 Y=%2" link(onFString,15336817:doText,[]) link(Str1,9203703:Value,[]) } Add(Memory,9203703,574,77) { } Add(Label,15336817,616,140) { Left=10 Top=55 } Add(StrCat,3796541,441,182) { Str2=" мсек" link(onStrCat,16719776:doText,[]) }
sla8a, не ты ли это рисовал? Редактировалось 4 раз(а), последний 2020-07-07 22:28:10
|