Einzelnen Beitrag anzeigen

Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#50

AW: Optimierung von Pixel

  Alt 8. Apr 2016, 18:11
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.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat