Entwickler-Ecke

Multimedia / Grafik - Grafik-Anzeige im Debugging ja, in Exe nicht.


hjl - Do 13.08.20 10:50
Titel: Grafik-Anzeige im Debugging ja, in Exe nicht.
In einer vektorgrafischen Anwendung (64 Bit für Windows 10) habe ich ein Problem.
Normalerweise funktioniert es sehr gut, doch in einem Fall möchte ich eine ungewohnt große Stringdatei (*.str) laden.
Es geht darum, 3,1 Mio. Punkte darzustellen, in einer TBitmap auf Canvas.
Mein Monitor hat mit 1680 x 1050 Pixel nur 1,7 Mio. Pixel, mein Rechner hat 32 GB RAM.
Das Programm kann aber auch Ausschnitte zeigen, beim Laden wird jedoch zuerst immer das ganze Bild gezeigt.
Auch ein ähnliches, käuflich erworbenes Programm konnte die Datei nicht anzeigen.

Das Problem ist, die Anzeige auf dem Bildschirm funktioniert nur im Debugging-Betrieb von Delphi 10.2 (Tokyo).
Lasse ich das Programm als Exe (Debug oder Release) laufen, bekommt es die Anzeige gar nicht hin.
Woran kann das liegen?
Ist Abhilfe möglich?


jaenicke - Do 13.08.20 12:06

Ohne Details zur Implementierung oder idealerweise einem kleinen Testprojekt wird es schwierig dazu etwas zu sagen...

Wie hoch ist denn die Speicherauslastung der Anwendung?

Wird vielleicht einfach nur einmalig auf das Canvas des Formulars gezeichnet statt im OnPaint und ggf. mit TPaintbox oder so etwas?


hjl - Do 13.08.20 12:26

Es wird eine Datei geladen und dann gezeichnet.

Das wären einige Statements:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
ImgStr.Canvas.Create;

ImgStr.Width                 := ClientWidth;
ImgStr.Height                := ClientHeight;
ImgStr.Picture.Bitmap        := TBitmap.Create;
ImgStr.Picture.Bitmap.Width  := ClientWidth;
ImgStr.Picture.Bitmap.Height := ClientHeight;

ImgStr.Canvas.Rectangle(00, ClientWidth, ClientHeight);

ImgStr.Brush.Style := bsClear;

ImgStr.Brush.Color := RScala.Color(iFF);
ImgStr.Pen.Style := psSolid;
ImgStr.Pen.Color := iColor;
ImgStr.Pen.Width := iWidth;
ImgStr.Polygon(Polygon);    

ImgStr.MoveTo(iRWs,iHWs);

ImgStr.LineTo(iRWs,iHWs);


Moderiert von user profile iconTh69: Delphi-Tags hinzugefügt


Th69 - Do 13.08.20 12:53

Also wird nur temporär gezeichnet, d.h. du mußt das, wie von jaenicke [https://entwickler-ecke.de/user_jaenicke.html] schon geschrieben, im OnPaint-Ereignis ausführen, s.a. Den Bildschirm aktualisieren [http://docwiki.embarcadero.com/RADStudio/Rio/de/Den_Bildschirm_aktualisieren].

Edit: Und nach dem Laden dann Refresh aufrufen.


hjl - Do 13.08.20 14:28

Zuerst muss ich mal gestehen, dass ich in meiner Ausführung einen Fehler gemacht habe:
alles, was unterhalb des Rectangle-Statement steht, müsste eigentlich mit ImgStr.Canvas. beginnen, da sie in einer Prozedur stehen, wo die Canvas als Parameter übergeben wird, dort habe die Canvas einfach ImgStr genannt - das war wohl nicht so gut. Diese Prozedur wird auch für Exports nach JPG, TIF, usw. verwendet.

Das mit dem Refresh erscheint mir klar, aber was ist mit dem OnPaint? Vom Formular?

Vielleicht sollte ich auch noch erwähnen, dass die zu ladende Datei im selben Programm vom Benutzer im üblichen Windows-Dateiauswahlmenü ausgewählt wird. Das geht so

Delphi-Quelltext
1:
2:
3:
4:
5:
if OpenDialog1.Execute then begin 
  {$ Ermitteln des gesamten Dateipfades }
  {$ Laden der Grafik }
  {$ Anzeigen der Grafik }
end;

So weit ist es ereignisgesteuert.
Wie passt nun OnPaint hier rein? Und welches OnPaint?

Dann verstehe ich noch nicht, was dies mit der stark vergrößerten Datenmenge zu tun hat.
Bei "normalgroßen" Dateien mit bis zu 1,3 Mio. Punkten hat es immer noch funktioniert.

Moderiert von user profile iconTh69: Delphi-Tags hinzugefügt


jaenicke - Do 13.08.20 14:34

user profile iconhjl hat folgendes geschrieben Zum zitierten Posting springen:
Dann verstehe ich noch nicht, was dies mit der stark vergrößerten Datenmenge zu tun hat.
Bei "normalgroßen" Dateien mit bis zu 1,3 Mio. Punkten hat es immer noch funktioniert.
Ein TImage (vermute ich mal aufgrund des Namens) ist hier ungünstig. Besser ist es die Daten in einer Bitmap im Speicher zu lassen und dann den Inhalt oder den gewünschten Ausschnitt in die Anzeige zu kopieren.

Das hatte Michael hier als Beispiel in einer TPaintbox gemacht:
http://michael-puff.de/Programmierung/Delphi/Code-Snippets/OffScreenBitmap.shtml


hjl - Do 13.08.20 14:43

Danke für den Hinweis!
Das schaue ich erst mal in Ruhe an, wenn ich mehr Zeit dafür habe.