Mercurial > foo_out_sdl
diff foosdk/sdk/libPPUI/gdiplus-helpers-webp.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/libPPUI/gdiplus-helpers-webp.h Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,46 @@ +#pragma once + +#include "gdiplus_helpers.h" + +// Presumes prior #include of webp/decode.h + +inline bool IsImageWebP(const void * ptr, size_t bytes) { + if (bytes < 12) return false; + return memcmp(ptr, "RIFF", 4) == 0 && memcmp((const char*)ptr + 8, "WEBP", 4) == 0; +} + + +// WebP-aware GdiplusImageFromMem +static std::unique_ptr<Gdiplus::Image> GdiplusImageFromMem2(const void * ptr, size_t bytes) { + GdiplusErrorHandler EH; + using namespace Gdiplus; + if (IsImageWebP(ptr, bytes)) { + WebPBitstreamFeatures bs; + if (WebPGetFeatures((const uint8_t*)ptr, bytes, &bs) != VP8_STATUS_OK) { + throw std::runtime_error("WebP decoding failure"); + } + const Gdiplus::PixelFormat pf = bs.has_alpha ? PixelFormat32bppARGB : PixelFormat32bppRGB; + const int pfBytes = 4; // Gdiplus RGB is 4 bytes + int w = 0, h = 0; + // ALWAYS decode BGRA, Gdiplus will disregard alpha if was not originally present + uint8_t * decodedData = WebPDecodeBGRA((const uint8_t*)ptr, bytes, &w, &h); + pfc::onLeaving scope([decodedData] {WebPFree(decodedData); }); + if (decodedData == nullptr || w <= 0 || h <= 0) throw std::runtime_error("WebP decoding failure"); + + std::unique_ptr<Bitmap> ret ( new Gdiplus::Bitmap(w, h, pf) ); + EH << ret->GetLastStatus(); + Rect rc(0, 0, w, h); + Gdiplus::BitmapData bitmapData; + EH << ret->LockBits(&rc, 0, pf, &bitmapData); + uint8_t * target = (uint8_t*)bitmapData.Scan0; + const uint8_t * source = decodedData; + for (int y = 0; y < h; ++y) { + memcpy(target, source, w * pfBytes); + target += bitmapData.Stride; + source += pfBytes * w; + } + EH << ret->UnlockBits(&bitmapData); + return ret; + } + return GdiplusImageFromMem(ptr, bytes); +}
