AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi TCanvas.Pixels[] optimieren - Wer hilft mit?
Thema durchsuchen
Ansicht
Themen-Optionen

TCanvas.Pixels[] optimieren - Wer hilft mit?

Ein Thema von blackdrake · begonnen am 24. Mär 2009 · letzter Beitrag vom 27. Mär 2009
Antwort Antwort
Seite 1 von 2  1 2      
blackdrake

Registriert seit: 21. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#1

TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 24. Mär 2009, 08:32
Hallo.

Ich arbeite viel mit TImages und verwende häufig Pixels[], um einzelne Pixel zu bearbeiten oder sie in zwei X-Y-For-Schleifen abzurufen. Leider werden die Programme dadurch sehr langsam. Ich habe mich seit heute mal mit den Scanlines beschäftigt und möchte eine Klasse schreiben, die ein TImage um eine optimierte Pixels[]-Property erweitert.

Die Klasse funktioniert bereits mit dem 24 Bit Speicherbelegung. Die Klasse muss aber noch unbedingt auf die anderen Werte von TPixelFormat portiert werden. Könnt ihr mir dabei helfen? Es würde mich sehr freuen, wenn ihr euch daran beteiligen könnt, sodass alle Farbtiefen unterstützt werden und die direkte Verwendung von Pixels[] endlich mal performant möglich ist.

Hier mein Code für 24-Bit-Bilder:

Delphi-Quellcode:
type
  TRGBArray = array[0..32767] of TRGBTriple;
  PRGBArray = ^TRGBArray;

  // TExtImage.Pixels[x,y] übernimmt die Funktion von
  // TImage.Picture.Bitmap.Canvas.Pixels[x,y] mit höherer
  // Performance.

  TExtImage = class(TImage)
  private
    function GetPixel(X, y: integer): TColor;
    procedure SetPixel(X, Y: integer; Value: TColor);
  public
    property Pixels[X, Y: integer]: TColor read GetPixel write SetPixel;
  end;

procedure TExtImage.SetPixel(X, Y: integer; Value: TColor);
var
  Row: PRGBArray;
begin
  if Self.Picture.Bitmap.PixelFormat = pf24Bit then
  begin
    Row := Picture.Bitmap.Scanline[Y];
    Row[X].rgbtRed := GetRValue(Value);
    Row[X].rgbtGreen := GetGValue(Value);
    Row[X].rgbtBlue := GetBValue(Value);
  end
  else
  begin
    // TODO: Auch andere PixelFormat's unterstützen!
    Picture.Bitmap.Canvas.Pixels[X, Y] := Value;
  end;
end;

function TExtImage.GetPixel(X, Y: integer): TColor;
var
  Row: PRGBArray;
begin
  if Picture.Bitmap.PixelFormat = pf24Bit then
  begin
    Row := Picture.Bitmap.Scanline[Y];
    result := RGB(Row[X].rgbtRed, Row[X].rgbtGreen, Row[X].rgbtBlue);
  end
  else
  begin
    // TODO: Auch andere PixelFormat's unterstützen!
    result := Picture.Bitmap.Canvas.Pixels[X, Y];
  end;
end;
(Die Klasse wäre eigentlich perfekt als Helferklasse für ein TCanvas, doch dann wäre die Abwärtskompatibilität futsch...)

Hier der Performancevergleich von Pixels[] bei meiner 24 Bit Farbtiefe Variante:

TCanvas: 1887 ms
TExtImage: 127 ms


(3 Mittelwerte im Debugger, 500 MHz, Testreferenzgrafik)

Gruß
blackdrake

---

Anhang: Die Testroutine:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  x: TExtImage;
  i, j: integer;
  s, e: TDateTime;
  col: TColor;
  Hour, Min, Sec, MSec: word;
begin
  x := TExtImage.Create(self);
  x.Parent := self;
  x.Picture.LoadFromFile('Test.bmp');
  x.AutoSize := true;

  s := Now();
  for i := 0 to x.Width - 1 do
  for j := 0 to x.Height - 1 do
  begin
    col := x.Pixels[i,j];
    col := col and clGray;
    x.Pixels[i,j] := col;
  end;
  e := Now();
  DecodeTime(e-s, Hour, Min, Sec, MSec);
  ShowMessageFmt('%d,%d', [Sec, MSec]);
end;
Die Referenzgrafik ist zu finden unter: http://www.delphipraxis.net/internal...017959#1017959
Daniel Marschall
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#2

Re: TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 24. Mär 2009, 08:51
Hallo,

eine Anmerkung habe ich gleich mal: Ein TImage ist ein Container, in dem alles mögliche drinstecken kann, ein Bitmap, ein Icon, ein JPEG, ein Metafile, irgendwas anderes, oder auch gar nichts. Dass Du einfach auf Picture.Bitmap zugreifst ist also eine sehr gefährliche Sache. Besser wäre es, z. B. einen Class-Helper für TBitmap zu schreiben oder (für ältere Delphi-Versionen) eine Ableitung von TBitmap.

Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#3

Re: TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 24. Mär 2009, 08:51
Dein Vorhaben ist löblich allerdings:
- Wer auf Geschwindigkeit großen Wert legt nimmt keine TImages
- Die Verwendung von Scanline wird erst richtig effektiv wenn man nicht ständig Scanline aufruft sondern nur einmal und dann die Daten am Stück bearbeitet.

[OT]
Die Mehrzahl von Format ist Formate und nicht Format's

[Edit]
eine genauere Zeitmessung bekommst du mit QueryPerformanceCounter
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
matashen

Registriert seit: 29. Jan 2007
Ort: daheim
460 Beiträge
 
Delphi XE2 Enterprise
 
#4

Re: TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 24. Mär 2009, 08:54
Was kann man denn alternativ zu TImage verwenden. Hab da schon lange nach gesucht, aber bisher bin ich nicht fündig geworden.

Gruß Matthias
Matthias
Das Leben ist eines der härtesten.
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#5

Re: TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 24. Mär 2009, 08:58
man kann alternativ (je nochdem ob Transparenzt benötigt wird) eine TPaintbox verwenden oder selbst eine Ableitung von TGraphicControl/TWinControl schreiben.
Wenn sehr oft gezeichnet werden muss (wo dann eigentlich ein TImage fehl am Platz ist) kommt man am besten man zeichnet alles direkt auf die Canvas und aktuallisiert nur bei bedarf in einem bestimmten Interval (Bei TImage und anderen Komponenten welche sich auf die Canvas des Parents zeichnen werden bei einer Änderung alle auf dem Parent befindlichen derartigen Komponenten gezeichnet. Und wenn sich mehrere dieser Komponenten ändern wird überflüssiger Weise jedes mehrfach gezeichnet anstelle alle gleichzeitig am Ende)
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
matashen

Registriert seit: 29. Jan 2007
Ort: daheim
460 Beiträge
 
Delphi XE2 Enterprise
 
#6

Re: TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 24. Mär 2009, 09:02
OK, damit kann ich aber leider nichts anfangen da dies für meine Anwendung zu aufwändig wird. Da würde ich auf blackdrakes lösung zurückgreifen wenns denn Fertig ist.
Ich hab auch das Problem, das TBitmap nur Bilder mit sehr wenig Auflösung vertragen. Da hatte ich schonmal nen Thread gestartet, aber leider erfolglos.
Aber vieleicht lässt sich ja hier das ganze ausbauen.

Gruß Matthias
Matthias
Das Leben ist eines der härtesten.
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 21. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#7

Re: TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 24. Mär 2009, 20:27
Hallo.

Da ein TImage mehrere Typen haben kann, ist Picture.Bitmap.Canvas ja gar nicht so toll. Und Picture.Canvas hat ein anderes verhalten. Wenn man dort auf Pixels[] zugreift (auch lesend), dann wird das ganze Bild weiß, wenn es vorher nicht gesetzt wurde.

Mir läge es eben wie gesagt daran, Pixels[] zu optimieren, da es ja scheinbar mit Scanlines nahezu gut funktioniert (aber wenn das 1x Anwenden von Scanlines dann eben nochmal schneller, aber vom Code her komplizierter, ist). Das blöde ist, dass man eben genau wissen muss, wie diese 1-Bit, 4-Bit, Custom-Bit Dinger intern aufgebaut sind... Wäre ja auch eigentlich eine Sache für Borland/CG, Pixels[] so performant wie möglich zu gestalten.

OK, Class helpers wären wie ich ja bereits angemerkt hatte, eine gute Idee, aber da muss ich mich erstmal reinarbeiten. Außerdem geht es ja dann mit Delphi 7 auch nicht mehr. Sagen wir mal, ich würde TBitmap (oder besser gleich TCanvas?) ableiten ... dann müsste ich ja TImage und/oder TBitmap nochmal neu schreiben und alle TCanvas mit TFastCanvas ersetzen... Wäre das nicht ungünstig? (Will endlich mal Mehrfachvererbung nutzen )

// Edit: Ja, mit TImages ist das so eine Sache. Was ist, wenn ich gerne Bitmaps laden+bearbeiten+speichern will, anstelle sie nur darzustellen? Was soll man denn stattdessen verwenden? (Sag jetzt bitte nicht, ich soll die Datei gleich binär ändern )

Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#8

Re: TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 24. Mär 2009, 20:44
Ich würde auch gar nicht damit anfangen eine optimierte Lib selbst zu schreiben - ich schwöre was schnelle Bildverarbeitung angeht auf die Graphics32-Lib. Die haben z.B. eine optimierte Pixels[]-Eigenschaft schon integriert, außerdem noch optimierte Funktionen, um Linien zu zeichnen, Bilder zu transformieren etc., Alphachannel gibt es auch noch.

Es sind auch Ersatzkomponenten für visuelle Komponenten wie TImage dabei. Wenn man die nicht benutzen möchte, ist es aber auch ein leichtes die Daten in ein TBitmap zu Kopieren (oder direkt auf ein Canvas).

Btw gebe ich SirThornberry recht, dass man Scanline konsequent verwenden muss, damit es wirklich zu einer Performancesteigerung kommt - Am Besten arbeitet man gar nicht erst mit Arrays, sondern mit Pointern (die nach jedem Pixel inkrementiert werden).
  Mit Zitat antworten Zitat
mr_emre_d
(Gast)

n/a Beiträge
 
#9

Re: TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 24. Mär 2009, 21:56
TFastBitmap:
640x480x24 ~ 50-60 ms.
384x384x32 ~ 20-30 ms.

MfG
Angehängte Dateien
Dateityp: rar tfastbmp_347.rar (1,5 KB, 28x aufgerufen)
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 21. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#10

Re: TCanvas.Pixels[] optimieren - Wer hilft mit?

  Alt 27. Mär 2009, 07:46
Zitat von NamenLozer:
ich schwöre was schnelle Bildverarbeitung angeht auf die Graphics32-Lib.
Hallo.

Vielen Dank für den Hinweis. Diese Unit ist wirklich schnell. Es war jedoch schon etwas arbeit, ein Programm darauf zu portieren, da man alle TColor-Funktionen durch TColor32 ersetzen muss und nicht die nativen mit den 32er-Farben mixen darf. Außerdem darf man nach dem PixelS[] bzw. am Funktionsende ein TImage32.Repaint niemals vergessen.

Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz