Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   max. TBitmap FMX vs. VCL (https://www.delphipraxis.net/205291-max-tbitmap-fmx-vs-vcl.html)

bernhard_LA 22. Aug 2020 15:01

max. TBitmap FMX vs. VCL
 
ich müsste *.tif Dateien mit ca. 20.000 * 20.000 pixel in eine FMX Bitmap laden ....
mit dem code fragment


Delphi-Quellcode:
 
   BMP := TBitmap.Create;
   BMP.Width := 500;
   BMP.Height := 500;


kann ich auf meinen Rechner TBitmaps mit ca. 3000 x 3000 pixel erzeugen, wie komme ich zu den großen Werten / Bilddateien ???
bei 6000 pixel x 6000 pixel bekomme ich eine Out of Memory Fehlermeldung :-(
bei VCL waren 20.000 x 20.000 pixel möglich

Bernhard Geyer 22. Aug 2020 15:34

AW: max. TBitmap FMX vs. VCL
 
Ist schon ein 64-Bit Projekt?
Ansonsten schaffts du mit VCL auch keine 20k * 20k Bilder

himitsu 22. Aug 2020 15:38

AW: max. TBitmap FMX vs. VCL
 
Zitat:

bei VCL waren 20.000 x 20.000 pixel möglich
Ähhh neee?
In einer realen 32-Bit-Anwendung, mit 2 GB RAM, wird es erfahrungsgemäß schwer "immer" einen gemeinsamen Speicherblock über 700 MB zu bekommen.

In 32 Bit garnicht, denn bei pf32Bit wäre das Bitmao 1.6 GB groß und das in einem zusammenhängenden Speicherblock.


ImageEN hatte ich schon große Bilder geladen.
Die haben ein TIEBitmap, welches intern LZW-Komprimiert ist.

Bei Delphis TWICImage musste ich aber bissl kämpfen, denn für eine Vorschaufunktion hatte ich auch sehr große TIFF-Bilder geladen.
Beim StretchDraw zeigte sich aber, dass der Entwickler von Embarcadero eine Volltrottel war,
denn da wird das Bild zuerst in ein internes TBitmap geladen und dann auf den Canvas (ein anderes TBitmap) runterscaliert.
Dabei bietet die WIC-API (Windows Imaging Component) auf extreme Speichersparsamkeit ausgelegt, indem die API immer nur mit kleineren Bildauschntitten arbeitet, wenn der Trottel auch die vorhandene Scalierungs-Interfaces genutzt hätte.

Selbst in Win32 ohne IMAGE_FILE_LARGE_ADDRESS_AWARE konnte ich am Ende sogar TIFFs mit derartigen Größen laden.
Allerdings nur in einem kleinen Programm, welches noch wenig Speicher belegt, wenige DLL/BPL geladen hat und wo der Speicher noch nicht zu sehr fragmentiert ist.

So oder so, würde ich dir also LargeAddressAware oder besser 64 Bit empfehlen.

TurboMagic 22. Aug 2020 15:38

AW: max. TBitmap FMX vs. VCL
 
Ich verstehe noch nicht wie eine Bitmap deren Width und Height jeweils auf 500 gesetzt wird
dann 3000x3000 Bildpunkte groß sein soll.

Hat das was mit dp als Einheit zu tun?

TurboMagic 22. Aug 2020 15:41

AW: max. TBitmap FMX vs. VCL
 
Zitat:

Zitat von himitsu (Beitrag 1472221)
Bei Delphis TWICImage musste ich aber bissl kämpfen, denn für eine Vorschaufunktion hatte ich auch sehr große TIFF-Bilder geladen.
Beim StretchDraw zeigte sich aber, dass der Entwickler von Embarcadero eine Volltrottel war,
denn da wird das Bild zuerst in ein internes TBitmap geladen und dann auf den Canvas (ein anderes TBitmap) runterscaliert.
Dabei bietet die WIC-API (Windows Imaging Component) auf extreme Speichersparsamkeit ausgelegt, indem die API immer nur mit kleineren Bildauschntitten arbeitet, wenn der Trottel auch die vorhandene Scalierungs-Interfaces genutzt hätte.

Hast du diese Thematik mal als QP Report erfasst?
Sonst bekommen wir da nie eine Verbesserung von "out of the box".

himitsu 22. Aug 2020 15:44

AW: max. TBitmap FMX vs. VCL
 
Wollte ich mal, aber hatte noch keine Zeit Lust.
Hatte am Ende komplett auf TWICImage verzichtet, weil es zu krank war, mit den internen Handles zu arbeiten, denn die blöde Komponente merkt sich "versteckt" nur das Basisinterface, aber ein Sub-Interface wird sofort im LoadFromStream wieder freigegeben und ich müsste es mir dann sinnlos neu erzeugen, nachdem ich mich mühevoll an das Interne Interface durchgekämpft hatte.
Hatte mir den Code letzendlich direkt mit der WinAPI gebaut und paar Zwischenschritte rausgekürzt, speziell auf meinen Fall zugeschnitten.

Und dann hilft es auch nur im Windows.
Ich weiß garnicht ob das FMX-TBitmap im Windows auch die Systemfunktionen verwendet.

TurboMagic 22. Aug 2020 15:48

AW: max. TBitmap FMX vs. VCL
 
Zitat:

Zitat von himitsu (Beitrag 1472224)
Wollte ich mal, aber hatte noch keine Zeit Lust.

Und dann hilft es auch nur im Windows.
Ich weiß garnicht ob das FMX-TBitmap im Windows auch die Systemfunktionen verwendet.

Ja, aber selbst wenn's nur für die VCL was bringt wär's doch eine gute Sache.
Und soviel Zeit braucht ein kleiner QP Report ja auch nicht.
Die Frage ist dabei, ob das ein Bugreport oder ein Feature Request wäre.

Falls du schon Code hast und den teilen wolltest/könntest wär's natürlich noch besser,
aber evtl. reicht da auch schon ein kleines Fragment aus um EMBT die richtige Richtung
zu zeigen... ;-)

himitsu 22. Aug 2020 15:56

AW: max. TBitmap FMX vs. VCL
 
Mir war so, als hätte ich auch Teile im Forum, aber fand den Beitrag grade nicht (von letztem Jahr, wenn ich mich nicht irre).
Vor paar Monaten war ich in der Firma nochmal drüber gestolpert, denn jetzt war jemandem was aufgefallen.
Cheff eines Kunden hatte ein Foto der neuen Maschine ins DMS geladen, die war Rot, aber in der Vorschau Blau (oder andersrum) ... am Ende hatte ich im WIC einen Parameter RGB mit BGR vertauscht. :lol:

Mein Problem war vor allem PDFs (inzwischen DevExpress) und Bilder (BMP, TIFF, GIF, PNG, JPEG) multithreated zu laden, runterzuskallieren und dann in der GUI anzuzeigen.
Teilweise extrem große/detailierte PDFs/Bilder. (technische Zeichnungen)

TurboMagic 22. Aug 2020 15:58

AW: max. TBitmap FMX vs. VCL
 
Na dann auf Report schreiben ;-)

bernhard_LA 22. Aug 2020 17:20

AW: max. TBitmap FMX vs. VCL
 
wir machen natürlich alles in x64, RAM 16 GBYTE und mehr vorhanden .......;
Die 500 x 500 pixel waren nur ein Code Fragment und als Beispiel gedacht :-)

unter VCL ging bei uns wie bereits geschrieben h=20.000 und W= 20.000 , 30.000 pixel * 15.000 pixel waren auch möglich, aber eben nicht 50k * 50K Bitmaps,
alles mit pf24bit.

Wer kann über große FMX Bitmaps berichten, Grafikformat *.jpg, *.tig oder *.bmp ?
ist hier der Video Speicher entscheidend , muss man was im Win hierfür konfigurieren ?
Was wäre das beste Pixelformat unter FMX ???
Will mit diesem Code dann auch unter LINUX wieder arbeiten können ....

himitsu 22. Aug 2020 17:46

AW: max. TBitmap FMX vs. VCL
 
Da hast du jetzt ein Problem, beim FMX.Graphics.TBitmap :angle:


Delphi-Quellcode:
procedure TBitmap.SetSize(const AWidth, AHeight: Integer);
begin
  ..
  if (AWidth > CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize)) or
     (AHeight > CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize))
  then
    raise EBitmapSizeTooBig.CreateRes(@SBitmapSizeTooBig);
Das hier klingt zwar nett,
Delphi-Quellcode:
type
  TCanvas = class abstract(TInterfacedPersistent)
  public const
    MaxAllowedBitmapSize = $FFFF;
aber im FMX für Windows landet es bei TCanvasD2D und dort ist es nur 8192. :shock:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  with TBitmap.Create(6000, 6000) do begin
    ShowMessage(CanvasClass.ClassName + ' ' + CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize).ToString);
    Free;
  end;
end;
Eventuell kann man das TBitmap auch mit einem anderen BitmapImage/Canvas erstellen?
siehe TBitmapImage.CreateHandle -> CanvasClass.InitializeBitmap -> ...
oder TBitmap.GetCanvasClass -> TBitmapImage.GetCanvasClass -> TCanvasManager.GetDefaultCanvas -> FDefaultCanvasClass

bernhard_LA 22. Aug 2020 21:40

AW: max. TBitmap FMX vs. VCL
 
8K * 8K pixel ist ja gar nix ..... :warn:

Medium 23. Aug 2020 12:15

AW: max. TBitmap FMX vs. VCL
 
Ich vermute mal stark, dass das letztlich damit zusammen hängt, dass FMX mittels D3D zeichnet, und Bitmaps daher als Textur eingehen. So weit ich weiß, sind die maximalen Texturgrößen gerade bei den Nicht-Gamer-Grafikkarten teils ziemlich begrenzt - 8192² scheint mir da plausibel.

Wahrscheinlich muss man die Bilddatei vorab in eine eigene Datenstruktur bringen, aus der man dann Pixeldaten in kleineren Rechtecken zur Anzeige an die API geben kann. Man verliert natürlich die ganzen vorgefertigten Zeichenfunktionen - es sei denn, man führt diese auf den kleineren Rechtecken in einem API Bitmap aus, und überträgt diese wieder zurück in die eigene Struktur.

Letztlich bleibt aber auch festzuhalten, dass Bitmaps solcher Größe klar in die Rubrik "Spezialanwendung" fallen, deren native Unterstützung man, finde ich, nicht unbedingt in einer so allgemein gedachten API wie FMX (oder auch VCL) voraussetzen kann.

himitsu 23. Aug 2020 15:06

AW: max. TBitmap FMX vs. VCL
 
Die registrierten TCanvasManager.FCanvasList kann man leider nicht ändern (strict private),
aber hab bissl was gefunden.

FMX.Canvas.D2D : TCustomD2D, TCustomBitmapCodecWIC= BMP JPEG PNG GIF TIFF ICO WMP ... WIC klingt ja eigentlich nicht schlecht
FMX.Canvas.GDIP : TCanvasGdiPlus
FMX.Canvas.GPU : TCustomCanvasGpu, TBitmapCtx
FMX.Canvas.Mac : TCanvasQuartz, TQuartzBitmap
FMX.Graphics : TPrinterCanvas

In TCanvasManager.GetDefaultCanvas an TCanvasManager.FDefaultCanvasClass kommst nicht ran.
TBitmap.GetCanvasClass oder TBitmapImage.GetCanvasClass lassen sich auch nicht überschreiben.
TBitmapImage/TCanvas/TCanvasClass kann man im TBitmap nicht zuweisen/austauschen. (keine aufrufbaren Setter-Methoden oder Write-Property)
TCanvasManager.RegisterCanvas kann man aufrufen und eine Canvas-Klasse nochmal mit anderen Parametern registrieren (Default=True), aber bringt nichts, weil es zuletzt gefunden und somit ignoriert wird.
So gesehn ist das schon ein bissl krank.

Hatte gedacht/gehofft so kommt was Anderes raus, aber es bleibt bei TCustomD2D mit 8192.
Delphi-Quellcode:
TCanvasManager.EnableSoftwareCanvas(True);
Image := TBitmap.Create(x, y);
TCanvasManager.EnableSoftwareCanvas(False);
FMX.Canvas.GDIP, FMX.Canvas.GPU ins USES, selbst wenn in der DPR als Erstes, ändert nichts.

Delphi-Quellcode:
class function TCanvasD2D.GetAttribute(const Value: TCanvasAttribute): Integer;
const
  DefaultMaxTextureSize = 8192; // According DirectX 10 specification.
Das wäre per se überschreibbar (override), aber hilft nichts, da sich die Ableitung nicht einbinden lässt, bzw. das originale TCanvasD2D immer zuerst gefunden wird.


Bleibt wohl nur eine Beschwerde im QualityPortal und auf Delphi 10.9 warten.
Oder eine externe Graphic-Lib verwenden.

Im Windows kannst dir auch das VCL-TBitmap reinholen. :stupid:

TurboMagic 23. Aug 2020 15:27

AW: max. TBitmap FMX vs. VCL
 
Na dann erstell doch mal so einen QP report... ;-)
Auf dass wir das flexibler bekommen.

Harry Stahl 23. Aug 2020 16:50

AW: max. TBitmap FMX vs. VCL
 
Liste der Anhänge anzeigen (Anzahl: 1)
Es hängt tatsächlich von der verwendeten Canvas-Klasse ab. Man kann da leider nur global drauf Einfluss nehmen.

Standardmäßig wird die TcanvasD2D Klasse verwendet, wenn man die ausschaltet, dann wird TCanvasGDIPlus verwendet, das funktioniert zumindest unter Windows und Linux (MACOS habe ich nicht ausprobiert).

Wenn man also in der .DPR-Datei, direkt als ersten Befehl

Delphi-Quellcode:
 GlobalUseDirect2D := false;
eingebt (also noch vor "Application.Initialize"), kann man Grafiken in der Größe 65000x65000 Bildpunkte erzeugen und verarbeiten, siehe anliegenden Screenshot (mit Source-Code) ein geladenes Bild unter Linux mit 21.600 x 10.800 Bildpunkten (größeres Bild habe ich gerade nicht zur Hand).

Dafür muss noch die Unit FMX.Types in die DPR-Datei eingebunden werden.

Die Nichtverwendung von Direct2D wird allerdings nachteilige Auswirkungen auf die allgemeine Performance der App haben, wie groß, müsstest Du prüfen. Unter Umständen könnte man dann überlegen, eine Extra App zu machen, welche für die Verarbeitung dieser großen Bild-Dateien zuständig ist (und dann eben nur dieser Part etwas langsamer wäre).

himitsu 23. Aug 2020 17:07

AW: max. TBitmap FMX vs. VCL
 
Zitat:

Zitat von Harry Stahl (Beitrag 1472304)
Delphi-Quellcode:
GlobalUseDirect2D := false;

Das wird in RegisterCanvasClasses verwendet, also meinen TestCode angepasst.
Delphi-Quellcode:
if GlobalUseDirect2D then begin
  FMX.Canvas.D2D.UnregisterCanvasClasses;
  TCanvasManager.EnableSoftwareCanvas(False); // um den Cache (FDefaultCanvasClass) zu löschen
end;
with TBitmap.Create(6000, 6000) do begin
  if GlobalUseDirect2D then begin
    FMX.Canvas.D2D.RegisterCanvasClasses;
    TCanvasManager.EnableSoftwareCanvas(False); // um den Cache zu löschen
  end;
  ShowMessage(CanvasClass.ClassName + ' ' + CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize).ToString);
  Free;
end;
Aber neee, hilft nix. :roll:


Allerdings das
Delphi-Quellcode:
GlobalUseGPUCanvas := True; // FMX.Types
ändert es zu "TCanvasGpu 16384" (auch ohne den Deregistrierungs-Code), aber hilft auch nicht viel mehr. :stupid:


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:06 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz