| Autor |
Beitrag |
P_G
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Do 29.01.09 10:34
Hallo,
sehe zur Zeit wohl den Wald vor lauter Bäumen nicht. Ich will ein Bitmap analysieren. Dazu erstelle ich ein Array of Array of TColor (hier fData), um schnell auf die Farbwerte der Pixel zugreifen zu können.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| OrigBmp.HandleType := bmDIB; OrigBmp.PixelFormat := pf8bit; FOR j := 0 TO OrigBmp.Height-1 DO BEGIN Row := OrigBmp.Scanline[j]; FOR i := 0 TO OrigBmp.Width-1 DO BEGIN fData[I,J].Color := END END; |
Scanline liefert merkwürdige Farbwerte. Die Farbzuweisung durch Row[i] liefert nur schwarz und rot. Kann mir jemand die Augen öffnen?
Gruß, P_G
|
|
P_G 
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Do 29.01.09 11:51
Irgendjemand? Mir gehen die Ideen aus...
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Do 29.01.09 12:06
Etwas mehr Code bitte
Was hat Row für einen Datentyp?
Wo schiebst du den Pointer weiter?
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Do 29.01.09 12:09
Schau dir mal meinen FAQ-Beitrag an, der beschreibt, wie man eine Bitmap stufenweise ausgraut  Dort wird Scanline korrekt angewendet.
Du wirst durt sehen, dass dir Scanline einen Pointer zurückgibt, der am besten als der folgende Datentyp aufgefasst werden kann:
Delphi-Quelltext 1: 2: 3: 4:
| type TColorRec = record r, g, b: Byte;
type PColorRec = ^TColorRec; | (Aus dem Kopf...) Was du nun tun musst, ist zunächst den Inhalt des pointers auslesen wie in meinem FAQ beitrag (link such ich dir gleich raus), dann den pointer per "inc" erhöhen um das nächste pixel zu bekommen.
Edit: hier der link: www.delphi-library.d...iewtopic.php?t=70493
Ich sehe dort, dass ich einen array [0 .. 2] of Byte genommen habe. Ich weiß nicht, ob beide Datentypen die gleiche Größe und den gleichen Aufbau haben, falls ja, müsste der Record auch gehen, aber zur Sicherheit lieber den Array nehmen.
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
P_G 
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Do 29.01.09 12:43
Zunächst Danke für die Antworten.
Der Datentyp for Row ist PByteArray (Pixelformat des Bitmaps ist pf8bit). Ich gehe davon aus, daß der Pointer durch die i-Schleife weitergesetzt wird (erster Fehler?)
Scheinbar liefert der Pointer aber nur den Rotwert des Pixels - auch bei 8 bit (zweiter Fehler weil Verständnisproblem?)
Die Frage ist letztendlich: Wie frage ich per scanline die Farbwerte eines Bitmaps ab, so daß ich einen TColor-Wert erhalte? Wenn ich fData[I,J].Color mit der Eigenschaft Pixels beantworte, läuft es wunderbar, nur eben viel zu langsam...
Noch mal zum Code:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| Var I, J: Integer; Row: PByteArray; begin SetLength(fData, OrigBmp.Width); for I := 0 to High(fData) do begin SetLength(fData[I], OrigBmp.Height); end;
OrigBmp.HandleType := bmDIB; OrigBmp.PixelFormat := pf8bit; FOR j := 0 TO OrigBmp.Height-1 DO BEGIN Row := OrigBmp.Scanline[j]; FOR i := 0 TO OrigBmp.Width-1 DO BEGIN fData[I,J].Color := END END; |
Gruß, P_G
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Do 29.01.09 12:48
P_G hat folgendes geschrieben : | Zunächst Danke für die Antworten.
Ich gehe davon aus, daß der Pointer durch die i-Schleife weitergesetzt wird (erster Fehler?)
Scheinbar liefert der Pointer aber nur den Rotwert des Pixels - auch bei 8 bit (zweiter Fehler weil Verständnisproblem?)
Die Frage ist letztendlich: Wie frage ich per scanline die Farbwerte eines Bitmaps ab, so daß ich einen TColor-Wert erhalte? Wenn ich fData[I,J].Color mit der Eigenschaft Pixels beantworte, läuft es wunderbar, nur eben viel zu langsam...
|
Erster Fehler: warum sollte, wenn die Schleifenvariable erhöht wird, der Pointer erhöht werden? Die beiden Variablen sind für gewöhnlich nicht Quantenverschränkt
Zweiter Fehler: Vielleicht ist es das Pixelformat, ich nutz da immer 24bit.
Meinen Code hast du dir angeguckt, in dem Library Beitrag? der sollte eigentlich alles erklären
Darin siehst du auch, wie du die drei Farbwerte ausließt. mit der Funktion RGB(r, g, b) erhälst du aus 3 Bytewerten einen TColor wert.
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Do 29.01.09 13:07
JayEff hat folgendes geschrieben : | Erster Fehler: warum sollte, wenn die Schleifenvariable erhöht wird, der Pointer erhöht werden? Die beiden Variablen sind für gewöhnlich nicht Quantenverschränkt  |
Schau dir seinen Code nochmal an: Er benutzt einen Pointer auf ein Array, das Pointer-Verschieben geschieht also implizit bei der Indizierung Row[i].
Für 24-Bit gibt es schon einen vorgefertigten Record, afair TRGBTriple.
_________________ >λ=
|
|
P_G 
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Do 29.01.09 13:11
Hi,
durch Row erhalte ich einen Pointer auf die jeweilige Zeile. Row[i] innerhalb der i-Schleife sollte nun den Pointer auf Pixel i innerhalb der Zeile Row liefern. Warum muß ich also noch weiter inkrementieren? Ich gebe zu, daß ich mich mittlerweile schon zu sehr verbissen habe, so daß mir dein Code-Beispiel nur bedingt weiterhilft (du manipulierst die Pixel und fragst sie nicht nur in Form eines TColor-Wertes ab - bin eben mittlerweile blind...).
Ich erkenne immerhin, daß du jeweils noch durch 3 dividierst, weil du durch das 24 bit Format sonst Verschiebungen hättest, die bei mir nicht anliegen (8 bit). Wenn ich übrigens RGB(GetRValue(Row[i]), GetGValue(Row[i]), GetBValue(Row[i])) einsetze, bekomme ich dieselben Fehlfarben. Irgendwo habe ich im Netz gelesen, daß scanline einen Farbwert zurückliefert, bei dem Rot und Blau vertauscht sind. Aber die RGB-Werte zu versetzen, bringts auch nicht.
Gruß, P_G
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 29.01.09 13:29
Moin!
P_G hat folgendes geschrieben : | auch bei 8 bit (zweiter Fehler weil Verständnisproblem?)
Die Frage ist letztendlich: Wie frage ich per scanline die Farbwerte eines Bitmaps ab, so daß ich einen TColor-Wert erhalte?
[...]
Delphi-Quelltext 1: 2:
| OrigBmp.HandleType := bmDIB; OrigBmp.PixelFormat := pf8bit; | |
Wenn ich das richtig sehe, vermutest du hier "Klartextfarbwerte", aber Bilder mit 8-Bit-Farbtiefe haben eine Palette!  Also entweder doch in 24-Bit konvertieren oder den Wert aus dem Scanline-Array als Index in die Farbtabelle des Bildes interpretieren.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
P_G 
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Do 29.01.09 14:15
| Zitat: | Wenn ich das richtig sehe, vermutest du hier "Klartextfarbwerte", aber Bilder mit 8-Bit-Farbtiefe haben eine Palette! Also entweder doch in 24-Bit konvertieren oder den Wert aus dem Scanline-Array als Index in die Farbtabelle des Bildes interpretieren |
Sorry - verstehe ich nicht. Delphis TColor ist in jedem Fall vom Typ Cardinal. Unabhängig von der Frage, ob die Farbzuweisung eines Bitmaps per indizierter Tabelle abläuft oder nicht, sollte man doch erwarten, daß sich über scanline ein TColor-Wert abfragen läßt, der später unmittelbar wieder für TCanvas verwendet werden kann. Pixels tut das schließlich auch. Nehme ich mal einen Moment lang an, daß ich nicht drum herumkomme, Pixelformat auf 24 zu setzen - wie bekomme ich nun per scanline für ein beliebiges Pixel einen TColor-Wert, der demselben Wert entspricht, wie eine Abfrage über Pixels?
Gruß, P_G
|
|
P_G 
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Do 29.01.09 14:42
Problem gelöst!
Pixelformat wird auf 32 gesetzt. Dann deklariere ich:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| type TRGB32 = packed record B, G, R, A: Byte; end; TRGB32Array = packed array[0..MaxInt div SizeOf(TRGB32) - 1] of TRGB32; PRGB32Array = ^TRGB32Array; |
Und setze scanline ein:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| Var I, J: Integer; Row: PRGB32Array; begin SetLength(fData, OrigBmp.Width); for I := 0 to High(fData) do begin SetLength(fData[I], OrigBmp.Height); end;
OrigBmp.HandleType := bmDIB; OrigBmp.PixelFormat := pf32bit; FOR j := 0 TO OrigBmp.Height-1 DO BEGIN Row := OrigBmp.Scanline[j]; FOR i := 0 TO OrigBmp.Width-1 DO BEGIN fData[I,J].Marked := False; fData[I,J].Color := RGB(Row[i].R, Row[i].G, Row[i].B); END END; |
Ich weiß immer noch nicht wirklich, warum meine vorherige Lösung nichts brachte. Aber egal, so gehts jedenfalls. Danke an alle, die Anregungen geliefert haben.
Gruß, P_G
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 29.01.09 15:34
Moin!
P_G hat folgendes geschrieben : | | Delphis TColor ist in jedem Fall vom Typ Cardinal. |
Das ist richtig, hast aber nix damit zu tun:
P_G hat folgendes geschrieben : | | Unabhängig von der Frage, ob die Farbzuweisung eines Bitmaps per indizierter Tabelle abläuft oder nicht, sollte man doch erwarten, daß sich über scanline ein TColor-Wert abfragen läßt, der später unmittelbar wieder für TCanvas verwendet werden kann. |
Nein, das ist nicht so. Scanline[] liefert lediglich einen Zeiger auf eine Zeile (raw!) des Bildes, damit ist nix über die Werte gesagt, die an dieser Adresse zu finden sind.
P_G hat folgendes geschrieben : | | Pixels tut das schließlich auch. |
Ja, allerdings wird hier eine GDI-API-Funktion gekapselt, die einen definierten Output hat. Das Speicherabbild des Images hat damit aber nix zu tun.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
|