Toon posts:

[Kylix] Bitmap wordt niet goed getoond i.c.m. scanline

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben bezig om onder linux een plaatje te capture'n i.c.m. Kylix. (capture kaart en ccd camera)

Dit lukt nu aardig. Ik heb inmiddels het plaatje op het scherm. Echter het probleem is dat als ik het plaatje dat in het geheugen staat in een bitmap wil zetten dit enorm lang duurt met de property Pixels[X Y] := ....

Ik heb daarom gebruik gemaakt van de functie ScanLine. Dit gaat razend snel. Er is alleen 1 probleem. De breedte van het plaatje klopt niet meer.

Weet iemand waar dat door kan komen?

Kylix code:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  Bitmap := TBitmap.Create;
  try
    Image1.Width := Capture_Width;
    Image1.Height := Capture_Height;
    Bitmap.Width := Capture_Width;
    Bitmap.Height := Capture_Height;

    i := Integer(map);
    for y := 0 to Capture_Height - 1 do
    begin
      PSL := BitMap.ScanLine[y];
      for x := 0 to Capture_Width - 1 do
      begin
        //R := Byte(Ptr(i + 2)^);
        //G := Byte(Ptr(i + 1)^);
        B := Byte(Ptr(i)^);

        //Bitmap.Canvas.Pixels[X, Y] := TColor((B * 65536) + (G * 256) + R); // BGR
        PSL[X] := TColor((B * 65536) + (B * 256) + B); // BGR

        i := i + 1;
      end;
    end;

    Image1.Canvas.Draw(0, 0, Bitmap);
  finally
    Bitmap.Free;
  end;


(Het plaatje dat gecaptured wordt is 8 bits, grijs.)

Verwijderd

Als je middels scanline wilt kopiëeren dien je rekening te houden met beide PixelFormats. Als het ene plaatje bijv. 8-bits is en het andere 24-bits dan moet je bij de tweede 3 bytes vullen terwijl je slechts één byte leest.

Verwijderd

Topicstarter
Klopt, ik was vergeten om aan te geven:

Bitmap.PixelFormat := pf8bit;

Nu is het plaatje kwa grootte wel goed, alleen zijn de kleuren totaal verkeerd. (Ik zie rood, groen, blauw, wit i.p.v. grijs tinten)

Het is een 8 Bits, grijs plaatje.

Moet je hiervoor een speciale omrekings functie voor gebruiken?

  • Brothar
  • Registratie: Oktober 2000
  • Laatst online: 04-02 09:14

Brothar

meester

1 byte: maximaal x kleuren; x = 2^8
3 bytes maximaal 2^24 kleuren
Toch ?

Het oude pascal gebruikte ook nog een palet, ik vermoedt dat dat in Kylix/Delphi niet anders zal zijn.

[ Voor 33% gewijzigd door Brothar op 03-03-2003 15:51 ]

eagle


Verwijderd

Topicstarter
Brothar schreef op 03 maart 2003 @ 15:50:
1 byte: maximaal x kleuren; x = 2^8
3 bytes maximaal 2^24 kleuren
Toch ?
Klopt dat weet ik. Maar de vraag is waarom ik geen grijs tinten te zien krijg in het plaatje?

Ik lees de pixel waarden uit het geheugen uit. Dat is 1 Byte, omdat ik gebruik maak van een 8 bits plaatje.

Vervolgens ken die byte waarde toen aan:

PSL[X] := B;

Heb je hiervoor een speciale omreken formule voor nodig?

Verwijderd

Topicstarter
Ik krijg nu dit plaatje te zien.

Ziet iemand misschien waardoor dit fout gaat? (8 bits grijs plaatje ==> wordt kleur)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Verwijderd schreef op 04 maart 2003 @ 12:08:
Ik krijg nu dit plaatje te zien.

Ziet iemand misschien waardoor dit fout gaat? (8 bits grijs plaatje ==> wordt kleur)
Kwil niet moeilijk doen maar bij mij is dat plaatje een groot zwart vlak :?

Professionele website nodig?


Verwijderd

Topicstarter
Wat me wel opvalt is dat het plaatje er op verschillende computer anders uit ziet (2 linux computers met het zelfde systeem en een windows bak).

Er zijn 2 manieren waarop ik het plaatje kan creeeren:

1) Kylix code
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  Bitmap := TBitmap.Create;
  try
    Image1.Width := Capture_Width;
    Image1.Height := Capture_Height;
    Bitmap.Width := Capture_Width;
    Bitmap.Height := Capture_Height;
    Bitmap.PixelFormat := pf8bit;

    i := Integer(map);
    for y := 0 to Capture_Height - 1 do
    begin
      //PSL := BitMap.ScanLine[y];
      for x := 0 to Capture_Width - 1 do
      begin
        //R := Byte(Ptr(i + 2)^);
        //G := Byte(Ptr(i + 1)^);
        B := Byte(Ptr(i)^);

        Bitmap.Canvas.Pixels[X, Y] := TColor((B * 65536) + (B * 256) + B); // BGR
        //PSL[X] := TColor((B * 65536) + (B * 256) + B); // BGR

        i := i + 1;
      end;
    end;

    Image1.Picture.Graphic := Bitmap;
  finally
    Bitmap.Free;
  end;


2) Kylix code
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  Bitmap := TBitmap.Create;
  try
    Image1.Width := Capture_Width;
    Image1.Height := Capture_Height;
    Bitmap.Width := Capture_Width;
    Bitmap.Height := Capture_Height;
    Bitmap.PixelFormat := pf8bit;

    i := Integer(map);
    for y := 0 to Capture_Height - 1 do
    begin
      PSL := BitMap.ScanLine[y];
      for x := 0 to Capture_Width - 1 do
      begin
        //R := Byte(Ptr(i + 2)^);
        //G := Byte(Ptr(i + 1)^);
        B := Byte(Ptr(i)^);

        //Bitmap.Canvas.Pixels[X, Y] := TColor((B * 65536) + (B * 256) + B); // BGR
        PSL[X] := TColor((B * 65536) + (B * 256) + B); // BGR

        i := i + 1;
      end;
    end;

    Image1.Picture.Graphic := Bitmap;
  finally
    Bitmap.Free;
  end;


De 1e methode werkt gewoon goed. Ik krijg dan een grijs plaatje te zien.
Echter deze methode is super traaaaag.

Bij de 2e methode krijg ik dus dat rare plaatje te zien. Alleen deze methode is wel super snel. Dus ik wil gebruik gaan maken van deze methode. Maar de vraag is waarom worden de kleuren anders getoond (verkeerd) dan bij de 1e methode.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 23-08 21:27

Creepy

Tactical Espionage Splatterer

Ik gok dat je de waarde die je toekent aan PSL[x] NIET moet omzetten naar een TColor aangezien deze waarde echt de "low-level" waarde is.

code:
1
property ScanLine[Row: Integer]: Pointer;

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

Topicstarter
Ook als ik die byte die ik uitlees uit het geheugen direct toeken aan de scanline array, zonder hem eerst om te zetten naar een TColor, krijg ik nog van die rare kleuren te zien.

  • Elissen
  • Registratie: Januari 2000
  • Laatst online: 27-07 15:54
Ik zie niet dat je de bitmap op grijswaarden zet.
code:
1
Bitmap.Monochrome := true;

Misschien is dat het?

Verwijderd

Topicstarter
Elissen schreef op 04 March 2003 @ 13:35:
Ik zie niet dat je de bitmap op grijswaarden zet.
code:
1
Bitmap.Monochrome := true;

Misschien is dat het?
Nee, ook dat heb ik al geprobeerd en maakt niks uit.

Verwijderd

Topicstarter
Maar hoe kan het nou dat ik een plaatje krijg met kleuren, als ik de bitmap ingesteld heb in 8 bits monochroom.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 23-08 21:27

Creepy

Tactical Espionage Splatterer

Verwijderd schreef op 04 maart 2003 @ 15:15:
Maar hoe kan het nou dat ik een plaatje krijg met kleuren, als ik de bitmap ingesteld heb in 8 bits monochroom.
Geen idee, maar in de scanline gooi je toch echt 32 bits waarden i.p.v. 8 bits!

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

Ben ff aan het proggen geslagen en hiermee lukte het me om een kopietje te trekken. Ik heb niet echt op lay-out van code en netheid gelet, maar dat kun je vast zelf wel:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
procedure TForm1.Button1Click(Sender: TObject);
type
  TPalette = packed record
    palVersion: Word;
    palNumEntries: Word;
    palPalEntry: array[0..255] of TPaletteEntry;
  end;
var
  B: TBitmap;
  X,
  Y: Integer;
  pbaOrg,
  pbaNew: PByteArray;
  palPalette: TPalette;
  LogPalette: PLogPalette;
  palHandle: HPALETTE;
begin
  Image1.Picture.LoadFromFile('GrayBMP.bmp');
  Image1.Picture.Bitmap.PixelFormat := pf8bit;
  B:=TBitmap.Create;
  try
    B.PixelFormat := pf8bit;
    palPalette.palVersion := $300;
    palPalette.palNumEntries := 256;
    for X:=0 to 255 do
    begin
      palPalette.palPalEntry[X].peRed := X;
      palPalette.palPalEntry[X].peGreen := X;
      palPalette.palPalEntry[X].peBlue := X;
      palPalette.palPalEntry[X].peFlags := 0;
    end;
    LogPalette := @palPalette;
    palHandle := CreatePalette(LogPalette^);
    try
       B.Palette := palHandle;
       B.Width := Image1.Picture.Width;
       B.Height := Image1.Picture.Height;
       for Y:=0 to Image1.Picture.Height-1 do
       begin
         pbaOrg:=Image1.Picture.Bitmap.ScanLine[Y];
         pbaNew:=B.ScanLine[Y];
         for X:=0 to Image1.Picture.Width-1 do
           pbaNew^[X]:=pbaOrg^[X];
       end;
       Self.Canvas.Draw(0, 0, B);
     finally
        B.Free;
     end;
  finally
    DeleteObject(palHandle);
  end;
end;

PS: Dit is Delphi-code en GEEN kylix, maar ik ga ervan uit dat dit ook onder Kylix werkt.

Verwijderd

Topicstarter
Creepy schreef op 04 March 2003 @ 15:46:Geen idee, maar in de scanline gooi je toch echt 32 bits waarden i.p.v. 8 bits!
Je maakt toch gebruik van de PByteArray en die is 8 bits.


hvdberg:

Deze code kan ik helaas niet gebruiken, omdat kylix de typen TPaletteEntry, PLogPalette en HPALETTE niet kent.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 23-08 21:27

Creepy

Tactical Espionage Splatterer

Verwijderd schreef op 04 March 2003 @ 16:03:
[...]
Je maakt toch gebruik van de PByteArray en die is 8 bits.
Die PByteArray mis ik ff, maar een TColor is 32 bits.
hvdberg:

Deze code kan ik helaas niet gebruiken, omdat kylix de typen TPaletteEntry, PLogPalette en HPALETTE niet kent.
HPALETTE is een typisch windows iets ;)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Elissen
  • Registratie: Januari 2000
  • Laatst online: 27-07 15:54
Verwijderd schreef op 04 March 2003 @ 16:03:
[...]
Je maakt toch gebruik van de PByteArray en die is 8 bits.
[...]
Maar je zit wel low-level op de data met een pointer. En ik denk niet dat dat gecontroleerd word. Trouwens, ScanLine geeft gewoon een pointer, dus Kilix weet niet eens dat er eigenlijk bytes in moeten.
Maareh, is het niet mogelijk om met memcopy heel bot gewoon te kopieeren. CopyMemory(van, naar, hoeveel); ?
Wellicht heb je dan wel BytesPerScanline (Graphics.pas) nodig.

Verwijderd

Even code aangepast zodat die ook op Kylix werkt.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
procedure TForm1.Button1Click(Sender: TObject);
var
  B: TBitmap;
  X,
  Y: Integer;
  pbaOrg,
  pbaNew: PByteArray;
begin
  Image1.Picture.LoadFromFile('GrayBMP.bmp');
  Image1.Picture.Bitmap.PixelFormat := pf8bit;
  B:=TBitmap.Create;
  try
    B.PixelFormat := pf24bit;
    B.Width := Image1.Picture.Width;
    B.Height := Image1.Picture.Height;
    for Y:=0 to Image1.Picture.Height-1 do
    begin
      pbaOrg:=Image1.Picture.Bitmap.ScanLine[Y];
      pbaNew:=B.ScanLine[Y];
      for X:=0 to Image1.Picture.Width-1 do
      begin
        pbaNew^[X*3]:=pbaOrg^[X];
        pbaNew^[(X*3)+1]:=pbaOrg^[X];
        pbaNew^[(X*3)+2]:=pbaOrg^[X];
      end;
      Self.Canvas.Draw(0, 0, B);
    finally
      B.Free;
    end;
end;

En zo kun je meteen zien waar de ByteArray voor dient!

Verwijderd

Topicstarter
Bedankt voor de hulp alvast.

Ik ga morgen weer verder op mijn werk.

Verwijderd

Topicstarter
Ik ben weer verder gegaan aan het capturen.

Ik heb inmiddels nu op de snelle manier een goed plaatje op mijn scherm. Echter ik capture nu het plaatje op 32 bit RGB. Ook de bitmap is nu 32 bit RGB.

Aangezien wij voor ons systeem alleen maar gaan werken met grijs waarden, willen wij het plaatje capturen als 8 bit grey. Ook de bitmap moet dan dus 8 bit zijn.

Als ik alles instel als 32 bit werkt het dus perfect met de volgende code:

Kylix code:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  Bitmap := TBitmap.Create;
  try
    Image1.Width := Capture_Width;
    Image1.Height := Capture_Height;
    Bitmap.Width := Capture_Width;
    Bitmap.Height := Capture_Height;
    Bitmap.PixelFormat := pf32bit;
    //Bitmap.Monochrome := True;

    i := Integer(map);
    edt_AantalBytesPerLine.Text := IntToStr(Abs(Integer(Bitmap.ScanLine[1]) - Integer(Bitmap.ScanLine[0])));
    Move(Map^, (Bitmap.ScanLine[0])^, Capture_Width * Capture_Height * Aantal_Bytes);

    // Uitlezen uit het geheugen
    i := i + (50 * Capture_Width * Aantal_Bytes) + (600 * Aantal_Bytes);
    edt_KleurCode1.Text := IntToStr(Byte(Ptr(i)^));

    // Uitlezen uit de bitmap
    P := Bitmap.ScanLine[0];
    i := Integer(P);
    i := i + (50 * Capture_Width * Aantal_Bytes) + (600 * Aantal_Bytes);
    edt_KleurCode2.Text := IntToStr(Byte(Ptr(i)^));

    Image1.Picture.Graphic := Bitmap;
  finally
    Bitmap.Free;
  end;


Als ik het verander in 8 bit opeens niet meer.

Wat kan dat nou zijn?

Als ik nu het plaatje op 8 bit capture en in een bitmap zet die als PixelFormat ingesteld staat op: Bitmap.PixelFormat := pfCustom; dan krijg ik dit plaatje te zien.

[ Voor 9% gewijzigd door Verwijderd op 05-03-2003 14:39 ]

Pagina: 1