![]() |
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:
und so:
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;
Delphi-Quellcode:
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.
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 (Apropos: Das ganze ist mit DelphiX in einem TSprite) Was mache ich falsch? :gruebel: |
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.
|
Re: Scanline lahm??
Delphi-Quellcode:
Die tut's bei mir recht schnell.
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; |
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:
Jetzt müsste man nur noch wissen was Cut() für eine function ist?
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; mfg Phantom1 |
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; |
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; |
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:
Wenn du aufhellen möchtest, dann einfach in Zeile 10 statt PSUBUSB PADDUSB verwenden.
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; |
Re: Scanline lahm??
Ab D6 wird schon SSE2 unterstützt, inklusive allem was drunterliegt.. Also SSE, 3DNow!, MMX (klar..)...
|
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:
Was wird hier anders gemacht?
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; |
Re: Scanline lahm??
Zitat:
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. |
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