Entwickler-Ecke
Multimedia / Grafik - optimierung gesucht BitMap
ALF - Fr 03.09.10 17:41
Titel: optimierung gesucht BitMap
Gibt es für diesen Code evtl noch ne bessere Möglichkeit? Bei einer grossen Fläsche hat er ganz schön zu Zeichen/zu rechnen!
Was dann natürlich zu
leichten Verzögerungen führt. Im Prinzip könnte man damit leben. Man vergrössert ja nicht ständig die Fläche auf 2600x1024 :wink: Es könnte aber sein das es besser geht!?
Die beiden Variablen peakbufl/peakbufr sind Bitmaps.
DoubleBuffered für die beiden Painboxen ist auch schon an.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| for ypos:= 0 to peakbufr.Width do begin peakbufl.Canvas.Pen.Color:= RGB( Trunc(102+ (255 - 102) / peakbufl.Height *ypos) , Trunc(113+ (255 - 113) / peakbufl.Height *ypos) , Trunc(126+ (255 - 126) / peakbufl.Height *ypos) ); peakbufl.Canvas.MoveTo(0, ypos); peakbufl.Canvas.LineTo(peakbufl.Width, ypos); peakbufr.Canvas.Pen.Color:= RGB( Trunc(102+ (255 - 102) / peakbufr.Height *ypos) , Trunc(113+ (255 - 113) / peakbufr.Height *ypos) , Trunc(126+ (255 - 126) / peakbufr.Height *ypos) ); peakbufr.Canvas.MoveTo(0, peakbufr.Height - ypos); peakbufr.Canvas.LineTo(peakbufr.Width, peakbufr.Height - ypos); end; |
Währe schon, wenn es dafür was optimaleres gäbe.
Gruss Alf
platzwart - Fr 03.09.10 20:27
Generell kann ich in Sachen Bitmaps nur die Graphics32 empfehlen. Ob die bei den Zeichenroutinen auch schnell wie beim Pixelzugriff sind, weiß ich nicht.
BenBE - Sa 04.09.10 16:59
Externes Bitmap erzeugen; dadrin zeichnen mit ScanLine; Backbuffer mit BitBlt auf's Front-Bitmap schieben.
ALF - Sa 04.09.10 22:03
BenBE hat folgendes geschrieben : |
Externes Bitmap erzeugen; |
was meinst Du mit extern :nixweiss:
Delphi-Quelltext
1: 2:
| peakbufl:= TBitMap.Create; peakbufr:= TBitMap.Create; |
sind doch meine BitMap!?
BenBE hat folgendes geschrieben : |
dadrin zeichnen mit ScanLine; |
ist Scanline schneller als Canvas?
BenBE hat folgendes geschrieben : |
Backbuffer mit BitBlt auf's Front-Bitmap schieben. |
Sorry, stell mich da echt blöd an, mit den Stichwörtern :oops:
Gruss Alf
BenBE - Sa 04.09.10 22:08
Such einfach mal hier im Forum nach
SCANLINE, da findet sich genug ;-)
Edit: Ach ja, glatt vergessen:
ALF hat folgendes geschrieben : |
BenBE hat folgendes geschrieben : | dadrin zeichnen mit ScanLine; | ist Scanline schneller als Canvas? |
Ja.
Wobei die Frage so nicht ganz stimmt, weil Scanline nur ein Teil der TCanvas-Klasse ist. Insgesamt hängt da eine etwas andere Vorgehensweise dran. Von daher ist das mit dem Ja nur für den Fall, dass man weiß, was man tut ;-)
Flamefire - Sa 04.09.10 22:14
extern heißt: du hast ein canvas auf dem formular, was sichtbar ist und tbitmap, was nicht sichtbar ist.
dann zeichnest du auf das bitmap und danach kopierst du das per bitblt auf die canvas auf dem form.
und scanline verwenden da schneller als moveto/lineto
BTW: Du hast ein haufen multiplikationen und divisionen in der schleife.
1) "ypos" dürfte ein fehler sein, oder? weil du teils durch die höhe aber ypos läuft durch die breite...
da solltest du nochmal gucken. besonders der fall, dass das canvas breiter als hoch ist. dann kommst du mit moveto(0,ypos) nämlich außerhalb an...
vermutlich in der for-schleife ein "to peakbufr.width"
2) überleg mal, ob du lookup tabellen verwenden kannst (also die farb-werte schon vorberechnen)
3) ansonsten die farbe nur 1 mal ausrechnen. nicht für beide canvas getrennt.
ALF - Sa 04.09.10 22:22
mh... jetzt muss ich das erst mal alles verstehen :wink: Bin nicht so schnell wie ihr :lol:
im Anhang mal die Fläsche die ich zeichne!
Werd mich mal daran machen, erst mal Danke
Edit: Verstanden hab ich erst mal gar nicht, aber erst mal schauen was ihr damit so meint!
Gruss ALf
oops, das sollte gar nicht so gross sein :gruebel:
BenBE - Sa 04.09.10 22:43
Wenn das so ist ... dann würde ich auch zu Lookup-Tabelle für die Farben raten und zusätzlich die Farbwerte mit ner optimierten Move-Methode (12 Bytes schreiben + Rest durch Bereichsüberlappung kopieren). Bearbeitung des Bitmaps erfolgt dadurch via ScanLine zeilenweise.
ALF - Sa 04.09.10 23:35
befor ich mich jetzt dusslig suche!
Scanline ist mir bekannt.
BenBE hat folgendes geschrieben : |
Von daher ist das mit dem Ja nur für den Fall, dass man weiß, was man tut ;-) |
keine Ahnung was Du damit sagen willst?
Flamefire hat folgendes geschrieben : |
extern heißt: du hast ein canvas auf dem formular, was sichtbar ist |
Ist das meine Paintbox wo ich dann später, die Bitmaps reinkopierer. Oder ist das was ganz anderes?
Flamefire hat folgendes geschrieben : |
und tbitmap, was nicht sichtbar ist.
dann zeichnest du auf das bitmap |
das sind doch meine peakbufl,peakbufr oder nicht?
Flamefire hat folgendes geschrieben : |
und danach kopierst du das per bitblt auf die canvas auf dem form. |
Delphi-Quelltext
1: 2:
| leftcannelpb.Canvas.Draw(0, 0, peakbufl);rightcannelpb.Canvas.Draw(0, 0, peakbufr); |
mach ich doch schon oder ist das auch verkehrt oder was soll der Begriff "bitblt" bedeuten?
Sorry also für das Nachfragen, falls ich die gängigen Begriffe noch nicht ganz verstanden habe.
Gruss ALf
delfiphan - So 05.09.10 00:19
Oder du nutzst OpenGL/DirectX. Kriegste auch gleich Kantenglättung, wenn du willst.
ALF - So 05.09.10 00:41
jooo Danke BITBLT gibts nen schönes Beispiel bei
DF [
http://forum.delphi-treff.de/showthread.php?24461] hätt ja selber drauf kommen können(Dusel ich :autsch: )habe ich ja auch noch vor kurzen gelesen mhh....
Danke @delfiphan , ist mir als gelegenheits proger zu heiss!
Kann nur stunden weise an meinem progi sitzen :cry:
Mach mich mal an @BenBE + @Flamefire Ideen run 8)
Flamefire hat folgendes geschrieben : |
3) ansonsten die farbe nur 1 mal ausrechnen. nicht für beide canvas getrennt. |
und evtl spiegelverkehrt auf die zweite raufkopieren :wink:
Danke :D
Gruss Alf
ALF - So 05.09.10 13:02
Sorry wenn ich pushen tu :flehan:
Habe das ganze nun mit Scanline gemacht und BitBlt. Ok kein Problem :D
Frage, gibt es nun ne Möglichkeit, das ich für die 2.bitmap die Farben irgendwie invertiere, so das ich nur einmal die Schleife habe?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| for ypos:= 0 to peakbufr.Height-1 do begin r:= trunc(102+ (255 - 102) / peakbufl.Height *ypos); g:= trunc(113+ (255 - 113) / peakbufl.Height *ypos); b:= trunc(126+ (255 - 126) / peakbufl.Height *ypos); pl:= peakbufl.ScanLine[ypos]; pr:= peakbufr.ScanLine[ypos]; for x:= 0 to peakbufl.Width-1 do begin pl.rgbRed:= r; pl.rgbGreen:= g; pl.rgbBlue:= b; pr.rgbRed:= r; pr.rgbGreen:= g; pr.rgbBlue:= b; inc(pl); inc(pr); end; end; |
habe mit xor, and, or, shr shl experimentiert. War klar das es nicht so geht, hätt ja sein können mhh..
Gruss Alf
delfiphan - So 05.09.10 13:11
Btw. Du kannst mit einem einzigen Scanline Aufruf auf das gesamte Bitmap zugreifen. Musst einfach auf die Ränder aufpassen, und ob die Bitmap verkehrt rum im Speicher liegt.
Flamefire - So 05.09.10 13:11
was meinst du mit invertieren? ist bei deinem ocde nirgends was zu sehen, wo du das mal gemacht hast.
PS: wenn du vor der x-schleife das rgb-tupel erstellst und dann im ganzen zuweist, ist es nochmal eins stück schneller.
und scanline brauchst du nur einmal vor der ypos schleife.
platzwart - So 05.09.10 13:17
Ich kann mich nur wiederholen: Graphics32 + Scanline = extremer Perfomanceboost...
elundril - So 05.09.10 13:40
Fang doch beim unteren Bitmap einfach von unten zu zeichnen an. Dann musst du nix invertieren sondern einfach nur beim zeichnen Y-Pos minus aktuelle Zeile rechnen.
ALF - So 05.09.10 13:49
platzwart hat folgendes geschrieben : |
Ich kann mich nur wiederholen: Graphics32 + Scanline = extremer Perfomanceboost... |
Ja ich weis, aber wenn ich irgendwann mal das Progi hier public machen sollte(incl Source) :mrgreen: , dann müssen andere das auch drin haben!
delfiphan hat folgendes geschrieben : |
Btw. Du kannst mit einem einzigen Scanline Aufruf auf das gesamte Bitmap zugreifen. Musst einfach auf die Ränder aufpassen, und ob die Bitmap verkehrt rum im Speicher liegt. |
:nixweiss:
Flamefire hat folgendes geschrieben : |
PS: wenn du vor der x-schleife das rgb-tupel erstellst und dann im ganzen zuweist, ist es nochmal eins stück schneller. |
mh...?
Flamefire hat folgendes geschrieben : |
und scanline brauchst du nur einmal vor der ypos schleife. |
und wie gebe pl/pr die neue position an?
Flamefire hat folgendes geschrieben : |
was meinst du mit invertieren? ist bei deinem ocde nirgends was zu sehen, wo du das mal gemacht hast. |
Delphi-Quelltext
1:
| pr.rgbRed:= pl.rgbRed xor r; |
elundril hat folgendes geschrieben : |
Fang doch beim unteren Bitmap einfach von unten zu zeichnen an. Dann musst du nix invertieren sondern einfach nur beim zeichnen Y-Pos minus aktuelle Zeile rechnen. |
:zustimm: jo hab ich gleich umgesetzt!
(wie immer Blind)
Delphi-Quelltext
1:
| pr:= peakbufr.ScanLine[(peakbufr.Height-1) - ypos]; |
Sorry für die vielen offenen Fragen auf eure Antworten.
Gruss Alf
BenBE - So 05.09.10 14:09
Deine innere Schleife brauchst Du nicht mal:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| r := ...; g := ...; b := ...;
pl.r := r; pl.g := g; pl.b := b; w := peakbufl.Width; pl2 := pl; inc(pl2); Move ( pl, pl2, SizeOf(PixelRGB) * (w - 1) ); Move ( pl, pr, SizeOf(PixelRGB) * w ); |
Flamefire - So 05.09.10 14:20
sicher, dass das funktioniert?
a) ist es nicht sehr leserlich. hab gerade erst verstanden, warum das funktionieren KÖNNTE
b) kann das schief gehen, wenn z.b. die Größen verschieden sind (z.b. der 64Bit register, MMX o.ä. verwendet)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| pl:= peakbufl.ScanLine[0]; pr:= peakbufr.ScanLine[0]; for ypos:= 0 to peakbufr.Height-1 do begin r:= trunc(102+ (255 - 102) / peakbufl.Height *ypos); g:= trunc(113+ (255 - 113) / peakbufl.Height *ypos); b:= trunc(126+ (255 - 126) / peakbufl.Height *ypos); pRGB.rgbRed:=r; pRGB.rgb... for x:= 0 to peakbufl.Width-1 do begin pl:= pRGB; pr:= pRGB inc(pl); inc(pr); end; end; |
So meinte ich das. Mach dir mal klar, wie die bitmap im speicher liegt. scanline ist nix weiter als ein GetPointerAufSpeicher()
was meinst du nun mit invertieren?
da die Farben der unteren Bitmap andersrum sind als oben? Oder das die invertierte Farbe genommen wird?
delfiphan - So 05.09.10 15:07
ALF hat folgendes geschrieben : |
delfiphan hat folgendes geschrieben : | Btw. Du kannst mit einem einzigen Scanline Aufruf auf das gesamte Bitmap zugreifen. Musst einfach auf die Ränder aufpassen, und ob die Bitmap verkehrt rum im Speicher liegt. | :nixweiss: |
1x Scanline für ganzes Bild.
Delphi-Quelltext
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:
| procedure TForm1.Button1Click(Sender: TObject); const N = 256; var X, Y: Integer; Bitmap: TBitmap; Base, Pixel: PCardinal; begin Bitmap := TBitmap.Create; try Bitmap.Width := N; Bitmap.Height := N; Bitmap.PixelFormat := pf32bit; Base := Bitmap.ScanLine[Bitmap.Height - 1];
for X := 0 to N - 1 do for Y := 0 to N - 1 do begin Pixel := Base; Inc(Pixel, X + Y * N); Pixel^ := Integer((X and Y) > 0) * $FFFFFF; end;
Image1.Picture.Bitmap.Assign(Bitmap); finally Bitmap.Free; end; end; |
Flamefire - So 05.09.10 15:33
und wenn du die 2 schleifen tauschst kommst du mit einem Inc(Pixel) aus
dann sparst du dir die multiplikation, da deine variante schon fast langsamer ist, als ein ständiger scanline aufruf.
delfiphan - So 05.09.10 15:35
Mir ging es oben nicht darum, optimierten Code zu zeigen. Das X + Y * N wär überhaupt nicht nötig, da der Pointer bei jedem Durchlauf sowieso nur 4 hochzählt. Ich wollte aber andeuten, dass man eigentlich mit BytesPerScanline arbeiten sollte, wenn man andere Pixelformats verwendet.
Folgendes würde für den Fall oben reichen:
Delphi-Quelltext
1: 2:
| Base^ := Integer((X and Y) > 0) * $FFFFFF; Inc(Base); |
Aber bei mir läuft das sowieso in 0.1ms durch. Da noch weiter zu optimieren wäre reine Zeitverschwendung. Wenn die Performance so wichtig ist, würde ich dann doch auf Hardwarebeschleunigung zurückgreifen, da kriegst du den Gradienten geschenkt.
Flamefire - So 05.09.10 16:09
Und ich wollte drauf hinweisen, dass scanline nicht viel mehr macht, als eine multiplikation und einen speicherzugriff. also soviel wie dein code auch.
dein letzter post stimmt nicht: du müsstest noch die x und y schleife vertauschen.
gut bei nem quadrat ist das egal, aber vom prinzip.
delfiphan - So 05.09.10 16:11
Flamefire hat folgendes geschrieben : |
Und ich wollte drauf hinweisen, dass scanline nicht viel mehr macht, als eine multiplikation und einen speicherzugriff. also soviel wie dein code auch.
dein letzter post stimmt nicht: du müsstest noch die x und y schleife vertauschen.
gut bei nem quadrat ist das egal, aber vom prinzip. |
Richtig, das müsste man noch ändern.
Tilman - So 05.09.10 16:11
Zitat: |
Delphi-Quelltext 1:
| Base := Bitmap.ScanLine[Bitmap.Height - 1]; | |
*mist*e! Habe gerade völlig unabhängig vom TE dieses Problem gehabt (ich will eine Textur in OpenGL laden), und gleichzeitig wird hier die Lösung gepostet! :o
Meine Lösung auf die ich nach längerer Suche gekommen war sah so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var bm: tBitmap; buffer: windows.BITMAP; begin bm := tBitmap.Create; [..] getObject(bm.Handle,sizeof(buffer),@buffer); |
Dazu stellt sich mir die Frage, warum 1. scanline verkehrt herum läuft, und 2. die Funktion nicht gut dokumentiert ist. Denn scanline[0] hatte ich natürlich als erstes probiert :?
Flamefire - So 05.09.10 16:14
ähm...scanline läuft richtig rum:
von 0,0->0,1->0,2...->0,h
deine lösung sollte im zugriff langsamer sein. und vermutlich musst du das auch wieder freigeben. bin nicht ganz sicher.
delfiphan - So 05.09.10 16:15
Wieso, weiss ich nicht genau aber vermutlich war das für gewisse Fälle schneller. Man google nach "bottom-up dib".
Wenn man die Art des Bitmaps nicht genau kennt, sollte man ScanLine verwenden. Es berücksichtigt die Alignment am Rand und bottom-up vs. top-down. Wenn man das Bitmap kennt, kann man sich die Fallunterscheidungen sparen. Ein grosser Geschwindigkeitsunterschied wird das aber tatsächlich nicht machen.
BenBE - So 05.09.10 16:15
Scanline läuft richtig rum; allerdings werden Bitmaps im Speicher von Unten nach Oben abgelegt, daher die umgekehrte Zeilenzählung.
ALF - So 05.09.10 16:17
So ich versuch mal wieder zu Antworten was ich alles gemacht habe!
Bevor
ihr euch die besten Ideen untereinander erklärt :rofl: und ich evtl gar nix mehr verstehe!
@delfiphan: Was mache ich aber mit der StartFarbe. Bei Dir würde es mit schwarz beginnen und in weiss enden. Wenn ich es richtig sehe, und wie dann mit der 2.bitmap. Das OpenGL/DirectX besser sind ist auch mir klar! Nur ist es auch ne Zeit und verstehen frage. Siehst Doch selbst wie lange ich nur für so ein bischen brauche :P
@Flamefire: Deine Funktioniert, nur muss man nicht mit 0 Anfangen sondern mit
Delphi-Quelltext
1:
| pl:= peakbufl.ScanLine[peakbufl.Height-1]; |
und die For schleife dann rückwärts laufen lassen!
So wie es bei Dir steht kommt es zum peng schon nach dem 2. Durchlauf! Getestet :wink:
Jedenfalls bei mir! Allerdings wüsste ich jetzt nicht wie ich in der gleichen Forschleife die 2.bitmap mit der Farbe fülle und zwar entgegengesetzt!
Flamefire hat folgendes geschrieben : |
was meinst du nun mit invertieren?
da die Farben der unteren Bitmap andersrum sind als oben? |
jo das meinte ich!
Bin aber auch an @BenBE Idee dran. Nur muss ich erst mal wieder verstehen was er mit SizeOf(
PixelRGB) meint/hernimmt :?
Anbei weis ich immer noch nicht was man hier evtl noch machen kann!
Delphi-Quelltext
1: 2: 3:
| r:= trunc(102+ (255 - 102) / peakbufl.Height *ypos); g:= trunc(113+ (255 - 113) / peakbufl.Height *ypos); b:= trunc(126+ (255 - 126) / peakbufl.Height *ypos); |
Gruss Alf
Tilman - So 05.09.10 16:20
Okay ihr habt natürlich völlig recht, nur stellt sich um so mehr die Frage warum in meinen Ausgaben der Hilfe (Delphi 7 und Delphi 2006) kein Pieps davon erwähnt wird, das Scanline[height-1] die gesamten Pixeldaten liefert. Hätte mir ne Stunde rumgesuche erspart ^^
delfiphan - So 05.09.10 16:21
Mein Code löst weder das Gescheindigkeitsproblem noch generiert es einen Gradienten. Es zeigt lediglich, dass es reicht, 1x Scanline aufzurufen. ;)
---
Moderiert von
Narses: Beiträge zusammengefasst---
Tilman hat folgendes geschrieben : |
Okay ihr habt natürlich völlig recht, nur stellt sich um so mehr die Frage warum in meinen Ausgaben der Hilfe (Delphi 7 und Delphi 2006) kein Pieps davon erwähnt wird, das Scanline[height-1] die gesamten Pixeldaten liefert. Hätte mir ne Stunde rumgesuche erspart ^^ |
Das muss auch nicht zwingend so sein (du kannst auch theoretisch ein top-bottom dib mit TBitmap betreiben). Das ganze benötigt aber Systemwissen und ist nicht wirklich ein Delphi-Feature, daher auch nicht so dokumentiert, denk ich mal.
// Sorry, Mods, bitte Posts zusammenführen, falls erwünscht.
elundril - So 05.09.10 16:30
ALF hat folgendes geschrieben : |
Anbei weis ich immer noch nicht was man hier evtl noch machen kann!
Delphi-Quelltext 1: 2: 3:
| r:= trunc(102+ (255 - 102) / peakbufl.Height *ypos); g:= trunc(113+ (255 - 113) / peakbufl.Height *ypos); b:= trunc(126+ (255 - 126) / peakbufl.Height *ypos); |
Gruss Alf |
Spart vielleicht nicht viel Zeit aber machts kürzer und schöner:
Delphi-Quelltext
1: 2: 3: 4:
| nenner := peakbufl * ypos; r := trunc(102 + (153 / nenner)); g := trunc(113 + (142 / nenner)); b := trunc(126 + (129 / nenner)); |
lg elundril
Flamefire - So 05.09.10 16:56
Delphi-Quelltext
1: 2: 3:
| r:= trunc(102+ (255 - 102) / peakbufl.Height *ypos); g:= trunc(113+ (255 - 113) / peakbufl.Height *ypos); b:= trunc(126+ (255 - 126) / peakbufl.Height *ypos); |
eher zu:
Delphi-Quelltext
1: 2: 3: 4:
| factor:=ypos/peakbufl.Height; r:= trunc(102+ (255 - 102) *factor); g:= trunc(113+ (255 - 113) *factor); b:= trunc(126+ (255 - 126) *factor); |
möglichkeit wäre noch 3 arrays[0..height] zu erzeugen (bei resize) und dort die werte schon zu berechnen (als fertiger RBG-Wert)
delfiphan - So 05.09.10 16:59
Wenn Geschwindigkeit, dann mit Integers rechnen.
ALF - So 05.09.10 17:02
elundril hat folgendes geschrieben : |
Spart vielleicht nicht viel Zeit aber machts kürzer und schöner:
Delphi-Quelltext 1: 2:
| nenner := peakbufl * ypos; r := trunc(102 + (153 / nenner)); |
|
delfiphan hat folgendes geschrieben : |
Wenn Geschwindigkeit, dann mit Integers rechnen. |
Hab ich schon gemacht funct mit der Farbe nicht!
Gruss ALf
Flamefire - So 05.09.10 17:14
integer gehen wirklich nicht.
und dein fehler kommt vom abschreiben...erst denken ;-)
oder nimm meins. da ist dasschon gefixt
ALF - So 05.09.10 17:19
Flamefire hat folgendes geschrieben : |
und dein fehler kommt vom abschreiben...erst denken ;-) |
hab nicht abgeschrieben, weil ich selbst schon versucht hatte das hübscher zu machen und den gleichen Fehler gemacht habe :P
Gruss Alf
delfiphan - So 05.09.10 17:46
Flamefire hat folgendes geschrieben : |
integer gehen wirklich nicht. |
Du musst einfach zuerst multiplizieren, dann dividieren.
ALF - So 05.09.10 18:48
Bei aller Diskusion wurde vergessen wie ich es machen kann das ich, wenn ich schon nur mit 1*scanline arbeite, die Farbe nun für die 2.Bitmap verändern kann? Meine Versuche haben ja nix gebracht!
@BenBE Vorschlag bekomme ich auch nicht gebacken :( .Währe ja auch ne überlegung wert.
Gruss ALf
BenBE - Mo 06.09.10 03:14
Für Speed würde ich die Funktion MulDiv empfehlen. Was die macht, dürfte der Name bereits verraten ...
Doku gibt's dazu auch in der DOH bzw. bei M$, weil das eine API ist.
ALF - Mo 06.09.10 18:06
So, hab jetzt das Teil fertig, würde sagen gefühlte 60%> schneller :wink: als meine!
Delphi-Quelltext
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:
| procedure TForm3.DrawBackround_Lines; var ypos, h, x: integer; pcl, pcr: PRGBQUAD; pRGB: tagRGBQUAD; clfx: real; begin ..... .....
for ypos:= 0 to peakbufr.Height-1 do begin clfx:= ypos / peakbufl.Height; pRGB.rgbRed:= trunc(102+ (153 *clfx)); pRGB.rgbGreen:= trunc(113+ (142 *clfx)); pRGB.rgbBlue:= trunc(126+ (129 *clfx)); pcl:= peakbufl.ScanLine[ypos]; pcr:= peakbufr.ScanLine[peakbufr.Height-1 - ypos]; for x:= 0 to peakbufl.Width-1 do begin pcl^:= pRGB; pcr^:= pRGB; inc(pcl); inc(pcr); end; end; .... .... end; |
EDIT: bringt aber nur was, wenn man auch BitBlt benutzt! Sonst bleibt es etwa bei 40%
Ein BIG THX an alle für die Ausdauer.
Gruss Alf
delfiphan - Mo 06.09.10 18:30
Ich hab mich mal schnell durch MulDiv durchgesteppt; der macht auch nur eine normale Multiplikation und eine normale Division. Die Funktion hat paar Ifs drin, ich nehme an es geht um Bereichsprüfung und Overflowverhinderung. Bei dir würde ich aber sowieso kein Integer Overflow befürchten, daher könntest du einfach multiplizieren und dann dividieren und dir denn Call und Ifs sparen. Integer-Arithmetik sollte nochmals signifikant schneller sein. Aber ich könnte mir auch gut vorstellen, dass es sich mehr lohnt, die innere Schleife noch weiter zu optimieren, statt die äussere. Um das zu beantworten bräuchte man einen Profiler.
Aber vielleicht lassen wir's am besten so sein, wie's jetzt ist ;)
elundril - Mo 06.09.10 18:37
Kommt aber teilweise zu anderen ergebnissen mit MulDiv, da kaufmännisch gerundet wird und nicht einfach nur der ganzzahlige Anteil genommen wird. Und wenn man die Integerumwandlung vorzieht ebenso.
Muss man halt abwägen ob es auch mit diesen "Fehlern" leben kann oder ob man die etwas geringere Geschwindigkeit in kauf nimmt.
lg elundril
platzwart - Di 07.09.10 12:58
ALF hat folgendes geschrieben : |
Delphi-Quelltext 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:
| procedure TForm3.DrawBackround_Lines; var ypos, h, x: integer; pcl, pcr: PRGBQUAD; pRGB: tagRGBQUAD; clfx: real; begin ..... .....
for ypos:= 0 to peakbufr.Height-1 do begin clfx:= ypos / peakbufl.Height; pRGB.rgbRed:= trunc(102+ (153 *clfx)); pRGB.rgbGreen:= trunc(113+ (142 *clfx)); pRGB.rgbBlue:= trunc(126+ (129 *clfx)); pcl:= peakbufl.ScanLine[ypos]; pcr:= peakbufr.ScanLine[peakbufr.Height-1 - ypos]; for x:= 0 to peakbufl.Width-1 do begin pcl^:= pRGB; pcr^:= pRGB; inc(pcl); inc(pcr); end; end; .... .... end; |
|
Das dürfte mit Graphics32 nochmals schneller gehen, ich schätze mal Faktor 5. Ich weiß, du willst es nicht benutzen, aber nur so als Info... ;)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!