Avatar billede zerohero Nybegynder
06. april 2001 - 10:40 Der er 25 kommentarer og
1 løsning

Scanlines og Pixels

Hvis jeg har en grafik linie der indeholder RGB værdier f.eks. RGB(100,120,10) RGB(200,150,240) RGB(90,40,80)... osv.
Kan jeg så med Scanline \"scanne\" denne grafik-linie og indsætte de forskellige RGB værdier i en Tlistbox.

Det skulle gerne virke på samme måde som denne \"pixels\" eksempel (problemet med pixels metoden er bare at det tager mega laaaang tid):

var x,y,r,g,b : integer;
begin
for x := 0 to Tbitmap.width-1 do
for y := 0 to Tbitmap.height-1 do begin
r := getrvalue(Tbitmap.canvas.pixels[x,y]);
g := getgvalue(Tbitmap.canvas.pixels[x,y]);
b := getbvalue(Tbitmap.canvas.pixels[x,y]);
Tlistbox.items.add(inttostr(r)+inttostr(g)+inttostr(b));
end;

ZeroHero
Avatar billede borrisholt Novice
06. april 2001 - 10:43 #1
zerohero>> Du snakker sort  !!!!

Kan du ikke komme med et godt gammeldags eksempel med en canvas og en pixels[x,y] der viser hvad du vil ...

Jens B
Avatar billede delphi Nybegynder
06. april 2001 - 11:05 #2
Jeg bankede lige følgende eksempel sammen. 

Bemærk at jeg bruger en 24Bit bitmap som skal placeres som: C:\\Temp\\Test.bmp  (Lav selv navnet om...)

New Application
Placer et Image og et Memo felt på formen.  Sæt formens bredde til noget passende, fx 350.

Brug så følgende code:

procedure TForm1.FormCreate(Sender: TObject);
Const
  FName = \'C:\\Temp\\test.bmp\';
Var
  y          : Integer;
  SLin      : PByteArray;
  r0, g0, b0 : Byte;
  r1, g1, b1 : Byte;
begin
  Try
    Image1.Picture.LoadFromFile(FName);
  Except
    Raise Exception.Create(\'This example needs a 24bit bitmap called: \'+FName);
  End;

  If Image1.Picture.Bitmap.PixelFormat <> pf24bit Then
    Raise Exception.Create(\'This example only works with a 24bit bitmap\');

  Image1.Top    := 0;
  Image1.Left  := 0;
  Image1.Width  := Image1.Picture.Bitmap.Width;
  Image1.Height := Image1.Picture.Bitmap.Height;

  Memo1.Clear;
  Memo1.Top    := 0;
  Memo1.Left    := Image1.Width;
  Memo1.Height  := Image1.Height;

  For y := 0 To Image1.Picture.Bitmap.Height-1 Do
    Begin
      SLin := Image1.Picture.Bitmap.ScanLine[y];
      r0:= sLin^[2];  // Note: stored as BGR
      g0:= sLin^[1];
      b0:= sLin^[0];

      r1:= sLin^[5];  // Note: stored as BGR
      g1:= sLin^[4];
      b1:= sLin^[3];

      Memo1.Lines.Add(\'Line: \'+IntToStr(y)+\': [\'+
                      \'R0: \' +IntToStr(r0)+\',\'+
                      \'G0: \' +IntToStr(g0)+\',\'+
                      \'B0: \' +IntToStr(b0)+\'], [\'+
                      \'R1: \' +IntToStr(r1)+\',\'+
                      \'G1: \' +IntToStr(g1)+\',\'+
                      \'B1: \' +IntToStr(b1)+\']\');
    End;
  ClientWidth  := Memo1.Left + Memo1.Width;
  ClientHeight  := Image1.Height;
end;


Peter
Avatar billede delphi Nybegynder
06. april 2001 - 11:06 #3
Jeg mente: Sæt memo\'ens bredde til 350... ikke formen - den bliver alligevel ændret i koden!
Avatar billede zerohero Nybegynder
06. april 2001 - 11:29 #4
Borrisholt>> Jeg er ked af hvis jeg ikke kan finde ud af at formulere mig ordenligt. Jeg prøver lige igen...

Jeg vil via Scanline indsætte et bitmap-billeds RGB værdier ind i en Tlistbox.

Den skal have samme funktion som dette eksempel:

procedure TForm1.PixelsTest;
var
x, y, r, g, b : integer;
begin

for x := 0 to Tbitmap.width-1 do
for y := 0 to Tbitmap.height-1 do begin
r := getrvalue(Tbitmap.canvas.pixels[x,y]);
g := getgvalue(Tbitmap.canvas.pixels[x,y]);
b := getbvalue(Tbitmap.canvas.pixels[x,y]);

Tlistbox.items.add(inttostr(r)+inttostr(g)+inttostr(b));
end;

end;

(Borrisholt - koden skulle altså være god nok).
Avatar billede delphi Nybegynder
06. april 2001 - 11:31 #5
Det er det min kode gør....bare til et memo i stedet for en Listbox.
Avatar billede zerohero Nybegynder
06. april 2001 - 11:36 #6
Delphi>> Jeg har lige testet dit eksempel, men
ved alle RGB værdierne står der nul...
Avatar billede vandhunden Nybegynder
06. april 2001 - 11:39 #7
Scanlines - Halløøøj Boye, Hej Kaj :-)
Avatar billede delphi Nybegynder
06. april 2001 - 11:40 #8
Sjovt, det gør der ikke i mit!  Der er ikke bare fordi du bruger en bitmap, der har sorte pixels i de to yderste, venstre positioner??

Vil du ha\' et screen shot af hvordan det ser ud på min PC?

Peter
Avatar billede zerohero Nybegynder
06. april 2001 - 11:40 #9
OK - Jeg tror jeg ved hvorfor... Dit eksempel læser kun de to første pixels i hver linie.
Avatar billede delphi Nybegynder
06. april 2001 - 11:40 #10
Vandhund: :)
Avatar billede delphi Nybegynder
06. april 2001 - 11:41 #11
Zerohero: Nemmerlig
Avatar billede zerohero Nybegynder
06. april 2001 - 11:41 #12
Delphi - (you are my man!!!)
Avatar billede delphi Nybegynder
06. april 2001 - 11:42 #13
Jeg ved det...
Avatar billede zerohero Nybegynder
06. april 2001 - 11:43 #14
Hvordan kan den læse alle pixels i hver line uanset hvilken bredde billedet har?
Avatar billede zerohero Nybegynder
06. april 2001 - 11:45 #15
Jeg mener istedet for at skrive:

r0:= sLin^[2];  // Note: stored as BGR
      g0:= sLin^[1];
      b0:= sLin^[0];

      r1:= sLin^[5];  // Note: stored as BGR
      g1:= sLin^[4];
      b1:= sLin^[3];

Kan man så ikke lave noget fikst så den læser aller pixels?
Avatar billede delphi Nybegynder
06. april 2001 - 11:56 #16
Du er nødt til at vide hvilket pixelformat der er benyttet (Bitmap.PixelFormat - find constanterne i online hjælpen).
Ud fra dette kendskab ved du så hvorledes de enkelte pixels er organiseret i linien.  Så må du lavbe noget alá:

PF := Bitmap.PixelFormat;
Case FBitmap.PixelFormat Of
  pf32bit : Pitch := 4;
  pf24bit : Pitch := 3;
  pf16bit : Pitch := 2;
  pf15bit : Pitch := 2;
  pf8bit  : Pitch := 1;
Else
  Error - unknown pixelform exception
End;

Var
  Pixel : LongWord; // Eller en eller anden stor-nok type

For Y := 0 To Bitmap.Heigth-1 Do
  For X := 0 To Bitmap.Width - 1 Do
    Begin
      SLine := Bitmap.ScanLine[y];
     
      Pixel := SLine^[X*Pitch]; 

      // Gør her det du vil med din pixel.  Formatet afhænger af
      // pixelformat, så du skal no ha en case sætning her:
      Case FBitmap.PixelFormat Of
        pf32bit : ...;
        pf24bit : Begin // Colors stored as: [BGRx]
                        // (x=Blue value for next pixel)
                    R := Pixel SHR 4;
                    G := Pixel SHR 8;
                    B := Pixel SHR 12;
                  End;
        pf16bit : ...;
        pf15bit : ...;
        pf8bit  : Begin  // Gray scale.  R = G = B;
                    R := Pixel SHR 12;
                    G := Pixel SHR 12;
                    B := Pixel SHR 12;
                  End;
      Else
        Error - unknown pixelform exception
      End;

    End; 

Det er frit fra leveren, men jeg håber du kan bruge det....

Peter
Avatar billede delphi Nybegynder
06. april 2001 - 11:58 #17
Hvis du VED at der er tale om et std. 24 bit bitmap, så kan det se\'følig kortes noget ned:

Var
  Pixel : LongWord; // Eller en eller anden stor-nok type

For Y := 0 To Bitmap.Heigth-1 Do
  For X := 0 To Bitmap.Width - 1 Do
    Begin
      SLine := Bitmap.ScanLine[y];
     
      Pixel := SLine^[X*3]; 

    // Colors stored as: [BGRx]
    // (x=Blue value for next pixel)
    R := Pixel SHR 4;
    G := Pixel SHR 8;
    B := Pixel SHR 12;

   
Peter
Avatar billede delphi Nybegynder
06. april 2001 - 11:58 #18
Det er altså ikke specielt nemt at skrive kode i det lille felt eksperten stiller til rådighed!
Avatar billede borrisholt Novice
06. april 2001 - 12:00 #19
Ønsker i to jer jeres eget chatrum ?

Jens B



Avatar billede delphi Nybegynder
06. april 2001 - 12:01 #20
Ups: ser lige alt alle mine Shift Right offsets i ovenstående kode kun skubber i 4 bit nibbles, ikke byute størrelse som det er krævet.  Der skal derfor stå:

    R := Pixel SHR 8;
    G := Pixel SHR 16;
    B := Pixel SHR 24;

Avatar billede delphi Nybegynder
06. april 2001 - 12:01 #21
Jens: Tjaa... føler du dig udenfor?  Du kan da bare være med!
Avatar billede borrisholt Novice
06. april 2001 - 12:03 #22
delphi  >>> Det var nu ikke lige sådan ment, mere som det mindet lidt om en chat ...

Jens B
Avatar billede delphi Nybegynder
06. april 2001 - 12:04 #23
Jeg ved det.  Jeg har ikke specielt meget tid til at følge med i Delphi kategorien (desværre), så istedet kaster jeg mig pover enkelte spørgsmål - som jeg så prøver at følge til dørs.
Avatar billede zerohero Nybegynder
06. april 2001 - 12:27 #24
Delphi>> Jeg tror jeg er ved at få det til at virke nu... Dog fatter jeg stadig ikke helt det med pixelformat 24bit osv. Men det må jeg kunne læse mig frem til et eller andet sted på nettet.

1000 tak for hjælpen...

ZeroHero
Avatar billede delphi Nybegynder
06. april 2001 - 12:45 #25
Tak for pointne.

Pixelformat:

Det drejer sig kort fortalt om hvorledes RGB værdierne for de enkelte pixels er gemt.  Ved Pixelformat pf24Bit, gemmes værdierne som 3 * 8 bit for hver pixel, i rækkefølgen BGR:

Forestil dig en linie startende med følgende pixels: Sort, Rød, Grøn, Blå, ....

Her vil dine scanline data, som bytes, være:

0, 0, 0,  0, 0, 255,  0, 255, 0,  255, 0, 0,  ....

Bruges et andet Pixelformat, fx. pf8bit, vil RGB værdierne være gemt (pakket) på en anden måde.  Ved pf(bit (grayscale) gemmes 8 bit for hver pixel - farver i gråtone scalaen er iøvrigt kendetegnet ved at R = G = B.  Prøv med fx. Paint Shop Pro - hvis du sætter værdierne for R, G og B så vil du se at den resulterende farve er grå, intensiteten (lysstyrken om du vil) afhænger af den benyttede værdi.

Bruger du fx. pixelformatet pf15bit, så gemmes der for hver pixel 5 bit til farverne R, G og B.  Du har dermed 2^5 = 32 varianseer for hver farve, hvilket resulterer i ialt 32768 farvekombinationer.  Dataene vil være pakket lidt specielt:

B value for pixel 0: Byte 0, bit 7-3.
G value for pixel 0: Byte 0, bit 2-0 + Byte 1, bit7-6.
R value for pixel 0: Byte 1, bit 5-1
B value for pixel 1: Byte 1, bit 0 + Byte 2, bit 7-4.
G value for pixel 0: Byte 2, 3-0 + Byte 3, bit 7
R value for pixel 0: Byte 3, bit 6-2
etc.

Som du kan se, så skal du faktisk ikke betragte en scanline som en byte stream/array, men som en bit stream.  Så skal du med bitvis udmaskning og shift operationer trække RGB værdier ud for de enkelte pixels.  Kun ved pixelformat pf8Bit, pf24Bit og pf32Bit passer det med at hver farves værdi er pakket som rene bytes - derfor er de også så hyppigt benyttede formater.

Peter
Avatar billede delphi Nybegynder
06. april 2001 - 12:48 #26
... hvis du sætter værdierne for R, G og B så ...

skulle være:

... hvis du sætter værdierne for R, G og B ENS så ...


der er også lidt ged for G og R værdierne for pixel 1 (et - ikke nul) i pf15Bit forklaringen.

Peter

(Hvorfor skal jeg altid læse korrektur på mine indlæg....)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester