Convert bitmap to PNG in-memory in C++ (win32)

后端 未结 8 1601
长情又很酷
长情又很酷 2020-12-03 08:02

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

相关标签:
8条回答
  • 2020-12-03 08:05

    LodePNG (GitHub) is a lib-less PNG encoder/decoder.

    0 讨论(0)
  • 2020-12-03 08:06

    If you want to only use Windows APIs, WIC is the way to accomplish this, and it supports both Bitmaps and PNGs.

    0 讨论(0)
  • 2020-12-03 08:13

    It would probably be better to use a library instead of reinventing the wheel yourself.

    Look into freeImage

    0 讨论(0)
  • 2020-12-03 08:18

    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).

    0 讨论(0)
  • 2020-12-03 08:18

    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.

    0 讨论(0)
  • 2020-12-03 08:20

    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.

    0 讨论(0)
提交回复
热议问题