Entwickler-Ecke

Multimedia / Grafik - Wie funzt der Scanline?


morvister - Do 28.08.08 11:33
Titel: Wie funzt der Scanline?
Hallo zusammen,

ich verwende in meinem augenblicklichen kleinen Projekt den Scanline, um die Farbe eines bestimmten Image-Bereiches zu ändern. Dazu habe ich einen leicht abgeänderten Beispiel-Code verwendet, so sieht er aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
procedure TForm2.LandFaerben(const r, g, b, LandNr: Byte);
type
  PixArrayBMP = Array [1..3of Byte;
  PixArrayIMG = Array [1..3of Byte;
  var p: ^PixArrayBMP;
      q: ^PixArrayIMG;
      h, w: Integer;
begin
  for h := 0 to Bitmap.Height-1 do begin
     p := Bitmap.ScanLine[h];
     q := Image1.Picture.Bitmap.ScanLine[h];
     for w := 0 to Bitmap.width-1 do begin
        if p^[3] = LandNr then begin
         q^[3] := r;
         q^[2] := g;
         q^[1] := b;
        end;
         Inc(p);
         Inc(q);
     end;
  end;
  Image1.Refresh;

end;


Das Bitmap existiert nur im Hintergrund und dient lediglich der Identifizierung einzelner Landkartenregionen mittels bestimmter Farbcodierungen. LandNr. 1 hat den R-Farbwert 1, LandNr. 2 hat R-Farbwert 2 usw. Und auf dem Image, welches der Anwender sieht, werden dann die echten Farbänderungen vorgenommen. Diese Methode wurde hier andernorts schon mal vorgeschlagen. (suche z.b. nach "Risiko") Die Methode funzt auch ganz hervorragend.

Nun zum eigentlichen Thema: Wie funzt der Scanline? Im Prinzip habe ich es so verstanden, dass die Zeile:

Delphi-Quelltext
1:
p := Bitmap.ScanLine[h]                    


irgendwie eine komplette Pixelzeile des Bitmaps "scant". Ich frag mich nur, wo werden die ganzen Infos für jedes einzelne Pixel denn untergebracht? "p" ist ein Zeiger auf PixArrayBMP, welches 3 Byte-Werte aufnehmen kann. Also die RGB -Werte für genau 1 Pixel. Für den 1. Durchlauf der for-Schleife reicht mein Verständnis als noch aus. Aber wohin zeigt denn "p" nach dem 1. bis n. "Inc(p)"?

Kann sein, dass ich in Multimedia falsch binm, weil das vllt. ein generelles Zeiger-Verständnis-Problem ist, aber da sich mein Problem auf den Scanline-Befehl bezieht, dachte ich mir, bin ich hier vllt. "richtiger".

Hoffentlich versteht jemand hier, was ich nicht verstehe und kann mir helfen :-)


Chryzler - Do 28.08.08 11:40

Mittels Bitmap.Scanline[y] bekommst du einen Pointer auf das erste Pixel in der angegebenen Zeile. D.h. im ersten Durchlauf zeigt der Pointer auf das erste Pixel, dann wird der Pointer um eine Stelle verschoben (Inc(p)), und er zeigt auf den zweiten Pixel, dann auf den dritten, usw. Wenn die gesamte Zeile zuende gelesen wurde, wird der Pointer wieder auf den ersten Pixel in der nächsten Zeile gesetzt (wieder durch Bitmap.Scanline[y]).


ene - Do 28.08.08 11:44

Hoi,

schau dir mal das hier an:

http://www.efg2.com/Lab/ImageProcessing/Scanline.htm


morvister - Do 28.08.08 11:55

besten Dank euch beiden, ich habs begriffen :idea:


elundril - Do 28.08.08 15:32

soweit ich weiß gibt es aber einen "einfacheren" weg um solche regionen zu erstellen und dann auf diese zu reagieren.

lg elundril