In deinem Fall kann Scanline seinen eigentlichen Vorteil gar nicht richtig ausspielen. Mit ScanLine kann man sehr schnell eine ganze Zeile des Bitmaps bearbeiten. Dein Code arbeitet aber spaltenorientiert, weswegen du immer nur ein Pixel der jeweiligen Scanline änderst und beim nächsten Aufruf bereits eine andere Scanline brauchst.
Eventuell kannst du noch etwas Performance herausholen, wenn du die Scanlines cached:
Delphi-Quellcode:
var
ScanLines: TArray<PRGBTriple>;
{ nach Zuweisung von Bitmap.Height werden die Scanlines im Array mit der ersten Spalte initialisiert }
SetLength(ScanLines, BitMap.Height);
for I := 0
to Length(ScanLines) - 1
do begin
ScanLines[I] := Bitmap.ScanLine[I];
end;
{ statt SetPixel }
aColor := HSLtoRGB(H, S, L);
// hier könnte man noch etwas herausholen, wenn direkt die RGB-Werte zurückgegeben werden.
P := ScanLines[BUFFER_SIZE - i];
P^.rgbtRed := GetRValue(aColor);
// dann spart man sich hier wieder das auslesen
P^.rgbtGreen := GetGValue(aColor);
P^.rgbtBlue := GetBValue(aColor);
{ nach Inc(ColumnCounter) werden die ScanLine-Pointer um eine Spalte weiter gerückt. }
for I := 0
to Length(ScanLines) - 1
do begin
Inc(ScanLines[I]);
end;
Vorausgesetzt, es gibt eine Prozedur
procedure HSLtoRGB(H, S, L: double; out R, G, B: Byte);
könnte der relevante Code etwa so aussehen:
Delphi-Quellcode:
SetLength(ScanLines, BitMap.Height);
for I := 0 to Length(ScanLines) - 1 do begin
ScanLines[I] := Bitmap.ScanLine[I];
end;
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;
P := ScanLines[BUFFER_SIZE - i];
HSLtoRGB(H, S, L, P.rgbtRed, P.rgbtGreen, P.rgbtBlue);
end;
for I := 0 to Length(ScanLines) - 1 do begin
Inc(ScanLines[I]);
end;
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;
end;
end;
Wenn nicht schon geschehen, solltest man auch mal die Basiszeit der Analyse ermitteln, die sowieso verbraucht wird ohne in das Bitmap zu schreiben.