Can I convert a bitmap to PNG in memory (i.e. without writing to a file) using only the Platform SDK? (i.e. no libpng, etc.).
I also want to be able to define a tran
LodePNG (GitHub) is a lib-less PNG encoder/decoder.
If you want to only use Windows APIs, WIC is the way to accomplish this, and it supports both Bitmaps and PNGs.
It would probably be better to use a library instead of reinventing the wheel yourself.
Look into freeImage
I read and write PNGs using libpng and it seems to deal with everthing I throw at it (I've used it in unit-tests with things like 257x255 images and they cause no trouble). I believe the API is flexible enough to not be tied to file I/O (or at least you can override its default behaviour e.g see png_set_write_fn
in section on customization)
In practice I always use it via the much cleaner boost::gil PNG IO extension, but unfortunately that takes char*
filenames and if you dig into it the png_writer
and file_mgr
classes in its implementation it seem pretty tied to FILE*
(although if you were on Linux a version using fmemopen and in-memory buffers could probably be cooked up quite easily).
GDI's (old school, non-plus) has a GetDIBits
method that can be asked to output bits using PNG compression (BITMAPINFOHEADER::biCompression
== BI_PNG
). I wonder if this could be used to create a PNG file? Using GetDIBits
to write standard bitmap files is complicated enough - so i suspect this would be even more difficult.
The CImage class (ATL/MFC) supports saving into PNG format. Like the GDI+ solution, it also supports saving to a stream. Here's some code I use to save it to a CByteArray:
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();
I don't know if you'd want to use ATL or MFC, though.