![]() |
Optimierung von Pixel
Jemand ne Idee wie ich das beschleunigen kann?
Delphi-Quellcode:
Image1.Picture.Bitmap.Canvas.Pixels[ColumnCounter, BUFFER_SIZE - i] := HSLtoRGB(H, S, L);
Bei einer Bitmap weite von 17507 kann das ganz schön lange dauern bis ich da durch bin. gruss |
AW: Optimierung von Pixel
Probier mal Scanline, oder noch besser: Erstelle einen eigenen Pixelbuffer: Breite x Höhe * 4 und zeichne das erst dort rein und kopiere es dann in das Image.
|
AW: Optimierung von Pixel
Zitat:
In wie weit ist das schneller. Bei einer Mp3 18sec benötige ich gut 5sec um den Stream einzulesen. Mit Pixel wohlbemerkt. gruss |
AW: Optimierung von Pixel
Delphi-Quellcode:
macht bei JEDEM Aufruf einen API Call. Reine Schätzung, aber
Canvas.Pixel
Delphi-Quellcode:
ist locker um den Faktor 1000 schneller (eher mehr). Dort schreibst du die Daten praktisch direkt in den internen Bitmapspeicher.
Canvas.ScanLine
Einen Pixelbuffer brauchst du meiner Meinung nach nicht. Nichts anderes liefert
Delphi-Quellcode:
doch: Einen Zeiger auf den Pixelbuffer des Bitmaps.
Canvas.ScanLine
|
AW: Optimierung von Pixel
Zitat:
Danke. gruss |
AW: Optimierung von Pixel
Zitat:
Delphi-Quellcode:
, nur dass du jetzt jeweils eine Zeile des Bitmaps direkt füllen kannst (eventuell würde es sogar gehen mit dem Pointer der 1. Zeile sämtliche Daten zu schreiben, aber da Bitmapdaten auch nicht-durchgehend sein können [Strides], würde ich das vermutlich nicht riskieren).
Pixels
Achten musst du nur auf die Anzahl der Bits pro Pixel. Meistens ist das in Delphi benutze Format
Delphi-Quellcode:
. Das bedeutet, dass du pro Pixel ein R, G und B Byte hast. Bei
pf24Bit
Delphi-Quellcode:
kommt noch ein Alpha-Byte hinzu und alles unter
pf32Bit
Delphi-Quellcode:
wird kompliziert, da du dann mit Bits rechnen musst (wirst du aber vermutlich nicht brauchen).
pf24Bit
Achso. Die Reihenfolge der Farben war nicht RGB, soweit ich mich erinnere. Da bin ich schon öfters drauf reingefallen, aber leider habe ich die korrekte Reihenfolge trotzdem schon wieder vergessen :-D :stupid: |
AW: Optimierung von Pixel
scheint wieder nicht so einfach zu sein .. ;)
Na wird schon irgend wie .. LOL Scanline gibt ja die Farbe zurück Ich muss sie aber zuweisen Hmm bin mir jetzt nicht klar darüber wie ich
Delphi-Quellcode:
HSLtoRGB(H, S, L);
Scanline zuweisen soll.
Delphi-Quellcode:
gruss
Value := SQRT(SQRT(Buffer[i]));
H := 0 + Value / 1.5; L := Value; |
AW: Optimierung von Pixel
Zitat:
Delphi-Quellcode:
Das füllt dein Bitmap in der Farbe rot.
var
B: TBitmap; X, Y: Integer; P: PByte; begin B := TBitmap.Create; try B.PixelFormat := pf24Bit; B.Width := 200; B.Height := 200; for Y := 0 to B.Height - 1 do begin P := B.ScanLine[Y]; for X := 0 to B.Width - 1 do begin P^ := 0; Inc(P); P^ := 255; Inc(P); P^ := 0; Inc(P); end; end; Canvas.Draw(0, 0, B); finally B.Free; end; end; Statt mit
Delphi-Quellcode:
zu arbeiten, kannst du auch
PByte
Delphi-Quellcode:
verwenden (der Speicher sollte eh aligned sein, weshalb du auch beim letzten Pixel mit dem
PDWord
Delphi-Quellcode:
Format kein invalid-read bekommen solltest) und dann die einzelnen Farbwerte per Bitshifts reinpacken:
pf24Bit
Delphi-Quellcode:
var
B: TBitmap; X, Y: Integer; P: PDWord; begin B := TBitmap.Create; try B.PixelFormat := pf24Bit; B.Width := 200; B.Height := 200; for Y := 0 to B.Height - 1 do begin P := B.ScanLine[Y]; for X := 0 to B.Width - 1 do begin P^ := (0 shl 8) or (255 shl 16) or (0 shl 24); P := PDWord(PByte(P) + 3); // 3 byte per pixel for pf24Bit end; end; Canvas.Draw(0, 0, B); finally B.Free; end; end; |
AW: Optimierung von Pixel
Guckst du hier:
![]() |
AW: Optimierung von Pixel
Noch ein Hinweis:
Pixelformat auf 32-Bit stellen und P nicht als PByte definieren sondern als PRGBQuad. Das ist ein Pointer auf ein Record mit den RGBA werten. Da musst du dir keine Gedanken über die Reihenfolge machen. Und mit einem inc(P) bist du dann auch automatisch direkt 1 Pixel weiter. |
AW: Optimierung von Pixel
Grob auf dem Tablet zusammengezimmert würde das so aussehen:
Delphi-Quellcode:
Var buf: PDWord;
I, x: integer; Begin For i := 0 to bmp.height - 1 do Begin Buf := bmp.scanline[i]; For x := 0 to bmp.width - 1 do Begin Buf^ := $FF000000 or HLSToRGB(...); Inc(buf); End; End; |
AW: Optimierung von Pixel
Zitat:
Delphi-Quellcode:
zu stellen. Ansonsten siehe meinen editierten Post.
pf32Bit
Zitat:
Delphi-Quellcode:
! Dann sollte man auch auf jeden Fall Neutral Generals Hinweis beachten. Dadurch wird der Code deutlich verständlicher. Und wie gesagt, sind die RGB Werte nicht in der korrekten Reihenfolge.
pf32Bit
Delphi-Quellcode:
müsste bei deinem Ansatz deshalb entsprechend angepasst werden.
HLSToRGB
|
AW: Optimierung von Pixel
Danke werde mir das mal alles zu gemüte führen
Hab das früher mit GetDiBits gemacht aber man glaubt es nicht ist auch nicht schneller als Scanline. (Hmm.. oder doch nicht) ![]() Hier mal noch etwas code wie ich die Daten fülle.
Delphi-Quellcode:
gruss
while BASS_ChannelIsActive(Channel) <> BASS_ACTIVE_STOPPED do begin
BASS_ChannelGetData(Channel, Pointer(Buffer), BASS_DATA_FFT512); for i := 0 to BUFFER_SIZE - 1 do begin Value := SQRT(SQRT(Buffer[i])); H := 0 + Value / 1.5; L := Value; Image1.Picture.Bitmap.Canvas.Pixels[ColumnCounter, BUFFER_SIZE - i] := HSLtoRGB(H, S, L); end; Inc(ColumnCounter); Progress := Trunc(100 * (BASS_ChannelGetPosition(Channel, BASS_POS_BYTE) / BASS_ChannelGetLength(Channel, BASS_POS_BYTE))); Form2.ProgressBar1.Position := Progress; Application.ProcessMessages; end; |
AW: Optimierung von Pixel
Zitat:
![]() |
AW: Optimierung von Pixel
Zitat:
gruss |
AW: Optimierung von Pixel
Hier was zum spielen.
Aber wie gesagt mit Pixel eine Qual.. Anhang gelöscht.. gruss |
AW: Optimierung von Pixel
|
AW: Optimierung von Pixel
Zitat:
|
AW: Optimierung von Pixel
Unter sehr leichtem Performaceverlust lässt sich Scanline auch ähnlich wie Pixels verwenden, wenn man sich eine kleine Helferprozedur bastelt.
Delphi-Quellcode:
Aufruf dann so:
procedure SetPixel(aBitmap: TBitmap; aX, aY: Integer; aColor: TColor);
var P: PRGBTriple; begin if aBitmap.Pixelformat <> pf24Bit then raise Exception.Create('Bitmap hat falsches Pixelformat (nicht 24-Bit).'); if (aX < 0) or (aX > aBitmap.Width) then raise Exception.Create('X-Koordinate liegt außerhalb des Bitmaps.'); if (aY < 0) or (aY > aBitmap.Width) then raise Exception.Create('Y-Koordinate liegt außerhalb des Bitmaps.'); P := aBitmap.Scanline[aY]; Inc(P, aX); P^.R := GetRValue(aColor); P^.G := GetGValue(aColor); P^.B := GetBValue(aColor); end;
Delphi-Quellcode:
Wenn man es direkt in seine Schleife baut, lässt sich halt das immer wieder erneute Abholen der Scanline vermeiden (zumindest innerhalb einer Zeile, und wenn man den Stride selber behandelt auch generell), und die Prüfungen fallen nur ein Mal an. Aber das hier düfrte dennoch etliche hundert Mal schneller als Pixels[] sein, bzw. kaum merklich langsamer als ohne die Krücken-Prozedur SetPixel().
while BASS_ChannelIsActive(Channel) <> BASS_ACTIVE_STOPPED do begin
BASS_ChannelGetData(Channel, Pointer(Buffer), BASS_DATA_FFT512); for i := 0 to BUFFER_SIZE - 1 do begin Value := SQRT(SQRT(Buffer[i])); H := 0 + Value / 1.5; L := Value; SetPixel(Image1.Picture.Bitmap, ColumnCounter, BUFFER_SIZE - i, HSLtoRGB(H, S, L)); end; Inc(ColumnCounter); Progress := Trunc(100 * (BASS_ChannelGetPosition(Channel, BASS_POS_BYTE) / BASS_ChannelGetLength(Channel, BASS_POS_BYTE))); Form2.ProgressBar1.Position := Progress; Application.ProcessMessages; end; Es kann sein, dass das Bild dann auf dem Kopf steht. Windows speichert Bitmaps nämlich auf dem Kopf, wenn ich mich nicht irre. Um das zu beheben müsste nur die Zeile
Delphi-Quellcode:
zu
P := aBitmap.Scanline[aY];
Delphi-Quellcode:
geändert werden.
P := aBitmap.Scanline[aBitmap.Height-aY-1];
|
AW: Optimierung von Pixel
Danke für deine Mühe.
Mit ein paar kleinen Änderungen funktioniert es ganz gut. BUFFER_SIZE von 160 um 1 decrementiert. Habe nun aber eine andere Farbe denke das liegt an pf24Bit. Zitat:
gruss |
AW: Optimierung von Pixel
Zitat:
Kann nicht wirklich eine verbesserte Geschwindigkeit feststellen. Das analysieren einer MP3 "Pink Floyd - Echoes"
ScanLine: 109138 ticks Pixel: 109404 ticks Also um beim Faktor 1000 mal schneller zu bleiben sollte ScanLine eigentlich 109.138 Ticks betragen Also irgendwie :( gruss |
AW: Optimierung von Pixel
Welche der genannten Methoden hast du denn für deine Messung verwendet?
Ich bin mir sicher dass man das noch verbessern kann, aber dafür müssten wir hier wohl mehr Details kennen. Auch wundere ich mich etwas, ob die Methode von Medium wirklich funktioniert. Damit hat man ja einen ScanLine-Aufruf pro Pixel. Ich weiß nicht genau was ScanLine im Hintergrund macht, aber ich wäre davon ausgegangen, dass genau der Wegfall dieser vielen Aufrufe einen Großteil des Performancegewinn ausmacht. :gruebel: |
AW: Optimierung von Pixel
Mediums Funktion ist sogar LANGSAMER als
Delphi-Quellcode:
:lol: Mein Testcode
Canvas.Pixels
Delphi-Quellcode:
produziert folgendes Ergebnis:
var
B: TBitmap; X, Y: Integer; P: PRGBTriple; C: Cardinal; begin B := TBitmap.Create; try B.PixelFormat := pf24Bit; B.Width := 2000; B.Height := 2000; // Canvas.Pixels C := GetTickCount; for Y := 0 to B.Height - 1 do begin for X := 0 to B.Width - 1 do begin B.Canvas.Pixels[X, Y] := clRed; end; end; ShowMessage(IntToStr(GetTickCount - C)); // 1141ms // Custom SetPixel method by Medium C := GetTickCount; for Y := 0 to B.Height - 1 do begin for X := 0 to B.Width - 1 do begin SetPixel(B, X, Y, clRed); end; end; ShowMessage(IntToStr(GetTickCount - C)); // 1391ms // Bitmap.ScanLine C := GetTickCount; for Y := 0 to B.Height - 1 do begin P := B.ScanLine[Y]; for X := 0 to B.Width - 1 do begin P^.rgbtRed := 255; P^.rgbtGreen := 0; P^.rgbtBlue := 0; Inc(P); end; end; ShowMessage(IntToStr(GetTickCount - C)); // 15ms finally B.Free; end; end;
Code:
1141ms - Canvas.Pixels
1391ms - SetPixel by Medium 15ms - ScanLine |
AW: Optimierung von Pixel
@Emil
Bei Performanceproblemen hat mit AQTime Pro schon gut geholfen. Da kann man sogar einzelne Zeilen messen lassen. Nur man sollte es nicht in die Delphi-IDE Einbinden, sondern extern nutzen. |
AW: Optimierung von Pixel
Zitat:
Aber eigentlich sollte doch GetTickCount ausreichend sein Zitat:
gruss |
AW: Optimierung von Pixel
Canvas.Pixels[] ruft intern die WinAPI Funktion
![]() Misst du eventuell das Berechnen der FFT mit? Weil das dürfte bei so einem langen Stück selbst mit den diversen optimierten FFTs recht lange dauern. Ansonsten mal so probieren:
Delphi-Quellcode:
Nicht ganz getestet, aber zumindest die Punkte sollten so passen. ich weiss jetzt nicht, ob die Nutzung von
var
b: TBitmap; // Pufferbitmap um horizontal zeichnen zu können p0, p: PRGBTriple; c: TColor; points: array[0..2] of TPoint; begin b := TBitmap.Create; b.PixelFormat := pf24Bit; b.SetSize(BUFFER_SIZE, 1); p0 := b.Scanline[0]; ... while BASS_ChannelIsActive(Channel) <> BASS_ACTIVE_STOPPED do begin BASS_ChannelGetData(Channel, Pointer(Buffer), BASS_DATA_FFT512); p := p0; for i := 0 to BUFFER_SIZE - 1 do begin Value := SQRT(SQRT(Buffer[i])); H := 0 + Value / 1.5; L := Value; c := HSLtoRGB(H, S, L); p^.rgbtRed := GetRValue(c); p^.rgbtGreen := GetGValue(c); p^.rgbtBlue := GetBValue(c); Inc(p); end; points[0] := Point(ColumnCounter+1, 0); points[1] := Point(ColumnCounter+1, BUFFER_SIZE-1); points[2] := Point(ColumnCounter, 0); PlgBlt(Image1.Picture.Bitmap.Canvas.Handle, points, b.Canvas.Handle, 0, 0, b.Width, b.Height, 0, 0, 0); // b gedreht an die richtige x-Position auf das Image malen Inc(ColumnCounter); Progress := Trunc(100 * (BASS_ChannelGetPosition(Channel, BASS_POS_BYTE) / BASS_ChannelGetLength(Channel, BASS_POS_BYTE))); Form2.ProgressBar1.Position := Progress; Application.ProcessMessages; end; ... b.Free; ![]() |
AW: Optimierung von Pixel
Roter Kasten:
Zitat:
|
AW: Optimierung von Pixel
Zitat:
Delphi-Quellcode:
den Bitmap-Buffer eigentlich cached. Allerdings werden da neben dem Anfordern des Buffers noch 100 andere Sachen in der Funktion gemacht, die ich mir jetzt nicht genauer angeschaut habe. Diese Funktionen werden wohl der Grund für den Performanceverlust sein.
ScanLine
|
AW: Optimierung von Pixel
Man könnte ja mal spaßeshalber eine Art Zwischenspeicher für das Ergebnis von ScanLine einführen.
Code:
if aY != old_aY:
old_aY = aY scanlineResult = ScanLine(..., aY) // mit scanlineResult weiter verfahren |
AW: Optimierung von Pixel
Ich habe jetzt alle Varianten durch und lade das Projekt mal hoch. (Anhang gelöscht neue auf der nächsten Seite)
Seltsamer weise tut die Funktion von Zacherl nicht was sie soll.. Oder ich war zu blöd diese einzubinden. Die neue von Medium liefert auch nicht das richtige Zeichnungs Resultat. wäre schön wenn ihr das mal testen würdet. alte Version ohne Änderung. wundert mich schon warum der Kram so lange dauert bei analysieren. Was nicht geht ist das auf die nächste Seite gesprungen wird. PS: Nicht wundern! 00:00:00 = Min,Sec,Ms gruss |
AW: Optimierung von Pixel
Delphi-Quellcode:
verbraucht fast deine ganze CPU Zeit.
PB.Refresh
|
AW: Optimierung von Pixel
Zitat:
Habe es deaktiviert. Auch wenn es schöner wäre die Fortschritte des ladens zu sehen. Auf der anderen Seite hat es keinen Einfluss darauf ob ScanLine schneller als Pixel ist. Macht bei mir nach dem deaktivieren von PB.Refresh gerade mal eine Sekunde aus. gruss |
AW: Optimierung von Pixel
Zitat:
Delphi-Quellcode:
auch. Trotzdem sehe ich den Fortschritt .. ist das bei dir nicht der Fall?
Application.ProcessMessages
Zitat:
|
AW: Optimierung von Pixel
Zitat:
gruss |
AW: Optimierung von Pixel
Zitat:
|
AW: Optimierung von Pixel
Zitat:
Wäre eine Möglichkeit. Ist deine Funktion jetzt schneller oder gibt es keine Unterschiede? gruss |
AW: Optimierung von Pixel
Zitat:
Delphi-Quellcode:
Progress := trunc(100 * (BASS_ChannelGetPosition(Channel, BASS_POS_BYTE) / BASS_ChannelGetLength(Channel, BASS_POS_BYTE)));
if (Form2.ProgressBar1.position <> Progress) then begin Form2.ProgressBar1.position := Progress; PB.Refresh; Application.ProcessMessages; end; Zitat:
|
AW: Optimierung von Pixel
Zitat:
Hat jetzt nicht direkt mit den Pixeln zu tun! Was mich jetzt noch fuchst das ich die Seiten nicht umschalten kann ohne dass das Bitmap anfängt zu scrollen. Also wenn die Linie das ende der Scrollbox erreicht hat. Danke das du dir das Anschaust. ;) Anbei ne neue Version mit deiner Änderung der Progressbar gruss |
AW: Optimierung von Pixel
Zitat:
Ist es trotz falsch dennoch flotter? |
AW: Optimierung von Pixel
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:38 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz