Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Scanline lahm?? (https://www.delphipraxis.net/54645-scanline-lahm.html)

igel457 8. Okt 2005 18:21


Scanline lahm??
 
Ich habe folgendes Problem:

in meinem Spiel sollen bestimmte Teile der Hintergrundgrafik aufgehellt/abgedunkelt werden.

Ich versuche das so:
(buffer ist ein TBitmap)
Delphi-Quellcode:
  for oy := 0 to buffer.Height-1 do
  begin
    row := buffer.ScanLine[oy];
    for ox := 0 to buffer.Width-1 do
    begin
      gamma := 10;
      if gamma <> 0 then
      begin
        b := cut(row[ox].rgbtBlue+gamma);
        g := cut(row[ox].rgbtGreen+gamma);
        r := cut(row[ox].rgbtRed+gamma);
        row[ox].rgbtBlue := b;
        row[ox].rgbtGreen := g;
        row[ox].rgbtRed := r;
      end;
    end;
  end;
und so:
Delphi-Quellcode:
type
  TRGBTripleArray = array[0..32768] of TRGBTriple;
  // 32768 = maximale Anzahl der Pixel in der Breite eines Bildes (also eine "ScanLine")
  pRGBTripleArray = ^TRGBTripleArray; // Pointer auf TRGBTripleArray
Doch leider ist das furchtbar lahm! Ich brauche für ein 1024x768 großes bild eine halbe Minute! Dabei hatte ich schon öfters ScanLine verwendet, und da war das nicht so lahm.

(Apropos: Das ganze ist mit DelphiX in einem TSprite)

Was mache ich falsch? :gruebel:

Dax 8. Okt 2005 18:25

Re: Scanline lahm??
 
Dein Code ist ziemlich ineffizient ;) Wenn du aufhellen/abdunkeln-Additionen statt so mit MMX oder SSE lösen würdest, dürfte es schon ein gutes Stück schneller werden.

turboPASCAL 8. Okt 2005 18:52

Re: Scanline lahm??
 
Delphi-Quellcode:
procedure MakeDarker(Bitmap: TBitmap; const dp: Byte = 10);
var
  PixelLine: PByteArray;
  x, y: integer;
begin
  if Bitmap.PixelFormat <> pf24Bit then
    Bitmap.PixelFormat := pf24Bit;

  for y := 0 to Bitmap.height - 1 do
  begin
    PixelLine := Bitmap.ScanLine[y];
    for x := 0 to (Bitmap.width * 3) - 1 do
       PixelLine^[x] := PixelLine^[x] - round(PixelLine^[x] / dp);
  end;
end;
Die tut's bei mir recht schnell.

Phantom1 8. Okt 2005 18:53

Re: Scanline lahm??
 
Als erstes würde ich 32bit anstatt 24bit Farbtiefe verwenden, bringt schonmal ein einiges.

Und dann noch ein paar Sachen:
Delphi-Quellcode:
var
  p: PRGBQuad;
...
  Buffer.PixelFormat:=pf32bit;
  p:=Buffer.ScanLine[Buffer.Height-1];
  gamma := 10;

  if gamma <> 0 then
    for x := 0 to buffer.Width*buffer.Height-1 do
    begin
      p^.rgbBlue := cut(p^.rgbBlue+gamma);
      p^.rgbGreen := cut(p^.rgbGreen+gamma);
      p^.rgbRed := cut(p^.rgbRed+gamma);
      Inc(p);
    end;
Jetzt müsste man nur noch wissen was Cut() für eine function ist?

mfg
Phantom1

igel457 8. Okt 2005 18:58

Re: Scanline lahm??
 
Ich verstehe das schon, es wäre wirklich besser Zeile für Zeile abzudunklen, anstatt Pixel für Pixel.

Leider wird nicht das gesammte Bild dunkler, sondern nur an einigen Stellen.

gamma wird erst noch ausgerechnet (hab ich vergessen zu sagen :wall: )

@Phantom1
Delphi-Quellcode:
function Cut(AValue:integer):byte;
begin
  result := AValue;
  if AValue > 255 then result := 255;
  if AValue < 0 then result := 0;
end;

Phantom1 8. Okt 2005 19:22

Re: Scanline lahm??
 
Die Cut function könntest du auch noch verbessern (wenn auch nur minimal),
zb so hier:
Delphi-Quellcode:
function Cut(AValue: Integer): Byte;
begin
  if AValue > 255 then
    Result := 255
  else
    if AValue < 0 then
      Result := 0
    else
      Result := AValue;
end;

dizzy 9. Okt 2005 00:49

Re: Scanline lahm??
 
Die Cut-Funktion könntest du mit MMX sogar komplett weglassen. Hier mal ein ASM-Beispiel (Achtung! Delphi kennt die MMX-Mnemonics meine ich erst ab D7):
Voraussetzung: Farbe in 32Bit
Delphi-Quellcode:
function Darken(Color: LongInt; Value: Byte): LongInt;
// EAX=Color; EDX=Value
asm
        // MMX-Register befüllen
        MOVD       MM1, EAX
        PUNPCKLBW  MM1, MM0
        MOVD       MM2, EDX
        PSHUFW     MM2, MM2, 0
        // Wert von Value von allen RGB abziehen, wenn 0 erreicht 0 belassen
        PSUBUSB    MM1, MM2
        // Ergebnis zurückschreiben
        PACKUSWB   MM1, MM0
        MOVD       EAX, MM1
        // FPU zurücksetzen
        EMMS
end;
Wenn du aufhellen möchtest, dann einfach in Zeile 10 statt PSUBUSB PADDUSB verwenden.

Dax 9. Okt 2005 00:58

Re: Scanline lahm??
 
Ab D6 wird schon SSE2 unterstützt, inklusive allem was drunterliegt.. Also SSE, 3DNow!, MMX (klar..)...

igel457 9. Okt 2005 09:06

Re: Scanline lahm??
 
Also das mit Assembler lass ich lieber, damit kenn ich mich nämlich überhaupt ger nicht aus.

Komischerweise funktioniert folgende Funktion ohne Probleme. Die macht natürlich nicht das was ich will, aber diese Funktion geht:

Delphi-Quellcode:
procedure Antialiasing(const DC: TCanvas; const Rectangle: TRect);
var
  cx, cy: Smallint;
  r, g, b: Byte;
  Row1: pRGBTripleArray;
  Row2: pRGBTripleArray;
  Row3: pRGBTripleArray;
  TEMP: TBitmap;
  CurRect: TRect;
begin
  TEMP := TBitmap.Create;
  try
    with TEMP do begin
      Width := Rectangle.Right - Rectangle.Left;
      Height := Rectangle.Bottom - Rectangle.Top;
      CurRect := Rect(0, 0, Width, Height);
      PixelFormat := pf24Bit;
      Canvas.CopyRect(CurRect, DC, Rectangle);
      with Canvas do begin
        for cy := 1 to (Height - 2) do begin
          Row1 := ScanLine[cy - 1];
          Row2 := ScanLine[cy];
          Row3 := ScanLine[cy + 1];

          for cx := 1 to (Width - 2) do begin
            r := (Row1[cx - 1].rgbtRed+Row1[cx].rgbtRed+
            Row1[cx + 1].rgbtRed+
            Row2[cx - 1].rgbtRed+
            Row2[cx + 1].rgbtRed+
            Row2[cx - 1].rgbtRed+
            Row3[cx].rgbtRed+
            Row3[cx + 1].rgbtRed+
            Row3[cx].rgbtRed) div 9;

            g := (Row1[cx - 1].rgbtGreen+
            Row1[cx].rgbtGreen+
            Row1[cx + 1].rgbtGreen+
            Row2[cx - 1].rgbtGreen+
            Row2[cx + 1].rgbtGreen+
            Row2[cx - 1].rgbtGreen+
            Row3[cx].rgbtGreen+
            Row3[cx + 1].rgbtGreen+
            Row3[cx].rgbtGreen) div 9;

            b := (Row1[cx - 1].rgbtBlue+
            Row1[cx].rgbtBlue+
            Row1[cx + 1].rgbtBlue+
            Row2[cx - 1].rgbtBlue+
            Row2[cx + 1].rgbtBlue+
            Row2[cx - 1].rgbtBlue+
            Row3[cx].rgbtBlue+
            Row3[cx + 1].rgbtBlue+
            Row3[cx].rgbtBlue) div 9;
            Row2[cx].rgbtBlue := b;
            Row2[cx].rgbtGreen := g;
            Row2[cx].rgbtRed := r;
          end;
        end;
      end;
      DC.CopyRect(Rectangle, Canvas, CurRect);
    end;
  finally
    TEMP.Free;
  end;
end;
Was wird hier anders gemacht?

turboPASCAL 9. Okt 2005 10:42

Re: Scanline lahm??
 
Zitat:

Leider wird nicht das gesammte Bild dunkler, sondern nur an einigen Stellen.
Wenn du auf meine damit ansprichst, welchen Wert hast du eingesetzt? Werte wie 1..10 sind bei
der Procedure MakeDarker schon ok. und machen keine Probleme. Es ist aber keine genaue
Gammawert berechnung.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:24 Uhr.
Seite 1 von 2  1 2      

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