Delphi-PRAXiS

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.

igel457 9. Okt 2005 10:45

Re: Scanline lahm??
 
Komisch...

Wenn ich meinen Code vom Anfang in eine extra Funktion packe, dann geht es... :gruebel:

Na ja.

Ich denke das Problem wäre damit geklärt. :wink:

Vieleicht hatte ich in meine alten Funktion irgendwelche Variablen schon verwendet. :wall:

Danke trotzdem! :bounce1:

//Edit:

@turboPASCAL:

Das ganze soll so funktionieren: Ich habe eine Art "Heightmap" und deshalb hat mein Bild nicht an jeder Stelle den gleichen Gammawert.

Wenn ich mir deine Funktion richtig angesehen habe, dann hellt die das ganze Bild auf/ab.

turboPASCAL 9. Okt 2005 11:08

Re: Scanline lahm??
 
Das kann am Pixelformat liegen meine Methode braucht 24 Bit. (habe das oben geändert)

Airblader 9. Okt 2005 12:06

Re: Scanline lahm??
 
Zitat:

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

Ist das wahr? :shock:
So kann dann ja NUR noch 255 oder 0 rauskommen :gruebel:
Du willst doch sicherlich nur die Grenzen prüfen, oder etwa nich?

air

igel457 9. Okt 2005 16:17

Re: Scanline lahm??
 
Ja, da hattest du recht. Hab ich mich wohl verschrieben :oops:


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:39 Uhr.

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