annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #pragma once
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include "gdiplus_helpers.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 // Presumes prior #include of webp/decode.h
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 inline bool IsImageWebP(const void * ptr, size_t bytes) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 if (bytes < 12) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 return memcmp(ptr, "RIFF", 4) == 0 && memcmp((const char*)ptr + 8, "WEBP", 4) == 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 // WebP-aware GdiplusImageFromMem
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 static std::unique_ptr<Gdiplus::Image> GdiplusImageFromMem2(const void * ptr, size_t bytes) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 GdiplusErrorHandler EH;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 using namespace Gdiplus;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 if (IsImageWebP(ptr, bytes)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 WebPBitstreamFeatures bs;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 if (WebPGetFeatures((const uint8_t*)ptr, bytes, &bs) != VP8_STATUS_OK) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 throw std::runtime_error("WebP decoding failure");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 const Gdiplus::PixelFormat pf = bs.has_alpha ? PixelFormat32bppARGB : PixelFormat32bppRGB;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 const int pfBytes = 4; // Gdiplus RGB is 4 bytes
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 int w = 0, h = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 // ALWAYS decode BGRA, Gdiplus will disregard alpha if was not originally present
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 uint8_t * decodedData = WebPDecodeBGRA((const uint8_t*)ptr, bytes, &w, &h);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 pfc::onLeaving scope([decodedData] {WebPFree(decodedData); });
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 if (decodedData == nullptr || w <= 0 || h <= 0) throw std::runtime_error("WebP decoding failure");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 std::unique_ptr<Bitmap> ret ( new Gdiplus::Bitmap(w, h, pf) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 EH << ret->GetLastStatus();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 Rect rc(0, 0, w, h);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 Gdiplus::BitmapData bitmapData;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 EH << ret->LockBits(&rc, 0, pf, &bitmapData);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 uint8_t * target = (uint8_t*)bitmapData.Scan0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 const uint8_t * source = decodedData;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 for (int y = 0; y < h; ++y) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 memcpy(target, source, w * pfBytes);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 target += bitmapData.Stride;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 source += pfBytes * w;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 EH << ret->UnlockBits(&bitmapData);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 return GdiplusImageFromMem(ptr, bytes);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 }