Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Pixel zählen mit Scanline (https://www.delphipraxis.net/168105-pixel-zaehlen-mit-scanline.html)

Jazzman_Marburg 4. Mai 2012 20:09

Pixel zählen mit Scanline
 
Hallo Gemeinde,
ich versuche gerade alle schwarzen Pixel in einem Image (TImage) zu zählen. Mit Canvas.Pixels geht es wohl -- nur eben langsam. Deswegen versuche ich auf ScanLine umzustellen, und das geht nun gründlich schief. Habe mir diverse Tutorials angeschaut und war meiner Sache sicher -- aber mit ScanLine zähle ich wohl etwas anderes. Deswegen meine Frage/Bitte ob jemand wohl den Fehler sieht?

Delphi-Quellcode:
 type
    TIntegerArray = array[0..MaxInt div SizeOf(integer) - 1] of integer;
    PIntegerArray = ^TIntegerArray;
  ...

 
  Anzahl := 0;
  Anzahl2 := 0;

  k:= myImage.Width;
  l:= myImage.Height;

  { Canvas.Pixels Version ------------------------------------- }
  for x := 0 to k - 1 do
  begin

    for y := 0 to l - 1 do
    begin

      color := myImage.Canvas.Pixels[ x, y ];
      if color = clBlack then
        inc(Anzahl);

    end;

  end;

  { ScanLine Version ------------------------------------------- }
  for y := 0 to l - 1 do
  begin

    ScanLine := myImage.Picture.Bitmap.ScanLine[ y ];
    for x := 0 to k - 1 do
    begin
     
      ScanLine^[x] := color;
      color := BGRToColor( color );
      if color = ClBlack then
        inc( Anzahl2 );

    end;

  end;
 
function BGRToColor(const BGR : Integer) : TColor;
begin
 result := (BGR and $FF000000) + ((BGR and $000000FF) shl 16) + (BGR and $0000FF00) + ((BGR and $00FF0000) shr 16);
end;
Eine Idee, weshalb das Scanline z.B. 489202 für Anzahl2 liefert -- Canvas.Pixels hingegen 5450 (was wohl richtiger ist)?

Vielen Dank
Gruß
Jazzman

Aphton 4. Mai 2012 20:33

AW: Pixel zählen mit Scanline
 
Integer hat die Größe 4, RGBTriple 3

Wenn du auf ein typisiertes Array mit Typengröße 4 (Integer) zugreifst, so greifst du letzendlich so auf den Speicher:
[i] = [<Typengröße>*i] (bei Integer eben 4)


i - index
0 - 0
1 - 4
2 - 8
3 - 12
usw

Jedoch darfste eben nicht in diesen Viererschritten auf den Speicher zugreifen (sondern in Dreierschritten).
TRGBTriple eignet sich dafür gut!

Jazzman_Marburg 4. Mai 2012 20:46

AW: Pixel zählen mit Scanline
 
Zitat:

Zitat von Aphton (Beitrag 1164942)
TRGBTriple eignet sich dafür gut!

Aha! :-D

Wieder was dazugelernt!

Vielen Dank Aphton.

Gruß
Jazzman

himitsu 4. Mai 2012 21:45

AW: Pixel zählen mit Scanline
 
Und auch nur, wenn man auf ein 3*8-Bit-RGB-Pixel drauf zugreift.

32 Bit pro Pixel sind 4 Byte
24 Bit nur 3 Byte (RGB)
und dann gibt es auch noch andere Formate


Delphi-Quellcode:
      ScanLine^[x] := color;
      color := BGRToColor( color );
      if color = ClBlack then
        inc( Anzahl2 );
Willst du dir Pixel auf eine Zufallsfarbe setzen oder zählen?

Jazzman_Marburg 4. Mai 2012 21:48

AW: Pixel zählen mit Scanline
 
Zählen! :shock:

himitsu 4. Mai 2012 22:09

AW: Pixel zählen mit Scanline
 
Dann stimmt in dem Code was nicht. :zwinker:

Bummi 4. Mai 2012 23:14

AW: Pixel zählen mit Scanline
 
nicht vollständig, aber als Ansatz ....
Delphi-Quellcode:
type
  pRGBTripleArray = ^TRGBTripleArray;
  TRGBTripleArray = ARRAY[0..$effffff] OF TRGBTriple;
  pRGBQuadArray = ^TRGBQuadArray;
  TRGBQuadArray = ARRAY[0..$effffff] OF TRGBQuad;

Function CountBlack24(Bitmap: TBitmap):Integer;
var
  X, Y: Integer;
  NUL:TRGBTriple;
  pLine: pRGBTripleArray;
begin
  NUl.rgbtBlue := 0;
  NUl.rgbtGreen := 0;
  NUl.rgbtRed := 0;
  Result := 0;
  for Y := 0 to Bitmap.Height -1 do
  begin
    pLine := Bitmap.ScanLine[Y];
    for X := 0 to Bitmap.Width -1 do
      if (pLine[X].rgbtBlue=0) and (pLine[X].rgbtred=0) and (pLine[X].rgbtgreen=0) then inc(Result);
  end;
end;


Function CountBlack32(Bitmap: TBitmap):Integer;
var
  X, Y: Integer;
  pLine: pRGBQuadArray;
begin
  Result := 0;
  for Y := 0 to Bitmap.Height -1 do
  begin
    pLine := Bitmap.ScanLine[Y];
    for X := 0 to Bitmap.Width -1 do
      if (pLine[X].rgbBlue=0) and (pLine[X].rgbred=0) and (pLine[X].rgbgreen=0) then inc(result);
  end;
end;

Function CountBlack(Bitmap: TBitmap):Integer;
begin
  if Bitmap.PixelFormat=pf24bit then Result := CountBlack24(Bitmap)
  else Result:=CountBlack32(Bitmap)

end;


procedure TForm2.Button1Click(Sender: TObject);
var
 i:Integer;
begin
  for I := 0 to Image1.Width do

  image1.Canvas.Pixels[i,i] := clBlack;
  image1.Picture.Bitmap.PixelFormat := pf24bit;
  Showmessage(IntToStr(CountBlack(image1.Picture.Bitmap)));
  image1.Picture.Bitmap.PixelFormat := pf32bit;
  Showmessage(IntToStr(CountBlack(image1.Picture.Bitmap)));

end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:10 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz