2008-12-14 17 views
15

Kann ich eine Bitmap in PNG im Speicher (d. H. Ohne in eine Datei zu schreiben) nur mit dem Platform SDK konvertieren? (d. h. keine libpng usw.).Konvertieren von Bitmap zu PNG im Speicher in C++ (Win32)

Ich möchte auch eine transparente Farbe (kein Alpha-Kanal) für dieses Bild definieren können.

Die GdiPlus-Lösung scheint auf Bilder mit einer durch 4 teilbaren Breite von beschränkt zu sein. Alles andere schlägt während des Aufrufs von Save() fehl. Kennt jemand den Grund für diese Einschränkung und wie/ob ich es umgehen kann?

Update: Bounty

Ich beginne eine Prämie (ich will das wirklich arbeiten). Ich habe die GDI + -Lösung implementiert, aber wie gesagt, sie ist auf Bilder mit Quad-Breite beschränkt. Das Kopfgeld wird an jeden vergeben, der dieses Problem mit der Breite lösen kann (ohne die Bilddimensionen zu ändern) oder eine alternative nicht-GDI + -Lösung anbieten kann, die funktioniert.

+0

um zu beginnen, habe ich ein Beispiel gefunden, um ein Bitmap als PNG mit Gdi + zu speichern: http://dotnet-snippets.de/dns/gdi-speichern-eines-png-SID814.aspx vielleicht ist es nützlich –

+0

Diese Lösung funktioniert für mich, auch mit Bildern, deren Breite nicht durch 4 teilbar ist. Ich bin auf Windows Vista und verwende Visual C++ 2008. –

+0

Warum willst du libpng nicht benutzen? Es hat eine sehr freizügige Lizenz. –

Antwort

14

Ich lese und schreibe PNGs mit libpng und es scheint mit allem zu tun Ich werfe es (Ich habe es in Unit-Tests mit Dingen wie 257x255 Bilder verwendet und sie verursachen keinen Ärger). Ich glaube, die API flexibel genug, um nicht in Datei gebunden wird I/O (oder zumindest können Sie die Standardverhalten siehe zB außer Kraft setzen png_set_write_fn in Abschnitt customization)

In der Praxis ich es immer verwenden über die viel sauberen boost::gilPNG IO extension , aber leider dauert das char* Dateinamen und wenn Sie graben die png_writer und file_mgr Klassen in seiner Umsetzung scheint es ziemlich gebunden an FILE* (obwohl, wenn Sie auf Linux eine Version mit fmemopen und In-Memory-Puffer konnte wahrscheinlich ziemlich leicht gekocht werden).

+0

+1 danke. Darf ich Boost :: GIL mit PNG IO verwenden? Ich habe keine Ahnung von Integration und davon Gebrauch machen. – Viet

+1

Boost GIL enthält eine "IO-Erweiterung", die derzeit das grundlegende Lesen und Schreiben in PNG-Dateien unterstützt, aber nicht genügend Hooks zum Lesen/Schreiben von In-Memory-Streams bietet, wie das ursprüngliche Poster gefragt hat. Es scheint eine neue IO-Erweiterung (google something wie "Boost GIL new IO extension", um verschiedene Postings zu finden) in Entwicklung, die viel mehr Flexibilität in diesem Bereich bietet. – timday

+1

libpng, während eine gute Lösung, scheint die Einschränkung der Frage "nur die Verwendung des Platform SDK" zu verletzen. –

2

Es wäre wahrscheinlich besser, eine Bibliothek zu verwenden, anstatt das Rad selbst neu zu erfinden.

Blick in freeImage

11

Auf dieser Seite der Code zeigt, wie ein Bitmap zu PNG konvertiert es in eine Datei schreiben: http://dotnet-snippets.de/dns/gdi-speichern-eines-png-SID814.aspx. Anstatt in eine Datei zu schreiben, unterstützt die Bitmap-Methode Save auch das Schreiben in eine IStream (http://msdn.microsoft.com/en-us/library/ms535406%28VS.85%29.aspx). Mit der API-Funktion CreateStreamOnHGlobal können Sie einen Stream erstellen, der vom Arbeitsspeicher gesichert wird. (http://msdn.microsoft.com/en-us/library/aa378980%28VS.85%29.aspx). Die verwendete Bibliothek, GDI +, ist in Windows ab WindowsXP enthalten und funktioniert in Windows ab Windows98. Ich habe noch nie etwas damit gemacht, nur gegoogelt. Sieht so aus, als könntest du das benutzen.

+1

Was ist mit dem GDI + -Problem, das ich in der ursprünglichen Frage erwähnt habe? –

5

Ich habe GDI + zum Speichern einer Bitmap als PNG in eine Datei verwendet. Sie sollten wahrscheinlich die MSDN-Informationen über GDI + here und insbesondere diese Funktion GdipSaveImageToStream überprüfen.

Dieses Tutorial here wird wahrscheinlich auch einige Hilfe bieten.

3

GDI (alte Schule, Non-Plus) hat eine GetDIBits Methode, die aufgefordert werden kann, Bits mit PNG-Komprimierung (BITMAPINFOHEADER::biCompression == BI_PNG) auszugeben. Ich frage mich, ob dies verwendet werden könnte, um eine PNG-Datei zu erstellen? Die Verwendung von GetDIBits zum Schreiben von Standard-Bitmap-Dateien ist kompliziert genug - ich vermute, das wäre noch schwieriger.

+0

Für alle, die daran denken, diesen Router zu verwenden, finden Sie unter [Antwort auf "GetDIBits() schlägt mit PNG-Komprimierung"] (https://Stackoverflow.com/a/3101090/2910230) oder "[JPEG und PNG Erweiterungen für bestimmte Bitmap-Funktionen und -Strukturen (https://msdn.microsoft.com/en-us/library/dd145023 (VS.85) .aspx) "auf MSDN, mit dem es verknüpft ist. –

3

Wenn Sie nur Windows-APIs verwenden möchten, ist WIC der Weg, dies zu erreichen, und es unterstützt sowohl Bitmaps als auch PNGs.

+0

Sind Sie sicher, dass es nicht die gleiche seltsame Breitenbeschränkung wie GDI + hat? –

+0

Nein, nicht sicher - aber WIC ist definitiv moderner und auf dem neuesten Stand gehalten als GDI + –

6

Die CImage-Klasse (ATL/MFC) unterstützt das Speichern im PNG-Format. Wie die GDI + -Lösung unterstützt auch das Speichern in einem Stream. Hier einige Code, den ich benutze es zu einem CByteArray zu speichern:

CByteArray baPicture; 
IStream *pStream = NULL; 
if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) == S_OK) 
{ 
    if (image.Save(pStream, Gdiplus::ImageFormatPNG) == S_OK) 
    { 
    ULARGE_INTEGER ulnSize; 
     LARGE_INTEGER lnOffset; 
     lnOffset.QuadPart = 0; 
     if (pStream->Seek(lnOffset, STREAM_SEEK_END, &ulnSize) == S_OK) 
     { 
      if (pStream->Seek(lnOffset, STREAM_SEEK_SET, NULL) == S_OK) 
      {      
       baPicture.SetSize(ulnSize.QuadPart); 
       ULONG ulBytesRead; 
       pStream->Read(baPicture.GetData(), ulnSize.QuadPart, &ulBytesRead); 
      } 
     } 
    } 
} 
pStream->Release(); 

Ich weiß nicht, ob Sie ATL oder MFC verwenden, würde wollen, though.

+1

Leider gibt es kein ATL/MFC in meinem Projekt. –

+0

ok ... vielleicht könnte der Stream Save Teil nützlich sein, sollte es ähnlich zu dem mit GDI + – djeidot

+0

sein Das half mir für etwas, an dem ich arbeitete, +1 dafür mindestens. – Aardvark

16

LodePNG ist ein lib-less PNG-Encoder/Decoder.

Verwandte Themen