Autor |
Beitrag |
SixpointedStarsoft
      
Beiträge: 22
Erhaltene Danke: 1
|
Verfasst: Sa 02.01.10 12:06
Hallo Zusammen
Ich habe ein Coloralphablending geschrieben, das heisst ein oberer und ein unterer Farbepixel mittels einer Blendfunktion vermischen, wie dies Windows.Alphablend macht. Der Code funktioniert, möchte ihn aber beschleunigen. Assembler wäre eine Möglichkeit, leider beherrsche ich das nicht. Meine Fragen sind also:
• Hat jemand eine Idee, wie man den Delphicode verbessern kann?
• Hat jemand Kentnisse, wie man das in Assembler schreiben könnte? (Oder dauert das lange dies zu erlernen?)
Hier der 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:
| procedure ColorAlphablending(var FarbeUntere: TColor32; FarbeObere : TColor32; AlphablendingWert:Real); function ToColor32(R, G, B: Byte; A: Byte = $FF): TColor32; asm MOV AH,A SHL EAX,16 MOV AH,DL MOV AL,CL end; var RU,GU,BU,RO,GO,BO : Byte; AU,AO: real; NeuerAlphaWert: real; antiAlpha: real; A3: byte;
begin AU := (FarbeUntere shr 24)/255; RU := (FarbeUntere and $00FF0000) shr 16; GU := (FarbeUntere and $0000FF00) shr 8; BU := FarbeUntere and $000000FF;
AO := (FarbeObere shr 24)/255*AlphablendingWert; RO := (FarbeObere and $00FF0000) shr 16; GO := (FarbeObere and $0000FF00) shr 8; BO := FarbeObere and $000000FF;
antiAlpha := 1 - AO; NeuerAlphaWert := AO+AU - AO * AU; A3:= Round(255*NeuerAlphaWert);
RU := Round(antiAlpha*RU+ NeuerAlphaWert*RO); BU := Round(antiAlpha*BU+ NeuerAlphaWert*BO); GU := Round(antiAlpha*GU+ NeuerAlphaWert*GO);
FarbeUntere:=ToColor32(RU,GU,BU,A3); end; |
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 02.01.10 12:28
Wie rufst du denn die Funktion auf? Denn die macht das ja pixelweise. Wenn du über Canvas.Pixels iterierst, dann liegt da der (sehr deutliche) Flaschenhals.
_________________ We are, we were and will not be.
|
|
j.klugmann
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 02.01.10 12:30
Noch eine Möglichkeit wäre , SSE statt normales Assembler zu nehmen.Gausi hat aber recht , durch SSE wird es dann auch nicht viel schneller.
|
|
SixpointedStarsoft 
      
Beiträge: 22
Erhaltene Danke: 1
|
Verfasst: Sa 02.01.10 13:51
Gausi hat folgendes geschrieben : | Wie rufst du denn die Funktion auf? Denn die macht das ja pixelweise. Wenn du über Canvas.Pixels iterierst, dann liegt da der (sehr deutliche) Flaschenhals. |
Also ich rufe die Procedur wie folgt auf:
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:
| procedure CopyTo( const BmpDest: TBitmap32; nXOriginDest: integer; nYOriginDest: integer; nWidthDest: integer; nHeightDest: integer; const BmpSrc: TBitmap32; nXOriginSrc: integer; nYOriginSrc: integer; nWidthSrc: integer; nHeightSrc: integer); var X,Y,W: Integer; P, PDest: PColor32Array; begin W:= BmpDest.Width; for Y := 0 to nHeightSrc-1 do begin
P := @BmpSrc.Bits[(nYOriginSrc+Y) * BmpSrc.Width]; PDest:= @BmpDest.Bits[(nYOriginDest+Y) * W];
for X := 0 to nWidthSrc - 1 do if P[nXOriginSrc+X] <> 0 then if (PDest[nXOriginDest + X] <>0) then if ((P[nXOriginSrc+X] shr 24) <> 255) then ColorAlphablending(PDest[nXOriginDest + X],P[nXOriginSrc+X],1) else PDest[nXOriginDest + X]:= P[nXOriginSrc+X] else PDest[nXOriginDest + X]:= P[nXOriginSrc+X]; end; end; |
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 02.01.10 14:01
Wenn du ScanLine benutzt, dann sparst du dir die ganzen Arrayzugriffe. Auch wenn der Geschwindigkeitszuwachs vermutlich nicht so hoch wie beim originalen TBitmap ist, denke ich trotzdem, dass es etwas bringen kann.
Und da du ohnehin schon mit Pointern arbeitest, ist das ja auch nicht mehr so viel anders.
|
|
SixpointedStarsoft 
      
Beiträge: 22
Erhaltene Danke: 1
|
Verfasst: Sa 02.01.10 14:14
jaenicke hat folgendes geschrieben : | Wenn du ScanLine benutzt, dann sparst du dir die ganzen Arrayzugriffe. Auch wenn der Geschwindigkeitszuwachs vermutlich nicht so hoch wie beim originalen TBitmap ist, denke ich trotzdem, dass es etwas bringen kann.
Und da du ohnehin schon mit Pointern arbeitest, ist das ja auch nicht mehr so viel anders. |
Scanline macht nichts anderes, denn scanline ist wie folgt aufgebaut:
Delphi-Quelltext 1: 2: 3: 4:
| function TBitmap32.GetScanLine(Y: Integer): PColor32Array; begin Result := @Bits[Y * FWidth]; end; |
desshalb habe ich daruaf versichtet diese Funktion aufzurufen, da dies schon wieder mehr Zeit in Anspruch nimmt. Nach meiner Zeitmessung schnellt, mit jedem solchen Aufruf die Zeit in die Höhe.
Im Moment arbeitet diese Procedure schneller als das Windows.Alphablend es tut (natürlich in der Art und Weise wie ich es gebrauche mit meinen Bildern). Sobald aber alle Pixel "geblendet werden müssen" ist Windows schneller.
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 02.01.10 15:03
Gut, dann natürlich nicht, aber worauf ich vor allem hinauswollte sind ja die Arrayzugriffe. Du musst doch nur jeweils den Pointer verschieben statt jedesmal wieder die Position im Array anzusprechen. Denn genau das macht die Scanline-Verwendung bei der normalen TBitmap ja schnell.
|
|
|