Autor |
Beitrag |
galagher
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 05.10.05 17:51
Hallo Leute!
Ich habe mehrere Image-Komponenten, in die ich Bildateien lade (.bmp, .gif, .jpg, .dib) und die, wenn sie neugezeichnet werden, unschön und deutlich sichtbar neu "aufgebaut" werden, obwohl ich DoubleBuffered := True verwende. Dies tritt jedoch nicht bei Bitmap-Dateien auf, bei anderen schon.
Für Bitmaps verwende ich PixelFormat := pfDevice, damit kriege ich eine schöne, glatte Anzeige hin. Bloss, was kann ich bei anderen Dateiformaten machen, um das Flackern wegzubringen?
Danke schon mal!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mi 05.10.05 18:52
Du könntest mal versuchen das Bild in eine Variable vom Typ TPicture zu laden
und erst dann anzeigen zu lassen. Also etwa so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| var TempPic: TPicture;
procedure LoadPic(Pfad: String); begin TempPic := TPicture.Create; TempPic.LoadFromFile(Pfad);
Image1.Picture := TempPic;
TempPic.Free; |
So würde Delphi das Bild im Hintergrund laden und erst dann anzeigen.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 05.10.05 19:38
GTA-Place hat folgendes geschrieben: | Du könntest mal versuchen das Bild in eine Variable vom Typ TPicture zu laden
und erst dann anzeigen zu lassen. |
Es flackert ja nicht beim Laden, sondern wenn es bereits geladen ist und zB. ein Fenster einer anderen Anwendung über meinem Programm ist und dieses Fenster über die Images bewegt wird, oder, wenn die ScrollBox, auf der die Images liegen, gescrollt wird. Dann schmieren die Images richtig und es dauert, bis sie wieder normal dargestellt werden. Windows zeichnet ja alles dabei neu, aber wie gesagt, bei .bmp-Files kommt das nicht vor.
Also nicht das Laden der Bilddateien, sondern das Neuzeichnen flackert, schmiert und ist elendig langsam. Klar, bei Bildern mit sagen wir 100x100 Pixel klappt es ja, aber bei 1024x768 ist's ein echter Graus. 
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mi 05.10.05 19:43
Und wenn du es doch so machst wie ich und in OnPaint dann Image1.Picture := TempPic; schreibst?
Vielleicht geht das schneller, als wenn er es nochmal malen muss.
EDIT: Gibt kein OnPaint... 
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 05.10.05 20:05
GTA-Place hat folgendes geschrieben: | Und wenn du es doch so machst wie ich und in OnPaint dann Image1.Picture := TempPic; schreibst? |
Nützt nichts, wenn ich zB. die Grösse von Form1 ändere, sodass das Image nicht mehr voll sichtbar ist, schmiert es beim Vergrössern des Formulars wieder. Auch das Darüberschieben anderer Fenster erzeugt einen Schmiereffekt. Ausserdem habe ich 150 Images - da müsste ich also 150 temporäre Pictures verwenden... Aber es nützt sowieso nichts.
Ich habe auch versucht, mit JPEG-Pixelformat zu arbeiten - nützt ebenfalls nichts:
Delphi-Quelltext 1: 2: 3: 4: 5:
| with TJPEGImage(ImagePlus1.Picture.Graphic) do begin PixelFormat := TJPEGPixelFormat(jf24Bit); end; |
Man müsste herausfinden, warum ein Bitmap weder schmiert noch flackert, aber ein .jpg-File zB. das hingegen schon macht.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Mi 05.10.05 21:30
Hallo,
probier mal folgendes:
Delphi-Quelltext 1: 2: 3:
| image1.ControlStyle:=image1.ControlStyle+[csOpaque]; image1.parent.ControlStyle:=image1.parent.ControlStyle+[csOpaque]; |
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Do 06.10.05 08:42
Ich denke mal dein Bitmap wird das selbe Problem haben wie die anderen Bilder auch, nur dass es bei ihm nicht auffällt, da es pfDevice als Pixelformat besitzt. pfDevice (oder HandleTyp bmDDB) sagen aus, dass das Bild hardwarebeschleunigt gezeichnet wird. Zu mindest wird es versucht so viel wie möglich aus der Hardware herauszuholen. Fakt dürfte sein, dass die Anzeige des Bitmap schneller ist als die der anderen. Evtl. wird es durch das verwendete Format noch mal beschleunigt.
150 Images? Und dann wunderst du dich warum es flackert und schliert? Das Zeichnen von 150 Komponenten dauert nun mal ne Weile. Das solltest du anders aufziehen. Also ich würde die Bilder entweder in TBitmaps oder bei unterschiedlichen Typen in TPictures laden. Zum Zeichnen würde ich dann eine PaintBox oder ein verändertes Panel benutzen. Zu Begin der Anwendung würde ich ein Bitmap erstellen, welches genau die Größe des Panels besitzt. Im OnPaint würde ich zu erst die Größe updaten. Es passiert nichts, wenn die größe gleich ist. Anschließend würde ich alles so zeichnen wie ich die Bilder gerne haben will. Und wenn alle fertig ist dann kann das Bitmap in die Zeichenfläche gezeichnet werden.
Evtl kannst du aus performance Gründen auch das temporäre Bild auch woanders zusammenbauen auf, dass es im OnPaint lediglich noch gezeichnet werden muss. So brauchst du es dann nur noch updaten, wenn sich auch tatsächlich etwas verändert hat. Dadurch sparst du Leistung ein die du anderweitig benutzen kannst.
Du solltest bei der Zeichenfläche aber noch den ControlStyle (wie bei Lannes) setzen. Es genügt dabei die PaintBox. Der Style sorgt dafür, dass das Fenster von Windows nicht mehr gelöscht wird, wodurch der ursprüngliche Inhalt erhalten bleibt.
Nur zum Verständniss. DoubleBuffering sorgt dafür, dass eine Komponente vor dem auf dem Bildschirm darstellen erst einmal in ein Temporäres Bitmap gezeichnet wird. Es nützt absolut nichts, wenn du ein Image mit DoubleBuffering versiehst, da das Darstellen eines Bildes je Problemlos funktionieren sollte. Ich an deiner Stelle würde die ParentKomponente deines Bitmaps mit DoubleBuffering versehen. Das sollte wesentlich mehr bringen. Aber bei 150 Images würde ich defintiv etwas anderes machen.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
Alpha_Wolf
      
Beiträge: 297
Ubuntu, Win XP, Win Vista
C#, Delphi 6 Prof, Delphi 2007 Prof, Java
|
Verfasst: Do 06.10.05 15:29
Wie Lossy ex schon sagte würde ich es ebenfalls anders aufbauen..
Ich hatte mal das Problem als ich einen speziellen Player für Kamerabilder programmiert habe..
Vielleicht hilf dir das in irgendeiner Art und Weise..
Das ganze ins Create der Form schreiben.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| ... var lCounter: integer begin for lCounter:= 0 to ComponentCount-1 do begin if Components[lCounter].InheritsFrom(TWinControl) then begin TWinControl(Components[lCounter]).DoubleBuffered:= true; end; end; end; |
_________________ Diskutiere nie mit einem Irren - er zieht dich auf sein Niveau und schlägt dich mit seiner Erfahrung.
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Do 06.10.05 17:51
Lossy eX hat folgendes geschrieben: | 150 Images? Und dann wunderst du dich warum es flackert und schliert? |
Naja, es sind ja 150 Images mit je nur 69x69 Pixel Grösse, das Bild wird mit .Proportional := True geladen und somit verkleinert. Nur das allein hilft nicht. Deine Tips sind zwar einleuchtend und ich würde das wahrscheinlich auch hinbekommen (mit Nachfragen hier im Forum  ), aber ich will nicht das ganze Programm umbauen müssen! Wenn schon, dann lieber gleich neu anfangen.
Aber ich habe eine andere Idee: Mit kleinen Bilddateien (etwa 200x300 Pixel oder mit Bilddateien mit nur 256 Farben) klappt ja alles zufriedenstellend. Sagen wir, ich lade ein Bitmap mit 1024x768 Pixeln in ein zur Laufzeit erstelltes Image. Wie kann ich nun erreichen, dass das Bitmap (JPEG usw.) nicht nur verkleinert dargestellt, sondern in der Image-Komponente tatsächlich verkleinert wird? (Selbst wenn ich Stretch oder Proportional verwende - das Bild bleibt so gross, wie es ist). Kennt jemand eine Funktion oder Prozedur, die das kann?
Das so verkleinerte Bild weise ich dann einer sichtbaren Image-Komponente zu. Das mache ich eben 150 mal.
Die Bilddatei soll natürlich nicht verändert werden, aber mein Programm soll nun nicht mehr ein grosses Bild, das verkleinert dargestellt wird, handlen, sondern ein grosses Bild, das verkleinert ist, so, als hätte es ein kleines Bild geladen.
Anders gesagt: Wenn ich SaveToFile anwende, wird das Bild mit exakt der Anzahl an Pixeln, die die Image-Komponente hat, gespeichert - 69x69.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Alpha_Wolf
      
Beiträge: 297
Ubuntu, Win XP, Win Vista
C#, Delphi 6 Prof, Delphi 2007 Prof, Java
|
Verfasst: Do 06.10.05 17:56
Hilft dir mein code nicht weiter (2 post vorher)? Wundert mich direkt..
Einfach mal die Hilfe besuchen und du findest einiges.. Bild verkleinern...
_________________ Diskutiere nie mit einem Irren - er zieht dich auf sein Niveau und schlägt dich mit seiner Erfahrung.
|
|
Teo
Hält's aus hier
Beiträge: 2
Windows 2000/XP
Delphi 4/7
|
Verfasst: Fr 07.10.05 08:42
Du köntest versuchen ob es besser geht wenn am Anfang der Zeichenroutine LockWindowUpdate(form.handle) steht und am ende LockWindowUpdate(0).
Dass hat aber ein Nachteil: das ganze wird nicht eher gezeignet als am ende der Routine. LockWindowUpdate (wie der Nahme sagt sorgt dafür dass zeichnen nicht ausgeführt wird)
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Fr 07.10.05 09:06
@Alpha_wolf: Bitte nicht so die Bilder verkleiner. StretchDraw macht nichts anderes als Pixel zu wiederholen oder wegzulassen. Das Ergebniss ist zwar ziemlich genau so wie in der Imagekomponente allerdings lässt die Qualität so doch sehr zu wünschen übrig. Und Graphics32 für so etwas simples zu bemühen finde ich auch übertrieben. Vor allem, da er die Bilder wohl bei jedem Durchgang kleiner rechnen wird. Dann doch lieber ein Resample mit Scanlines. Das ist schnell und sieht gut aus. Den Code habe ich jetzt spontan mit Google gefunden aber er sieht ganz brauchbar aus.
Allen Komponenten das Doublebuffering zu verpassen halte ich auch nicht für sinnvoll. Schließlich muss er bei jedem Zeichnen ein Temporäres Bitmap anlegen und in das hineinzeichen. Bei ImageKomponenten ist das aber recht sinnfrei, da das bereits Bilder sind. Ich denke mal das Problem rührt davon, dass die Komponenten in der Scollbox verschoben werden und vorerst der Hintergrund gelöscht wird.
Das Zeichnen dauert nun mal eine Weile. Beim StrechtDraw wie es in den TImages benutzt wird muss er durch das ganze Bild gehen um heraus zufinden welche Pixel er zeichnen muss und welche nicht. Um so größer die Bilder sind umso mehr zeit braucht er dafür. Auch wenn die Bilder jetzt kleiner wären, das Problem bleibt das Gleiche. Nur ist es in anderen Fällen nicht so offensichtlich, weil er nicht so lange dafür braucht. Was ist aber, wenn dein Rechner gerade beschäftigt ist oder dein Programm auf einem langsameren Rechner ausgeführt wird? Dann wird es genau so sein. Und dann auch mit den kleineren Bildern.
Ich persönlich sehe keine andere Möglichkeit als, dass du es entsprechend anpasst. Wobei ich mal sehr stark bezweifel, dass du deswegen komplett neu anfangen musst. Und auch wenn, dann kannst du ja größere Teile bestimmt so übernehmen oder andere Stellen die dir nicht gefallen ausbessern etc. Aber normal musst du lediglich die Verwaltung von TImages auf TPictures umstellen und beim Zeichnen dann auf die TPictures zugreifen. Den ResampleAlgorithmus solltest du wohl in jedem Fall mit benutzen.
Du kannst ja auch daraus lernen, wie man ein Programm aufbaut, damit man es später erweitern oder umbauen kann. Das wird nicht das letzte mal gewesen sein, dass du in solche eine Situationen gekommen bist. Spreche da ein bisschen aus Erfahrungen.  Ich vertrete da auch die Meinung, dass man etwas lieber umbauen sollte als es auf Teufel komm raus auf etwas anderes umzbiegen. Da kommt meist nichts so tolles bei raus.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 07.10.05 18:54
Ich möchte mehrere Bildformate verkleinern können, nicht nur Bitmaps! Das Bild einfach kleiner machen im Image! Ob es nun ein JPEG ist oder sonstwas.
Aber erstmal danke für eure Anregungen - momentan versuche ich es mit StretchDraw hinzukriegen. Sieht aber nicht sehr erfolgreich aus. Nicht kleiner darstellen, kleiner werden!
Moderiert von raziel: Quote-Tag repariert.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Fr 07.10.05 22:23
Du kannst ja schließlich auch jedes jpeg auf ein tbitmap zeichnen und das dann kleiner rechnen lassen. Schon mal an so etwas gedacht? In welchem Format die kleinen Bilder sinst doch wurscht. Sind doch nur zum anzeigen da, oder etwa nicht?
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 08.10.05 16:46
Ok, StretchDraw klappt jetzt. Aber ich möchte die verkleinerten Bilder auch noch proportional korrekt, also ohne Verzerrung, anzeigen, denn
Delphi-Quelltext 1: 2: 3:
| ImagePlusX.Picture.LoadFromFile(OpenPictureDialog1.Files[B]); TImagePlus(FindComponent('ImagePlus'+IntToStr(B))). Canvas.StretchDraw(Rect(0, 0, 69, 69),ImagePlusX.Picture.Graphic); |
verzerrt das Bild auf 69x69 Pixel. Wie kann ich statt dem fixen Wert 69 einen variablen Wert errechnen, der die Grafik wie .Proportional := True ins Image einpasst, angenommen, bei einer 1024x768 Pixel grossen Grafik?
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 08.10.05 20:10
Mir würde es auch schon helfen, wenn man von einem Image mit Proportional := True die Höhe und Breite des tatsächlichen Bildes ermitteln kann. .Picture.Height oder .Picture.Width geben immer die Original-Werte zurück, ich brauche aber soetwas wie .Canvas.Width. Diesen Wert verwende ich dann für die Breite in StretchDraw.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: So 09.10.05 09:57
Also mit dem Dreisatz (Prozentrechnung) kommst du spielend die Größe die du brauchst. Das solltest du schon beherschen, weil man das sehr häufig braucht.
Das würde dann so aussehen. Höhe = 1024 / 69 * 768. Du musst natürlich vorher überprüfen ob das Bild hochkant oder Quer ist.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 09.10.05 10:42
Lossy eX hat folgendes geschrieben: | Also mit dem Dreisatz (Prozentrechnung) kommst du spielend die Größe die du brauchst. |
Danke, das hab' ich vorhin gerade mit Google eher zufällig gefunden:
www.swissdelphicente...index.php/t9232.html
Proporional verkleinern geht somit im Prinzip so:
Yneu = (Xneu * Yalt) / Xalt
Xneu = (Xalt * Yneu) / Yalt
Allerdings bleiben in die "freien" Bereiche weiss, das müsste ich nun noch wegbekommen, und ausserdem noch das verkleinerte Bild mittig ausrichten...
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 09.10.05 16:53
galagher hat folgendes geschrieben: | Allerdings bleiben in die "freien" Bereiche weiss, das müsste ich nun noch wegbekommen, und ausserdem noch das verkleinerte Bild mittig ausrichten... |
Beides gelöst: Vor dem Zeichnen des Bildes verwende ich einfach FloodFill, und das Ausrichten in der Mitte des Ziel-Images kann man berechnen, momentan kriege ich es aber nur dann ohne Verzerrung hin, wenn Breite und Höhe des Ziel-Images ident sind.
Soll aber nicht heisen, dass ihr mir jetzt nie mehr antworten sollt, weil ich die Lösung selbst gefunden habe! 
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: So 09.10.05 20:18
Um ein Bild zu löschen benutze ich immer FillRect mit dem Rect. FloodFill geht doch normal her und füllt nur einen gewissen bereich mit einer Farbe. Dabei muss er normal ja jedes Pixel abfragen. In deinem Fall sollte ein einfachen übermalen schneller sein.
Und das mit dem Mittig ausrichten und gleich höhe/breite habe ich nicht gerallt.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
|