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);
+}