Ich bearbeite derzeit sehr große Bilder, die im Wesentlichen durch Zusammenfügen vieler kleinerer Bilder (z. B. Panorama- oder Fotomosaik-Software) erzeugt werden. Um Out-of-Memory-Ausnahmen zu vermeiden (im Speicher sind nur "Karten", wie die kleineren Bilder angeordnet werden), habe ich Code geschrieben, der diese Bilder zeilenweise als Bitmaps mit BinaryWriter und LockBits speichert. So weit, so gut.
Das Problem ist jetzt, dass ich diese Bilder auch als JPEGs (oder PNGs) speichern möchte. Da ich ziemlich neu in c bin, kann ich mir im Moment nur zwei Möglichkeiten ausdenken:
1) Ähnlich wie beim Speichern der Bitmap. Generieren eines JPEG-Headers und Speichern der großen Bilder Zeile für Zeile, vorher irgendwie komprimieren. Ich habe jedoch keine Ahnung, wie ich die Komprimierung durchführen soll.
2) Übertragen Sie die bereits gespeicherte Bitmap in den Speicher und speichern Sie sie als codiertes JPEG.
Da der zweite Ansatz einfacher schien, habe ich so etwas versucht:
%Vor%Das Problem ist jetzt, dass die save-Methode versucht, die Bitmap zuerst vollständig in den Speicher zu laden, was zu einer Nicht-Speicher-Ausnahme führt.
Ich wäre mehr als glücklich für Vorschläge, wie Sie dieses Problem lösen oder umgehen können!
Beachten Sie, dass JPEG-Komprimierung einige wichtige nicht-triviale Nachteile hat:
1) JPEG ist verlustbehaftet, Sie regenerieren also nicht dasselbe Bild. Dies mag durchaus akzeptabel sein, aber wenn Sie das Quellbild genau regenerieren müssen, dann ist PNG der richtige Weg.
2) JPEG ist an 8-Pixel-Grenzen ausgerichtet. Wenn Sie Bilder zusammenfügen, deren Größe nicht das Vielfache von 8 ist, entweder in der Breite oder in der Höhe, erhalten Sie starke Artefakte an den Bildgrenzen
In Anbetracht Ihres Anwendungsfalls würde ich eher nicht empfehlen, Bilder zusammenzunähen und einen Standardkomprimierungsalgorithmus wie PNG oder Zlib für jedes kleinere Bild zu verwenden. Sie können die resultierenden komprimierten Streams immer noch in einer einzigen Datei speichern. Der Vorteil ist, dass Sie dann direkt an der Position des kleinen Bildes, das Sie extrahieren möchten, "springen" können, was * viel * Speicher * spart.
Der Nachteil ist, dass Sie nicht alle kleineren Bilder in eine große Vorschau "visuell" anzeigen können (Sie müssen ein Programm für diese Verwendung erstellen).
Ich vermute, dass Sie das in .NET nicht machen können, aber Sie können immer in eine C-Bibliothek rufen, um das Heavy Lifting durchzuführen. Ich habe es nicht selbst benutzt, aber ich schlage vor, dass Sie sich die GraphicsMagick Bibliothek ansehen. Es ist eine C-Bibliothek mit Lizenzierung, die sowohl Open-Source-und kommerzielle Nutzung ermöglicht und es sieht aus wie es tun könnte, was Sie brauchen.
(da der Titel "oder ein anderes komprimiertes Format" sagt)
TIFF-Format hat eine Vorstellung von Kacheln und Streifen. Beide können verwendet werden, um zu vermeiden, dass das gesamte große Bild zu jeder Zeit im Speicher ist. Vielleicht werden Kacheln für Sie nützlich sein, da Sie kleine Bilder zusammenfügen.
Sie könnten LibTiff.Net (kostenlos, kommerziell, Open Source, nur in C # geschrieben) für die Aufgabe ausprobieren.
Es gibt einen Artikel Grundlegende Einführung in die Fähigkeiten des Bibliothek mit Informationen zum streifen- und kachelorientierten Bild-IO (im zweiten Teil des Artikels).
Disclaimer: Ich arbeite für das Unternehmen.
Tags und Links c# stream bitmap compression jpeg