AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi TMetaFile zuschneiden

TMetaFile zuschneiden

Ein Thema von Der schöne Günther · begonnen am 6. Mai 2020 · letzter Beitrag vom 15. Mai 2020
Antwort Antwort
Der schöne Günther

Registriert seit: 6. Mär 2013
5.866 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

TMetaFile zuschneiden

  Alt 6. Mai 2020, 20:47
Ja, ich habe die Suche zu "EMF" und "TMetaFile" bemüht.

Ich benutze den Steema TeeChart um mir eine Vektorgrafik erstellen zu lassen. Eine entsprechende Routine gibt ein TMetaFile zurück. Ich habe Null Erfahrung mit der Klasse. Ich stehe vor dem Problem dass das TMetaFile rechts und unten leeren Raum enthält wenn die Anwendung vom Betriebssystem hochskaliert wird. Also nicht "DPI-Aware" ist, Windows aber mit > 100 % Skalierung läuft.

Im Anhang einmal die EMF-Datei als PNG und einmal in einer ZIP-Datei.

Ich möchte dieses Bild zuschneiden. Ich habe keine Ahnung wie. Kann mir jemand einen Tipp geben?

PS: Wenn man das Manifest der Anwendung erweitert und sie selbst die Skalierung übernimmt stimmt die Grafik wieder. Die Anwendung "dpi aware" zu machen haben wir auf der Roadmap, aber eine schnelle Lösung für dieses TMetaFile wäre natürlich trotzdem schön.
Miniaturansicht angehängter Grafiken
metafile.png  
Angehängte Dateien
Dateityp: zip metafile.zip (4,6 KB, 7x aufgerufen)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
2.908 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#2

AW: TMetaFile zuschneiden

  Alt 7. Mai 2020, 09:12
Hm, tricky. Hatte ich mir einfacher und weniger aufwendig vorgestellt.
Ich habe es nur über den Umweg über ein TBitmap "geschafft".
Und die neue Datei ist auch 744 KB groß, gegenüber dem Original mit 47,8 KB. Da steht die Befürchtung im Raum, dass nicht wirklich die GDI-Befehle platzsparend in der neuen EMF-Datei stehen, sondern einfach nur das Bitmap (also als eine Ansammlung von Bytes) drin steckt.

Delphi-Quellcode:
procedure TForm1.btn1Click(Sender: TObject);
var
  Metafile: TMetafile;
  Metafile2: TMetafile;
  MetafileCanvas: TMetafileCanvas;
  OldSize, NewSize: TRect;
  Bitmap: TBitmap;
begin
  Metafile := TMetafile.Create;
  try
    Metafile.LoadFromFile('C:\Temp\metafile\metafile.emf');

    OldSize := TRect.Create(0, 0, Metafile.Width, Metafile.Height);
    NewSize := TRect.Create(0, 0, 680, 280);

    Bitmap := TBitmap.Create;
    try
      Bitmap.SetSize(OldSize.Width, OldSize.Height);
      Bitmap.Canvas.StretchDraw(OldSize, Metafile);
      Bitmap.SetSize(NewSize.Width, NewSize.Height);
      Bitmap.SaveToFile('C:\Temp\metafile\metafile2.bmp');

      Metafile2 := TMetafile.Create;
      try
        Metafile2.SetSize(NewSize.Width, NewSize.Height);

        MetafileCanvas := TMetafileCanvas.Create(Metafile2, 0);
        try
          MetafileCanvas.StretchDraw(NewSize, Bitmap);
        finally
          MetafileCanvas.Free;
        end;

        Metafile2.SaveToFile('C:\Temp\metafile\metafile2.emf');
      finally
        Metafile2.Free;
      end;
    finally
      Bitmap.Free;
    end;
  finally
    Metafile.Free;
  end;
end;
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
2.908 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#3

AW: TMetaFile zuschneiden

  Alt 7. Mai 2020, 09:21
Schuß ins Blaue:
Über die Draw-Commmands/GDI-Befehle iterieren und die Befehle ignorieren, die den weißen Rand zeichnen und das auf ein neues Metafile umlenken.

https://docs.microsoft.com/de-de/win...numenhmetafile
https://docs.microsoft.com/de-de/pre...162606(v=vs.85)

Aufwand zu nutzen Verhältnis steht in Frage?
Gegenfalls einfach mal Steema anschreiben, ob man das beim Export einfach weg bekommt?
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
5.866 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: TMetaFile zuschneiden

  Alt 7. Mai 2020, 09:50
Bei Steema habe ich ehrlich gesagt die Hoffnung aufgegeben dass die noch etwas in die Delphi-Welt investieren. Vor ein paar Jahren war das noch besser, aber der Fehler ist denen seit 2015 bekannt. Er wurde 2018 nochmal ausgekramt und hat es anscheinend nicht mal im zweiten Anlauf in den Bugtracker geschafft.

Klar, das Problem lässt sich beheben indem man die Anwendung "Dpi aware" macht, aber das auch nicht an einem Nachmittag gemacht. Alternativ könnte ich in den Steema Source code einsteigen aber die Zeit investiere ich lieber um die VCL-Oberfläche mit DPI-Skalierung vertraut zu machen.
  Mit Zitat antworten Zitat
Redeemer

Registriert seit: 19. Jan 2009
Ort: Kirchlinteln (LK Verden)
879 Beiträge
 
Delphi 2009 Professional
 
#5

AW: TMetaFile zuschneiden

  Alt 7. Mai 2020, 10:37
Man kann auch den PENHMETAHEADER benutzen. Hier ein Beispiel aus einem anderen Kontext:
Delphi-Quellcode:
procedure TSVGMetafile.FixRDPBug(const Handle: HDC);
var
  Temp: TMemoryStream;
  Header: PENHMETAHEADER;
begin
  // Workaround für einen Fehler in RDP, durch den szlMillimeters und rclFrame falsch sind, wenn der Hauptbildschirm des verbindenden Rechners nicht das Seitenverhältnis 4:3 hat
  // vgl. https://stackoverflow.com/a/1533053
  // Kann leider nicht beim geladenen Bild geändert werden, da man an szlDevice (HORZRES und VERTRES bei GetDeviceCaps) nicht im Speicher des vorhandenen Bildes ran kommt
  // Bug scheint in Windows 10 nicht mehr zu existieren.

  // Besteht KEINE Remote-Desktop-Verbindung? Dann Abbruch.
  // Keine Ahnung, ob das Anfang August funktioniert hat, aber ich habe jetzt Ende Oktober keinen Self.Handle mehr, die Methode gibt daher 0 zurück, was anders als 320 bzw. 240 ist.
  // Daher wird der Handle von TMetafileCanvas übergeben.
  if GetDeviceCaps(Handle, HORZSIZE) <> 320 then Exit;
  if GetDeviceCaps(Handle, VERTSIZE) <> 240 then Exit;
  // Theoretisch können diese Werte auch ohne RDP auftreten, wenn der Nutzer einen 4:3-Bildschirm besitzt.
  // FixRDPBug macht korrekte Bilder nicht kaputt, daher geht es hier ausschließlich um die Performance, die bei einem Durchlauf des folgenden Codes verloren geht.

  Temp := TMemoryStream.Create();
  try
    Self.SaveToStream(Temp);
    if Temp.Size > 0 then
    begin
      Temp.Position := 0;
      Header := Temp.Memory;

      Header^.rclFrame.Right := (Header^.rclBounds.Right + 1) * 100;
      Header^.rclFrame.Bottom := (Header^.rclBounds.Bottom + 1) * 100;
      Header^.szlDevice.cx := 320; // gleiche Werte für beide szl-Felder machen es einfacher, Rundungsfehler hierüber zu vermeiden (man kann einfach mit 100 multiplizieren)
      Header^.szlDevice.cy := 240;
      Header^.szlMillimeters.cx := 320;
      Header^.szlMillimeters.cy := 240;

      inherited LoadFromStream(Temp);
    end;
  finally
    Temp.Free();
  end;
end;
Janni
2005 PE, 2009 PA, XE2 PA
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
5.866 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: TMetaFile zuschneiden

  Alt 15. Mai 2020, 19:44
Ich habe noch einen Workaround... naja eher Trick entdeckt der einem das Leben hier vielleicht etwas einfacher macht:
  1. Mache die Anwendung HighDPI-aware
  2. Setze in der DPR noch vor Application.Initialize() die Thread-DPI-Awareness auf "UNAWARE"
  3. Führe das Erstellen der Vektorgrafik in einem separaten Thread aus. Der Thread muss zu Beginn separat auf High-DPI-Aware gestellt werden.
  4. ???
  5. Gewinn!

Ein einzelner Thread kann mittels SetThreadDpiAwarenessContext seine DPI-Awareness ändern.

Geändert von Der schöne Günther (15. Mai 2020 um 19:58 Uhr) Grund: Es scheint, Schritt 1 und 2 waren sogar überflüssig. Großartig!
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:41 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf