Toon posts:

[Delphi] veranderingen op scherm detecteren.

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo allen,

Ik ben al een tijd bezig met een programmatje dat bepaalde veranderingen in een bepaald gedeelte van het scherm detecteerd en hierop een procedure uitvoert. Het probleem is eigenlijk als volgt: In een bepaald gedeelte van mijn scherm heb ik bewegende objecten. Deze objecten hebben allen een vast kenmerk, bv een rode kleurwaarde. Al deze objecten komen langs een bepaald gebied op mijn scherm. Dit gebied houdt ik in de gaten op mijn scherm. hiervoor gebruik ik de onderstaande procedure maar deze is nog steeds niet snel genoeg. Als ik de objecten sneller laat bewegen dan is de onderstaande procedure te langzaam. Heeft iemand een beter idee?

code:
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
function spthread: integer; stdcall
  const
  RectWidth = 290;
  RectHeight = 1;
  RectLeft = 866;
  RectTop = 660;
var
  Bitmap: TBitmap;
  DC: HDC;
  x, w, h, L, t, y, color: Integer;
  PixelPtr: PRGBQuad;
  I: Integer;
 begin
   I := 0;
  Bitmap := TBitmap.Create;
  try
    w := RectWidth;
    h := RectHeight;
    L := RectLeft;
    T := RectTop;
    Bitmap.Width := w;
    Bitmap.Height := h;
    DC := GetDC(0);
    try
      BitBlt(Bitmap.Canvas.Handle, 0, 0, w, h,
             DC, L, T, SRCCOPY);
    finally
      ReleaseDC(0, DC);
    end;
    Bitmap.PixelFormat := pf32Bit;
    for y := 0 to h - 1 do
    begin
      PixelPtr := PRGBQuad(Bitmap.ScanLine[y]);
      for x := 0 to w - 1 do
      begin
        I := I +1;
        Inc(PixelPtr);
        Color := PixelPtr^.rgbRed;
        if Color = 0 then begin Exit; end;
        if Color = 227 then begin SetCursorPos (L+I, T); Exit; end;
        if Color < 50  then begin SetCursorPos (L+I, T); Exit; end;
        if Color = 208 then begin SetCursorPos (L+I+50, T); Exit; end;
      end;
    end;
  finally
    Bitmap.Free;
    end;
  end;

  • whoami
  • Registratie: December 2000
  • Laatst online: 20:31
Waarom laat je je objecten geen melding geven aan het programma als ze van kleur veranderen ipv dat je programma detecteert of iets van kleur veranderd is?

https://fgheysels.github.io/


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 22-08 10:56

Delphi32

Heading for the gates of Eden

Ik sluit me aan bij de opmerking van whoami, maar misschien kan je in je huidige situatie geen color-changed-events implementeren, dus ik kijk ook maar even naar de code. En dan ben ik benieuwd hoeveel sneller je eigenlijk nog wilt worden, want ik zie alleen wat kleine dingetjes die hier en daar een clock-cycle sneller zouden kunnen (en en passant een memleak kunnen voorkomen :)):
Ik ben bang dat de meeste processortijd zit in de nested loop om de bmp te scannen op kleur. Die gaan we dus aanpakken. De regel
Delphi:
1
i := i + 1;
veranderen we in
Delphi:
1
Inc(i)
, dat scheelt alvast 1 instructie per iteratie. Vervolgens maak je van je if-statements een case-statement, want ook dat is iets efficiënter. De exits achter de ifjes moet je weglaten, want je lekt hier 1 Tbitmap per keer dat je procedure voorbij komt, en dat is nogal vaak begreep ik. Teveel lekken vindt geen enkel OS leuk ;) Dus ff iets anders verzinnen om de nested loop te exiten, want op deze manier sla je je finally over.
Ik snap niet helemaal waarom je 4 constanten declareert voor de afmetingen van de bitmap, en die vervolgens in 4 variabelen (w, h, L en T) stopt die verder niet meer wijzigen. Gebruik dan alleen die constanten |:( (misschien moet je er voor de BitBlt functie dan typed consts van maken).
Al met al zijn er een paar kleine performance-winstjes te halen, maar ik zou zeker kijken of een event-based methode niet veel handiger is.

Verwijderd

Topicstarter
whoami schreef op 17 april 2003 @ 23:42:
Waarom laat je je objecten geen melding geven aan het programma als ze van kleur veranderen ipv dat je programma detecteert of iets van kleur veranderd is?
Ja, ik weet dat die manier sneller is, maar dit alles speelt zich af binnen een flash movie. Ik heb geen idee hoe ik dit zou moeten doen.

Verwijderd

Topicstarter
Delphi32 schreef op 18 April 2003 @ 00:43:
Ik sluit me aan bij de opmerking van whoami, maar misschien kan je in je huidige situatie geen color-changed-events implementeren, dus ik kijk ook maar even naar de code. En dan ben ik benieuwd hoeveel sneller je eigenlijk nog wilt worden, want ik zie alleen wat kleine dingetjes die hier en daar een clock-cycle sneller zouden kunnen (en en passant een memleak kunnen voorkomen :)):
Ik ben bang dat de meeste processortijd zit in de nested loop om de bmp te scannen op kleur. Die gaan we dus aanpakken. De regel
Delphi:
1
i := i + 1;
veranderen we in
Delphi:
1
Inc(i)
, dat scheelt alvast 1 instructie per iteratie. Vervolgens maak je van je if-statements een case-statement, want ook dat is iets efficiënter. De exits achter de ifjes moet je weglaten, want je lekt hier 1 Tbitmap per keer dat je procedure voorbij komt, en dat is nogal vaak begreep ik. Teveel lekken vindt geen enkel OS leuk ;) Dus ff iets anders verzinnen om de nested loop te exiten, want op deze manier sla je je finally over.
Ik snap niet helemaal waarom je 4 constanten declareert voor de afmetingen van de bitmap, en die vervolgens in 4 variabelen (w, h, L en T) stopt die verder niet meer wijzigen. Gebruik dan alleen die constanten |:( (misschien moet je er voor de BitBlt functie dan typed consts van maken).
Al met al zijn er een paar kleine performance-winstjes te halen, maar ik zou zeker kijken of een event-based methode niet veel handiger is.
Bedankt voor al deze info. Ik ga het allemaal ffe veranderen en kijken of het misschien toch dat kleine verschil maakt dat ik nodig heb.

  • Mir
  • Registratie: Maart 2001
  • Niet online

Mir

Het voordeel van constanten is natuurlijk dat het niet meer uit je geheugen gelezen hoeft te worden (tenm, niet dmv 'pointen')

Verwijderd

Topicstarter
Mensen,

Ik bedenk me net dat bitblt door mijn videokaart wordt uitgevoerd. Zou het niet mogelijk zijn dat mijn Videokaart gewoon te traag is. Ik heb een MX440.

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 16:05

Reptile209

- gers -

Je zou de bitmap global kunnen maken: dat scheelt je een create en een free per ronde. Wel ff opletten dat hij uiteindelijk wel wordt gereleased!

edit:

Ik weet niet wat de overhead van een try-finally is, maar de buitenste voegt iig niet zo heel veel toe volgens mij. Die zou je er dan dus uit kunnen laten. Ik weet niet hoe kwetsbaar de BitBlt() is, maar misschien kan die er dan ook nog uit.

[ Voor 48% gewijzigd door Reptile209 op 18-04-2003 13:50 ]

Zo scherp als een voetbal!


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
De exits achter de ifjes moet je weglaten, want je lekt hier 1 Tbitmap per keer dat je procedure voorbij komt, en dat is nogal vaak begreep ik.
Je hebt zeker de try / finally over het hoofd gezien? Die TBitmap leakt niet hoor.
De regel
Delphi:
1
i := i + 1;
veranderen we in
Delphi:
1
Inc(i)
, dat scheelt alvast 1 instructie per iteratie.
Nee hoor. Maakt niks uit. Dezelfde asm code wordt gegeneerd.

[ Voor 31% gewijzigd door martijn_brinkers op 18-04-2003 14:51 ]


  • FendtVario
  • Registratie: Januari 2002
  • Laatst online: 12-05-2025

FendtVario

The leader drives Vario!

TijnFLiP schreef op 18 April 2003 @ 13:52:

Nee hoor. Maakt niks uit. Dezelfde asm code wordt gegeneerd.
Uit de Delphi help file:
X increments by 1, or by N if N is specified; that is, Inc(X) corresponds to the statement X := X + 1, and Inc(X, N) corresponds to the statement X := X + N. However, Inc generates optimized code and is especially useful in tight loops.

:Y)

www.fendt.com | Nikon D7100 | PS5


Verwijderd

Topicstarter
Delphi32 schreef op 18 april 2003 @ 00:43:
Ik sluit me aan bij de opmerking van whoami, maar misschien kan je in je huidige situatie geen color-changed-events implementeren, dus ik kijk ook maar even naar de code. En dan ben ik benieuwd hoeveel sneller je eigenlijk nog wilt worden, want ik zie alleen wat kleine dingetjes die hier en daar een clock-cycle sneller zouden kunnen (en en passant een memleak kunnen voorkomen :)):
Ik ben bang dat de meeste processortijd zit in de nested loop om de bmp te scannen op kleur. Die gaan we dus aanpakken. De regel
Delphi:
1
i := i + 1;
veranderen we in
Delphi:
1
Inc(i)
, dat scheelt alvast 1 instructie per iteratie. Vervolgens maak je van je if-statements een case-statement, want ook dat is iets efficiënter. De exits achter de ifjes moet je weglaten, want je lekt hier 1 Tbitmap per keer dat je procedure voorbij komt, en dat is nogal vaak begreep ik. Teveel lekken vindt geen enkel OS leuk ;) Dus ff iets anders verzinnen om de nested loop te exiten, want op deze manier sla je je finally over.
Ik snap niet helemaal waarom je 4 constanten declareert voor de afmetingen van de bitmap, en die vervolgens in 4 variabelen (w, h, L en T) stopt die verder niet meer wijzigen. Gebruik dan alleen die constanten |:( (misschien moet je er voor de BitBlt functie dan typed consts van maken).
Al met al zijn er een paar kleine performance-winstjes te halen, maar ik zou zeker kijken of een event-based methode niet veel handiger is.
Ik heb de veranderingen doorgevoerd. Mijn app houdt het nu allemaal iets langer vol, maar helaas nog niet lang genoeg. Ik moet toch maar met color-change-events gaan werken. Ik heb alleen geen flauw idee hoe dit werkt, iemand suggesties?

  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Uit de Delphi help file:
X increments by 1, or by N if N is specified; that is, Inc(X) corresponds to the statement X := X + 1, and Inc(X, N) corresponds to the statement X := X + N. However, Inc generates optimized code and is especially useful in tight loops.
Als je kijkt naar de asm code die wordt gegeneerd is het toch echt exact gelijk, althans bij D7. Kan zijn dat ze dat nu geoptimaliseerd hebben naar Inc (is natuurlijk niet echt moeilijk).

Ik heb even een snelheids testje gedaan. En als je TBimap 1 keer creeerd zoals Reptile209 voorstelde datn scheelt dat zo ongeveer een factor 3. Dus ipv 300000 clock cycles kost het 'nog maar' 100000 clock cycles :)

hiermee kan je de clock timestamp opvragen. Je kan zodoende tellen hoveel clock cycles er zijn geweest zodat je precies kan pinpointen waar de meeste tijd verloren gaat.

Delphi:
1
2
3
4
function ReadTimeStampCounter: Int64; assembler;
asm
        DW      $310F
end;


Uit een test lijkt het erop dat eigenlijk alle tijd gaat zitten in

Delphi:
1
2
3
4
5
6
7
    DC := GetDC(0);
    try
      BitBlt(Bitmap.Canvas.Handle, 0, 0, w, h,
             DC, L, T, SRCCOPY);
    finally
      ReleaseDC(0, DC);
    end;


Ik denk dus niet dat je dat makkelijk kan versnellen.

[ Voor 33% gewijzigd door martijn_brinkers op 18-04-2003 15:51 ]


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Eigenlijk is BitBlt overbodig denk ik. Je kan ook een TCanvas globaal aanmaken en dan

Delphi:
1
      Canvas.Handle := DC;


Dat lijkt een stuk sneller te gaan.

Hmmm toch niet. Want je moet alsnog met een Bitmap gaan werken :(

[ Voor 17% gewijzigd door martijn_brinkers op 18-04-2003 15:56 ]


Verwijderd

Als je de source van die flash movie hebt, kun je de in de actionscript code met FSCommand messages sturen naar het programma waarin de flash movie wordt gespeeld.
Hier staat het een en ander over het importeren van Falsh in Delphi:
http://www.delphipages.com/news/detaildocs.cfm?ID=38

Ik hoop dat je er wat aan hebt

  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 22-08 10:56

Delphi32

Heading for the gates of Eden

TijnFLiP schreef op 18 April 2003 @ 13:52:
Je hebt zeker de try / finally over het hoofd gezien? Die TBitmap leakt niet hoor.
Nee, die had ik niet over het hoofd gezien. Uit de Delphi help, die ik er voor de zekerheid had bijgepakt:
The Exit procedure immediately passes control away from the current procedure. If the current procedure is the main program, Exit causes the program to terminate.

Exit will cause the calling procedure to continue with the statement after the point at which the procedure was called.

Mijn conclusie was (na het lezen van dit stukje) dat na een Exit de Finally niet meer wordt uitgevoerd.
Ach ik lees nu toch het volgende (in de help over try..finally):
If a call to the Exit, Break, or Continue procedure causes control to leave statementList1, statementList2 is automatically executed. Thus the finally clause is always executed, regardless of how the try clause terminates.

Dus heb je helemaal gelijk: er is geen lek. Gelukkig maar :)
Pagina: 1