renz
Neues Mitglied
Unterschiedliche Positionen in der Ausgabe einer im Canvas-Element enthaltenen Bitmap nach der Speicherung des Inhalts eines Canvas-Elements als Bitmap in einer WPF-Anwendung, wenn dem Canvas zuvor ein Visual hinzugefügt worden ist.
VS 2019; C#; WPFNach meinem bisherigen Verständnis sollte einer Büchse auch nur das entnommen werden können, was zuvor in irgendeiner Weise hinein gepackt worden ist. Im vorliegenden Fall scheint jedoch etwas mehr hineinzukommen - etwas, das sich auf den Umraum der Büchse bezieht. Zur Aufgabenstellung:
- Einem Grid wurde in Grid.Column="5" Grid.Row="1" Grid.RowSpan="3" ein Canvas-Element hinzugefügt, das wiederum ein Image-Element sowie ein Rectangle-Element enthält. Damit die automatische Größenanpassung an den Inhalt des Image-Elements zwischen <Window> <ScrollViewer> <DockPanel> <Menu> <Grid> <Canvas> <Image> und <Rectangle jederzeit gegeben ist, wurden Breite und Höhe des Canvas-Elements an die aktuellen Werte des Images-Elements gebunden sowie die Werte für Breite und Höhe des Image-Elements auf „Auto“ festgelegt. Außerdem wurden die Werte für minimale Breite und minimale Höhe des Image-Elements an die aktuellen Werte des Canvas-Elements gebunden. Analog erfolgte die Bindung für das Rectangle-Element.
- Zur Laufzeit wird dem Canvas-Element eine Bitmap zugewiesen, auf der entsprechend den Gegebenheiten i.d.R. einige Tausend grafische Elemente zu erstellen sind, was u.a. mit dem >System.Windows.Shapes.Line-Befehl< bewerkstelligt werden kann.
- Natürlich soll die im Canvas-Element erzeugte Visualisierung auch in anderen Bildverarbeitungsprogrammen zur Verfügung stehen, so daß die Speicherung seines Inhalts als Bitmap erforderlich ist. Dem Inhalt der Bitmap liegen 3 mögliche Ansichten des Canvas-Elements zugrunde:
- die in das Image-Element geladene Bitmap
- die auf dem Image erstellte Zeichnung
- a und b gemeinsam in einer Ansicht.
- Die erforderliche Methode zum Speichern der jeweiligen Zustände folgt dem bekannten Mechanismus durch Erzeugung eines FileStream’s mit gewünschter BitmapEncoder-Auswahl. Die einzig interessante Zeile:
// Daten ausgeben:
rtb.Render(visual: Canv01);
// oder alternativ: rtb.Render(visual: Grd01.Children[13]);
bestimmt, daß der Inhalt von Canvas als Visual zu rendern ist.
Obwohl es aus meiner Sicht am bestehenden Programm nichts zu beanstanden gibt, überrascht mich doch das Ergebnis der gespeicherten Bitmap. Wie in den beigefügten Abbildungen zu sehen, wird der Canvas-Inhalt mit einem Versatz sowohl in der X- als auch der Y-Achse gespeichert, der zuvor im Code jedoch nicht explizit definiert worden war. Logischer Weise reicht nun die für die Bitmap vorgesehene Fläche, die ja nur gleich der Fläche des Canvas-Elementes sein sollte, nicht mehr aus, so daß der Canvas-Inhalt am Ende abgeschnitten erscheint. Zur Erzeugung eines optisch akzeptablen Zustands bedarf es daher der Einführung eines Korrekturwertes, der sich aus dem Abständen des Canvas-Elements zum linken und oberen Rand des Grids bestimmt. In diesem Fall sorgt die Anweisung:
Code:
[/INDENT][/INDENT]
[INDENT=2][INDENT=2]RenderTargetBitmap rtb = new RenderTargetBitmap([/INDENT][/INDENT]
[INDENT=2][INDENT=2]pixelWidth: (int)Canv01.ActualWidth + (470 * 2),[/INDENT][/INDENT]
[INDENT=2][INDENT=2]pixelHeight: (int)Canv01.ActualHeight + (30 * 2),[/INDENT][/INDENT]
[INDENT=2][INDENT=2]dpiX: 0,[/INDENT][/INDENT]
[INDENT=2][INDENT=2]dpiY: 0,[/INDENT][/INDENT]
[INDENT=2][INDENT=2]pixelFormat: PixelFormats.Pbgra32);[/INDENT][/INDENT]
[INDENT=2][INDENT=2]
Abb. 1 – Zustand des gefüllten Canvas-Elements vor dem Speichern
Abb. 2 – Canvas-Element mit der zuvor erzeugten Bitmap
Die von mir nicht beabsichtigte Hinzufügung der Position des Canvas im Grid zur erzeugten Bitmap entspricht daher der Büchse, der mehr entnommen wurde, als hineingetan. Letztendlich handelt es sich im Programmablauf um einen Schönheitsfehler, der zu unnötigem Aufwand führt. Da mir nicht klar ist, wie dieser zu vermeiden ist, stelle ich mein Anliegen in die Community mit der Hoffnung, daß mir jemand auf die Sprünge helfen kann.
Interessanterweise entsteht beschriebener Effekt nicht, wenn in der Anweisung:
rtb.Render(visual: Canv01);
statt des Canvas-Elements das Image-Element oder das Rectangle-Element verwendet werden. So stellt sich die Frage, wie dem Encoder beigebracht werden kann, nur das Canvas-Element im zu erzeugenden Format zu berücksichtigen.