DrawingContext in Bitmap-Datei

8

Ich habe einen DrawingContext (Teil einer Visual oder DrawingGroup), wo ich eine Reihe von Rechtecken und / oder 1-Bit-Bildern übereinander zeichne. Stellen Sie es sich als maskierendes 1-Bit-Bild vor. Ich möchte dies in eine Bitmap-Bilddatei konvertieren.

Die Verwendung von RenderTargetBitmap ist keine Option, da sie nur im 32-Bit-Pixel-Format rendern kann. Wenn ich also ein 20MB 1-Bit-Bild rendern muss, dann habe ich 640MB (20 * 32) Speicher auf meinem Haufen. Das erzeugt natürlich eine großartige LOH-Fragmentierung, und die Anwendung läuft auf der zweiten Aufnahme nicht mehr voll aus.

Ich brauche also eine Möglichkeit, um eine 1-Bit-Bitmap-Datei effizient aus einem Zeichnungskontext zu schreiben. Irgendwelche Ideen / Vorschläge / alternative Methoden würden geschätzt.

    
LadderLogic 31.07.2012, 01:58
quelle

3 Antworten

7

Eine Reihe von Ideen, einige sind ein wenig verworren ...

Drucken Sie zu XPS und extrahieren Sie dann Bitmap

Sie könnten Visual auf ein XPS-Dokument drucken.

Wenn Sie Glück haben, werden die 1-Bit-Bilder, die Sie in DrawingContext gezeichnet haben, kombiniert und eine einzelne Bitmap in der XPS-Datei erzeugt.

Für die Rechtecke könnte es die Rechtecke als vektorbasierte Information im XPS behalten (die "Form" basierend auf Rectangle oder DrawingContext DrawRectangle könnte beides tun) .... wenn das passiert, dann erstelle ein Bitmap in dem Sie den Rechteckteil zeichnen und diese Bitmap in den Kontext zeichnen.

Sobald Sie die XPS-Dateien haben, können Sie sie analysieren und das "Bild" extrahieren, wenn Sie Glück haben, dass es darin erzeugt wurde. (XPS ist nur eine ZIP-Datei, die XAML verwendet, um Inhalt zu beschreiben und verwendet Unterverzeichnisse, um Bitmap-Bilddateien, Schriftarten usw. zu speichern.)

(Ich denke, Sie können die Klasse Package verwenden, um auf die Rohteile eines XPS-Dokuments zuzugreifen, oder XpsDocument für eine Interpretation auf höherer Ebene).

Oder zeigen Sie das XPS einfach in einem XPS-Viewer an, wenn Sie nur versuchen möchten, Ihre kombinierten 1-Bit-Bilder in einem anderen Kontext anzuzeigen.

Verwenden Sie einen Druckertreiber, der die Funktion zum Drucken in Bildern bereitstellt

Das ist nicht ideal ... nicht zuletzt, weil Sie einen Druckertreiber auf dem Rechner installieren müssen ... aber Sie können vielleicht einen "Print to Image" -Druckertreiber verwenden und diesen dann zur Erstellung verwenden Ihre Bitmap. Hier sind einige Vorschläge:

Erstellen Sie ein GDI + HBITMAP und führen Sie die Zeichnung mit GDI + -Aufrufen aus ... und verpacken Sie es anschließend zur Verwendung mit WPF ... oder speichern Sie es auf der Festplatte.

[1] Erstellen Sie zuerst eine GDI + -Bitmap, die groß genug ist, um Ihr zusammengesetztes Rendering aufzunehmen.

(Es gibt ein paar verschiedene Möglichkeiten, dies zu tun ... Eine Möglichkeit besteht darin, eine WriteableBitmap zu verwenden, um die Backbuffer-Bits / Speicher bereitzustellen ... das heißt, wenn Sie auf die Bits im Speicher zugreifen wollten ... in Ihrem Fall I glaube nicht, dass du es tun musst / musst).

%Vor%

Oder auf diese Weise, wenn Sie WriteableBitmap zugreifen möchten.

[2] Konvertieren Sie beliebige WPF-BitmapSources in GDI + -Bitmaps, sodass Sie sie mithilfe von DrawImage auf den GDI + -Grafikkontext zeichnen können.

Sie können das mit CopyPixels auf Ihren BitmapSources machen.

Für Ihre Rechtecke können Sie einfach den Renderbefehl GDI + DrawRectangle verwenden.

[3] Speichern Sie die GDI + Bitmap auf Festplatte

Verwenden Sie die .Save-Methode in System.Image.Bitmap, um sie als Bitmap zu speichern.

[4] Verwenden Sie das gespeicherte Bild als Quelle für ein Bildelement

(Beachten Sie, dass beim Laden des Bilds wahrscheinlich eine Menge Speicher verbraucht wird, obwohl es 1bpp ist, da der WPF-Rendering-Pfad alle 32 bpp beträgt).

[4] ODER umschließen Sie die GDI + -Bitmap für die Verwendung in WPF

Sie können InteropBitmap verwenden, um die GDI + -basierte Bitmap zu umbrechen, sodass Sie sie als BitmapSource in WPF verwenden können. (Bitte beachten Sie, dass es sich um eine 32bpp Eins handeln muss .... wenn es so ist ... dann sind Sie wieder an Platz 1 ... aber versuchen Sie es trotzdem).

Erstellen Sie eine Bitmap "Service"

Erzeuge einen anderen Prozess, der als Dienst dient (muss kein NT-Dienst sein ... könnte ein untergeordneter Prozess sein, den du startest), um deine kombinierten 1bpp-Bilder zu rendern .... es gibt verschiedene Möglichkeiten mit denen du kommunizieren kannst es gibt ihm die Rendering-Befehle.

Wenn der Speicherverbrauch zu hoch wird / die LOH fragmentiert wird, können Sie diesen Dienst neu starten.

Andere Ideen

Sie könnten mit OpenGL (zB OpenTK oder SharpGL) rendern, oder mit DirectX ... über den 3D-Pfad mit D3DImage oder Direct2D rendern (ob das sich genauso verhält wie RenderTargetBitmap in Bezug auf die Speichernutzung ... das ist zu finden aus).

Probiere NET 4.5 aus, da es im LOH Heap einige Verbesserungen gegeben hat:

Colin Smith 03.09.2012 01:02
quelle
2

Ich glaube nicht, dass Sie etwas besseres tun können. Da RenderTargetBitmap MILcore verwendet, auf das Sie nicht zugreifen können. Und ich glaube nicht, dass es eine andere Möglichkeit gibt, Visual zu kopieren. Aber ich denke, es gibt eine Option mehr. Es wird nicht eine Zeile sein, aber ich denke, es wird gut genug sein.

Grundsätzlich werden Sie visuell Block für Block rendern (PGBRA32) und es in BlackWhite im laufenden Betrieb konvertieren, und dann mit Blackwhite Buffer concat. Ich habe einen kleinen Beispielcode gestartet, aber auf halbem Weg entschieden, dass es nicht so einfach sein wird, aber Sie können es beenden.

%Vor%

Legen Sie also im Grunde eine neue WriteableBitmap mit dem BlackWhite-Format an und rufen Sie diese Funktion dann wie folgt auf:

%Vor%

// Speichern Sie dann blackWhiteFullBuffer bei Bedarf auf der Festplatte.

    
Erti-Chris Eelmaa 02.09.2012 07:27
quelle
0

Was ist mit PixelFormats

?

Bearbeiten : (Danke an Anders Gustafsson)

Das untere ist PixelFormats.BlackWhite , mit 1bit pro Pixel.

Auf diese Weise können Sie jedes BitmapImage in eine FormatConvertedBitmap konvertieren, in der Sie das Format in ein niedrigeres bpp ändern können.

    
mlemay 31.08.2012 11:20
quelle