![]() |
schnellerer Zugriff auf Tbitmap
Also bis jetzt greif ich so auf meine TBitMap-Variabel zu:
Delphi-Quellcode:
nun hab ich rausgefunden, dass das Ansprechen von der imgColor Variabel sehrsehr langsam funktioniert. Ich brauche sicher 100mal so viel zeit für diese Zuweisung als für das berechnen von CalcColor(...).
imgColor.Canvas.Pixels[s,z]:=CalcColor(aDivVal[s,z]);
Jetzt gibt es da keine schnellere Variante um auf eine TBitMap-Variabel zuzugreifen? Oder wass muss den da so extrem gerechnet werden? Wenn ich eine 2D Array of TColor habe funktioniert das ganze vielviel schneller.... Danke schon im Voraus... |
Re: schnellerer Zugriff auf Tbitmap
Hallo,
Langsam ist nicht der Zugriff auf das TBitmap sondern der auf die Pixels. Such mal hier nach ScanLine oder schau dir das Tutorial ( ![]() grüße, daniel |
Re: schnellerer Zugriff auf Tbitmap
Oder nutze die
![]() :thumb: |
Re: schnellerer Zugriff auf Tbitmap
Du könntest erst auf ein Bitmap im Speicher zeichnen und das dann wenn du fertig bist auf das anzuzeigende kopieren.
|
Re: schnellerer Zugriff auf Tbitmap
Zitat:
|
Re: schnellerer Zugriff auf Tbitmap
Zitat:
|
Re: schnellerer Zugriff auf Tbitmap
Zitat:
|
Re: schnellerer Zugriff auf Tbitmap
Zitat:
Ich berechne zuerscht jeden Pixel des Bitmaps und zeige den dan mit Canvas.Draw(0,0,Bitmap); in die Paintbox. Und natürlich auch beim Ereigniss onpaint.... |
Re: schnellerer Zugriff auf Tbitmap
pixels verwendet intern SetPixel und GetPixel. Wenn du SetPixel und GetPixel direkt aufrufst ist das ganze auch wieder eing gaaaaaaaaaaaaaaanz kleines bischen schneller
|
Re: schnellerer Zugriff auf Tbitmap
Hier mal der direkte Codevergleich VCL <-> Graphics32:
Die ist alles das was TCanvas für ein SetPixel macht/braucht:
Delphi-Quellcode:
Umwandlungen, if-Clauses und jede Menge mehr - für jeden einzeln gesetzen Pixel! Zudem ein Call einer API-Funktion. Das ist nicht wirklich schlimm, aber im Vergleich mal das was ein TBitmap32 macht:
procedure TCanvas.SetPixel(X, Y: Integer; Value: TColor);
begin Changing; RequiredState([csHandleValid, csPenValid]); Windows.SetPixel(FHandle, X, Y, ColorToRGB(Value)); Changed; end; procedure TCanvas.RequiredState(ReqState: TCanvasState); var NeededState: TCanvasState; begin NeededState := ReqState - State; if NeededState <> [] then begin if csHandleValid in NeededState then begin CreateHandle; if FHandle = 0 then raise EInvalidOperation.CreateRes(@SNoCanvasHandle); end; if csFontValid in NeededState then CreateFont; if csPenValid in NeededState then CreatePen; if csBrushValid in NeededState then CreateBrush; State := State + NeededState; end; end; function SetPixel(DC: HDC; X, Y: Integer; Color: COLORREF): COLORREF; stdcall;
Delphi-Quellcode:
Was sieht schneller aus?
procedure TBitmap32.SetPixel(X, Y: Integer; Value: TColor32);
begin Bits[X + Y * Width] := Value; end; Btw: TCanvas.SetPixel direkt aufzurufen bringt imho so gut wie nix, da der Compiler die Properties eh beim Kompilieren auf die Funktionen umlenkt -> es ist einem direkten Funktionsaufruf gleichwertig. \\edit: Kleine Zusatzinfo: Die G32 benutzt wo es geht, und so weit vorhanden MMX, 3DNow, SSE, SSE2. (Das kommt beim Überblenden von halbtransparenten Bitmaps und den ganzen Filten+Stretchen+Rotation gut zum Einsatz.) |
Re: schnellerer Zugriff auf Tbitmap
@dizzy:Vielen Dank für deine Info!!
Nun leider durchschau ich das ganze mit der Graphics32 noch nicht ganz. Wie kann ich die einsetzen bzw. welche Files benötige ich wirklich? Ich habe gesehen, dass diese ja aus über 10 Units besteht und sicherlich einiges kann was ich nicht brauche. Ich muss eigentlich fast nichts könnten. Das einzige was ich können muss ist ein Bild in Form eines Bitmaps auf dem RAM anzulegen. Es Pixelweise zu beschreieben und zwar mit TColor Werten. Die TColor-Werte weise ich so zu:
Delphi-Quellcode:
geht das noch schneller? Also die shl und shr sind ja sicherlich was vom schnellsten... RGB kenn ich auch ist aber nicht ganz so schnell so viel ich weiss.
color:=(tmp shl 16)+(tmp shl 8)+tmp //in tmp steht immer eine Zahl zwischen 0 und 255 (normales RGB System)
Danach möchte ich das Bild in einer Paintbox anzeigen. Dabei muss es teilweise noch gestrecht werden. Das wäre eigentlich alles was ich machen muss. Es sollte natürlich so schnell wie möglich werden da dies relativ wichtig ist. Ich möchte die selbe Zuweisung dann noch für Filme benutzen und wenn ich das einige 1000Frames rechne spielt es schon eine Rolle ob ich eine Woche oder ein paar Stunde dran bin :-) EndProjekt: Ein Fraktalprogramm welches einen Film von einem Zoom rechnen kann. Vielen Dank für eure Hilfe!!!! |
Re: schnellerer Zugriff auf Tbitmap
Das was du brauchst ist recht einfach, und der Handhabung von TBitmap recht ähnlich. Du musst die Unit "GR32" einbinden, und ein "TBitmap32" als Offscreenbitmap erzeugen. Davon im Vorfeld auch gleich die größe setzen, ganz wie mit den normalen Bitmaps.
Jetzt kommt die G32 allerdings mit einem eigenen Farbformat her: "TColor32". Aus der Hilfe zur G32:
Code:
Also kannst du einzelne Pixel wie folgt bearbeiten:
Bits 32...24: Alpha
Bits 23...16: Red Bits 15...8 : Green Bits 7...0 : Blue
Delphi-Quellcode:
Um dieses Bitmap irgendwo hin zu zeichnen hat TBitmap32 diverse überladene Versionen von "TBitmap32.DrawTo". Eine Variante kann auf ein beliebiges HDC zeichnen, z.B. ein "TCanvas.Handle". Das dürfte für dich interessant werden.
var
bmp: TBitmap32; begin bmp := TBitmap32.Create; bmp.Width := 320; bmp.Height := 240; bmp.Pixels[100, 100] := Color32(RotAnteil, GrünAnteil, BlauAnteil); // oder mit Alphakanal bmp.Pixels[100, 100] := Color32(RotAnteil, GrünAnteil, BlauAnteil, AlphaWert); // oder ohne Umwandlung mit shifting (ist bei der G32 NICHT zwangsläufig schneller!) bmp.Pixels[100, 100] := (AlphaWert shl 24) or (RotAnteil shl 16) or (GrünAnteil shl 8) or BlauAnteil; Zitat:
Hoffe das hilft! Fabian |
Re: schnellerer Zugriff auf Tbitmap
Vielen Dank für deine Hilfe. Ich werds gleich mal ausprobieren. Was du dir darunter vorstellen sollt? Ähh also das Mandelbrotfraktal kennst du oder? jetzt kann man da ja reinzoomen indem man einen Rahmen zieht. Naja also ich möcht jetzt stufenlos ins Fraktal reinfliegen können :-) Mal schauen wies rauskommt :-) Ich komm mit dem schreiben von AVI-Files noch nicht ganz klar. Also ich hab mal den TAVIWriter angesehen. Doch den müste ich relativ stark umschreiben. Das erste Problem ist, dass der unter Delphi6 nicht läuft. Der Compiler bringt dort einenen Fehler so im Stil "Ausdruck gefunden aber then erwartet" mitten in einem Funktionsaufruf und der Courser steht an einem ort wo es sowieso nix hat. Naja ebenn die Rükwärtkompatibilität von Delphi :-) Das zweite und noch viel grösere Problem ist. Dass der in der Orginalversion eigentlich so arbeitet, dass man zuerst alle bilder in eine Tbitmap list reinläut und er sie erst dann anfängt auf die HDD zu schreiben. Ist für mich auch unbrauchbar weil ich keine 10GB Ram habe :-)
Naja mal schauen.... werd ich schon noch irgendwie hinkriegen... |
Re: schnellerer Zugriff auf Tbitmap
Liste der Anhänge anzeigen (Anzahl: 1)
Mit Fraktalen hast du bei mir den richtigen Nerv getroffen :D (Siehe Anhang: Das war mein letztes größeres Projekt -> 3D-Julia Fraktale)
Der eigentliche Flaschenhals ist da allerdings weit weinger die Geschwindigkeit beim Zugriff auf das Bitmap, als viel mehr die Berechnungen selbst. Da kann ich dir meinen ![]() Das Schreiben eines Videos habe ich bisher immer VirtualDub oder TMPGEnc überlassen, und einfach die Bitmaps auf Platte geschoben. Allerdings könnte dir das ![]() Viel Erfolg! Und wenn Fragen dazu sind: Ich bin eigentlich immer interessiert :) Gruss, Fabian PS: Ääääähhh .mpg ist nicht als Anhang erlaubt... dann eben als .zip :? |
Re: schnellerer Zugriff auf Tbitmap
das sieht ja (sorry) verdammt gut aus! Mit 3D Fraktalen hab ich mich noch nie beschäftigt. Vielleicht komm ich darauf zurück, wenn ich mit den 2D Fraktalen fertig bin :-)
Zur berechnugn. Also hier mal den Code, welchen ich brauch um die Divergenze von einem Punkt zu berechenn:
Delphi-Quellcode:
Nun also ich hab das ganze mit der GR32 Unit einmal ausprobiert. Und ich muss sagen... kein vergleich viel schneller. Nur leider versteh ich das mit dem Alpha Teil des TColor32 Typs noch nicht ganz. Für was ist der gut? Kann man den auch weglassen? Denn momentan hab ich noch das Problem, das meine Bitmaps vielviel grösser werden als sie vorhin waren. Dies ist relativ verherend da ich ja nicht belibig Ram habe....
TComplex=record
r,i:Extended; end; (...) function TFrmMain.CalcDivMandel(x,y:Extended):Integer; var z1,z2:TComplex; h1,h2:Extended; i :Integer; begin z1.r:=0; z1.i:=0; i :=0; repeat h1 :=z1.r*z1.r; h2 :=z1.i*z1.i; z2.r:=h1-h2 +x; z2.i:=2*z1.r*z1.i+y; z1:=z2; inc(i); until (i>=steps) or ((h1+h2)>4); result:=i; end; Nun nochmals eine kurze Frage. Du sagtest du überlässt das "Filmmachen" an Virtualdub etc. Wie funktioniert das denn bei dir genau? Also Virtualdub kenn ich relativ gut. Ich benutzte es häufig zum umcodieren von Filmen. Jetzt speicherst du einfach alle Frames als Bitmap auf die HDD? Danke, Greez cumi |
Re: schnellerer Zugriff auf Tbitmap
Zitat:
Zitat:
Die gesamte Sequenz im RAM zu halten ist imho ohnehin nicht so glücklich. Über Chunks von so 10 bis 20 Bitmaps im Speicher kann man reden, die dann in einem Schwupps geschrieben werden, aber ich hab jedes Bitmap direkt nach Fertigstellung weggeschrieben und fertig. Zitat:
Einfach mit aufsteigender Nummereierung benennen (z.B. frac0001.bmp; frac0002.bmp; ...; fracXXXX.bmp), und VirtualDub (und auch TMPGEnc) erkennen mit Öffnen des ersten Bildes der Sequenz dass es auch eine Sequenz ist, und behandelt es wie ein Video. Ist zunächst mal die einfachere Variante während man sich noch mit den "wichtigen" Dingen rumplagen muss 8). Gruss, Fabian |
Re: schnellerer Zugriff auf Tbitmap
Zitat:
Zitat:
Nun du sagtest dieser werde für die Transparenz benutz. Wie funktioniert das? Mir ist gleich die Idee gekommen, dass ich eigentlcih übergänge von einer in die andere Farbe so rechnen könnte. Äh also mal eine Idee wie ich mir vorstellen könnte wies gehen könnte :-) Kann man einfach zuerst was zeichen, sprich einen Pixel einfärben mit dem Alphawert 255 und danach den selben Pixel nochmals überschreiben allerdings mit einem Alphawert von zb. 128 und dann er der Pixel schlussentlich den Mittelwert? Naja war nur so eine Idee :???: Zitat:
------------------ Nun hab ich aber trotzdem nochmals eine Frage. Also irgendwas mach ich da noch nicht ganz richtig habe ich bemerkt. Es sind nicht einfach TBitMap32 die mehr Stack brauchen, nein ich brauche wenn ich das selbe nochmals rechne und eigentlich nicht weitere TBitMaps erzeuge (mach ich dann auch teilweise in einer doppeltverlinkten Liste. Seit ich dieses System kenne brauch ich es wo es nur irgendwie einbisschen Sinn macht weil mich die Geschwindigkeit und die Bedienung fast vom Stuhl gehauen hat :P ). Ich überschreibe dabei allerdings ein vorhandenes TBitMap immer wieder. Nun der fehler muss wohl dabei liegen. Ich mache dies so:
Delphi-Quellcode:
Ich hab dann mal zum probieren immernoch vor dem TBitmap32.Create img.free aufgerufen, was allerdings keine Abhilfe schuf.
img:=TBitmap32.Create; //img ist vom Typ TBitMap32
img.Width:=sRef.dx; img.Height:=sRef.dy; Iregdnwer eine Idee was da sonst noch schieflaufen könnte?? Ah ja und gibts kei Tool von Delphi her welches einem anzeigt wo wieviel Speicher gebraucht wird? Ich benutze bis jetzt (ich weiss, dass es nichts dümmeres gibt :-)) den Taskmanager von WinXP. Ich zweifle jedoch an dessen Richtigkeit..... Vielen Dank für eure Hilfe! Greez cumi |
Re: schnellerer Zugriff auf Tbitmap
Zitat:
![]() Zitat:
Zitat:
Zitat:
Zitat:
btw: Du schreibst "Stack". Objekte werden doch aber auf dem Heap angelegt, oder? :gruebel: Zitat:
![]() Arrividetschi :) Fabian |
Re: schnellerer Zugriff auf Tbitmap
Zitat:
Mal noch eine Frage. Was machst du eigentlich beruflich? Informatik ist nicht nur dein Hobby, oder? Ich bin immerwieder aufs neue erstaunt wie genau, dass du über all diese Dinge bescheid weisst.... Und hier gleich noch der absolut passende Test :-) Zitat:
Jetzt bin ich gleich an einem Problem angelangt das eigentlich auch hierhinein gehört und zwar: Ich habe zwei Farben (TColor32). Nun möchte ich einen Übergang von der einen in die andere berechnen. Ich nehme an, dass es hierfür von der GR32 auch Möglichkeiten gibt. Ich hab sie leider nur noch nicht gefunden :-) Zitat:
Zitat:
Zitat:
Zum Schluss möcht ich dir, Fabian, nochmals ganz herzlich danken für deine Geduld mir alle Fragen zu beantworten. Bin ich echt mega super froh :-) Denn wenn ich das alles in Büchern oder im Netz zusammensuchen müsste würd ichs glaub ich gar nicht finden oder dann hätte ich ein halbes Jahr :-) Greez cumi |
Re: schnellerer Zugriff auf Tbitmap
Zitat:
Zitat:
Allerdings bringt die G32 eine nette Routine mit, die das Mischen recht effizient (weil mit MMX) umsetzt: "Combine(X, Y, W: TColor32): TColor32" Auszug aus der Hilfe: Zitat:
Zitat:
Zitat:
Zitat:
Macht ja Spaß! Cu, Fabian |
Re: schnellerer Zugriff auf Tbitmap
in welcher unit ist die Combine(X, Y, W: TColor32) enthalten?
|
Re: schnellerer Zugriff auf Tbitmap
Laut der Hilfe-Datei (*mitdemzaunwink* ;)) in der "GR32_Blend".
|
Re: schnellerer Zugriff auf Tbitmap
supi, habs jetzt geschafft, allerdings mit der blendfunktion.... laut hilfe passt die noch genauer zu meinem problem... oder ist die viel langsamer?
|
Re: schnellerer Zugriff auf Tbitmap
Die könnte u.U. sogar schneller sein. Das weiss ich grad nicht so genau.
Der Unterschied zwischen den beiden ist ja: Combine mischt 2 Farben (incl. Alpha-Komponente) im Verhältnis W : (1-W) Blend mischt 2 Farben (excl. Alpha-Komponente), dafür in einem Verhältnis wie es die Alpha-Komponente angibt. Lösen lässt sich dein Problem prinzipiell mit beiden :). \\edit: Diese ungewollten Grinser immer :D |
Re: schnellerer Zugriff auf Tbitmap
stimmt, jo naja ich machs jetzt mit blend... ist spezifisch für mein Problem direkter...
Und ich muss sagen, diese GrafikUnit ist wirklich ganz extrem leistungsstark! |
Re: schnellerer Zugriff auf Tbitmap
wenn isch schon am fragen bin, dann frag ich doch gleich weiter, denn ich bin schon bei meinem nächsten Problem angelangt. Gibt es eine Funktion, welche einem die Komplementärfarbe (Gegenfarbe) einer TColor32 berechnet?
|
Re: schnellerer Zugriff auf Tbitmap
Soooo schlecht ist die Hilfe zur G32 doch garnet :zwinker:
Invert() bzw. InvertRGB() invertieren dir ein ganzes TBitmap32. Einmal mit, und einmal ohne den Alphakanal mit zu invertieren. Ansonsten ist zu einer Farbe "r, g, b" die Farbe "255-r, 255-g, 255-b" invers. Also so einfach selber zu machen, dass die G32 da nicht mal eine separate Funktion für bietet ;). \\edit: Die Funktion ColorSub() könnte dir dabei helfen. Wenn du:
Delphi-Quellcode:
bekommst du die Komplementärfarbe zu Rot. Sollte schneller sein, als es von Hand zu berechnen. Einfach die zu invertierende Farbe von Weiss subtrahieren.
NewColor := ColorSub(Color32(255,255,255), Color(255,0,0));
|
Re: schnellerer Zugriff auf Tbitmap
*sabber* Fraktale, das ist eins der geilsten sachen die es gibt.
hab auch mal so nen Programm geschrieben was mandelbrote usw. backt. Mit der TBitmap methode scanline kannste ne mandelbrotberechnung mit Pixles[x,y] so um die 10 seckunden verschnellern! Auf delphi-source.de gibt es beispiele zu scanline ![]() Hoffe das hilft dir! Mir hat es das! |
Re: schnellerer Zugriff auf Tbitmap
Öhm, glaub mir: Die G32 ist u.U. sogar noch schneller, und vor allem um Längen komfortabler als das Pointerrumgeschubse mit Scanline. Hab's bevor ich die G32 kannte auch mit Scanline gemacht, aber der Umstieg war mehr als richtig und einfach.
Zumal man mit der G32 auf einmal einen riesen Haufen an Möglichkeiten mehr hat: Layered Bitmaps, eingebautes Antialiasing mit verschiedenen Algos (man kann sogar Pixel auf Float-Koordinaten setzen, und die G32 übernimmt die Verteilung auf die 4 realen Pixel), volle Alphakanalunterstützung, haufenweise Optimierungen mit MMX, SSE(2), etc., und vieles vieles mehr. Wer viel Grafik mit Delphi macht, dem kann ich die G32 einfach nur wärmstens an's Herz legen - Scanline ist nen Weisenkind dagegen ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:45 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