Zugriff über Canvas->Pixels zu langsam - warum? alternativen Zugriff auf Pixel?
-
Hallo.
Ich versuche in einem bitmap mit
bmp->Canvas->Pixels[x,y]
auf die einzelnen Pixel des Bildes zuzugreifen um sie dann einzeln zu manipulieren. (Schwellwertbildung -> Binärisierung)
Das ganze dauert aber bei einem Bild mit etwas 600*500 Pixel fast 3 sec. Definitiv zu langsam. Woran kann das liegen? Gibt es eine andere Möglichkeit pixel direkt anzusteuern? ich der Hilfe habe ich nichts gefunden.
Vielen Dank
Jan
-
TBitmap::ScanLine ermöglicht den zeilenweisen Zugriff auf die Pixel. Ist um einiges schneller als über Canvas->Pixels[][].
-
so weit ich weiss aber nur zum lesen- oder?
-
Die Eigenschaft ScanLine ist readonly, aber über ScanLine kannst du schreibend auf die Pixel zugreifen (siehe Beispiel in der Hilfe).
-
ich habe das so eingebaut mit scanline.
rot = GetRValue(ptr[x]);
-
hellsehen koennen wir noch nicht; zeig mal deinen gesamten code.
der zugriff ueber Canvas->Pixels[x][y] ist deshalb so langsam, da Pixels ein Property von Canvas ist und ueber eine Get- & Set-Funktion beschrieben bzw. gelesen wird. damit hast du bei jedem pixel einen zusaetzlichen funktionsaufruf. dazu kommt noch der array-zugriff (2d-array). zuerst auf x und im anschluss auf y. durch die ganzen zusätzlichen funktionen sinkt natürlich die geschwindigkeit enorm und Pixels sollte daher nie verwendet werden sondern ScanLine.
-
so - jetzt habe ich die sache mit scanline am laufen. aber toll ist die geschwindigkeit immernoch nicht. was kann man das noch machen? bmp ist das Bitmap und die Bilder sind nicht sonderlich gross - das muss schneller gehen.
void binaerisiere() { byte *ptr; for(int y=0; y<bmp->Height; y++) { ptr = (byte *) bmp->ScanLine[y]; for (int x=0; x<bmp->Width; x++) { if (ptr[x] >= StrToInt(Form1->Schwellenwert_edit->Text)) ptr[x]= 230; else ptr[x]= 0; } } }
-
Du könntest die Feldmatirx kopieren und über diesse die Manipulation dürchführen .
Das beste währe aber sicherlich den Speicher ausfindigzumachen und dort die Manipulation vorzunehmen
-
was genau ist denn die Feldmatrix?
wie würde ich denn Speicherbereich rankommen?
-
Wenn es um Performance geht haben Sachen wie StrToInt(Form1->Schwellenwert_edit->Text)) auf jeden Fall nichts in den Schleifen verloren, auch wenn das hier wohl nicht die Bremse ist.
-
ja - ist schon klar. ich hatte da zwischendurch auch schon feste werte drin - das hat keinen unterschied gemacht.
-
talshiar schrieb:
void binaerisiere() { byte *ptr; for(int y=0; y<bmp->Height; y++) { ptr = (byte *) bmp->ScanLine[y]; for (int x=0; x<bmp->Width; x++) { if (ptr[x] >= StrToInt(Form1->Schwellenwert_edit->Text)) ptr[x]= 230; else ptr[x]= 0; } } }argh...
1. weg mit StrToInt()
-> bei jedem Pixel rufst du die Funktion auf (dort wird in ner Schleife
eine String in ne Zahl konvertiert -> sehr schlecht, zumal die sich ja
nicht aendert in der Schleife!)
2. weg mit Form1->Schwellenwert_edit->Text
-> bei jedem Pixel wird die Get-Funktion von Text aufgerufen
-> sehr schlecht!
3. weg mit bmp->Width und bmp->Height da hier bei jedem Pixel
die Get-Funktion fuer Width und Height aufgerufen werden und sich
die Hoehe und Breite ja kaum aendert!besser waere zum beispiel folgendes:
typedef unsigned char u_char; typedef unsigned int u_int; void binaerisiere() { u_char Threshold = StrToInt(Form1->Schwellenwert_edit->Text); u_int Height = bmp->Height; u_int Width = bmp->Width; u_char *ptr; u_int x, y; for (y = 0; y < Height; ++y) { ptr = (u_char*) bmp->ScanLine[y]; for (x = 0; x < Width; ++x) *(ptr + x) = (*(ptr + x) >= Threshold ? 230 : 0); } }besser lebst du sowieso, wenn du dir ne eigene bild-klasse baust und den ganzen vcl schnickschnack weglaesst. damit bist du dann auch unabhaengiger von der entwicklungsumgebnung.
ausserdem sollte die funktion das bild und den schwellwert uebergeben bekommen und diese nicht als globale variablen rumlungern!
duerfte auf jeden schneller sein als deine version, wenn nicht solltest du deine compiler-optionen ueberpruefne (release-modus).