Mercurial > foo_out_sdl
comparison foosdk/sdk/libPPUI/gdiplus_helpers.cpp @ 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 |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #include "stdafx.h" | |
| 2 #include "gdiplus_helpers.h" | |
| 3 | |
| 4 static bool _Once() { | |
| 5 ULONG_PTR token = 0; | |
| 6 Gdiplus::GdiplusStartupInput input; | |
| 7 Gdiplus::GdiplusStartupOutput output; | |
| 8 GdiplusErrorHandler() << Gdiplus::GdiplusStartup(&token, &input, &output); | |
| 9 return true; | |
| 10 } | |
| 11 | |
| 12 void GdiplusScope::Once() { | |
| 13 static bool done = _Once(); | |
| 14 (void)done; // suppress warning | |
| 15 } | |
| 16 | |
| 17 void GdiplusErrorHandler::Handle(Gdiplus::Status p_code) { | |
| 18 if (p_code != Gdiplus::Ok) { | |
| 19 switch (p_code) { | |
| 20 case Gdiplus::InvalidParameter: | |
| 21 throw pfc::exception_invalid_params(); | |
| 22 default: | |
| 23 throw std::runtime_error(pfc::format("Gdiplus error (", (unsigned)p_code, ")")); | |
| 24 } | |
| 25 | |
| 26 } | |
| 27 } | |
| 28 | |
| 29 HBITMAP GdiplusLoadBitmap(UINT id, const TCHAR* resType, CSize size) { | |
| 30 using namespace Gdiplus; | |
| 31 try { | |
| 32 auto stream = WinLoadResourceAsStream(GetThisModuleHandle(), MAKEINTRESOURCE(id), resType); | |
| 33 | |
| 34 GdiplusErrorHandler EH; | |
| 35 Image source ( stream ); | |
| 36 EH << source.GetLastStatus(); | |
| 37 | |
| 38 Bitmap resized (size.cx, size.cy, PixelFormat32bppARGB); | |
| 39 EH << resized.GetLastStatus(); | |
| 40 | |
| 41 { | |
| 42 Graphics target(&resized); | |
| 43 EH << target.GetLastStatus(); | |
| 44 EH << target.SetInterpolationMode(InterpolationModeHighQuality); | |
| 45 EH << target.Clear(Color(0, 0, 0, 0)); | |
| 46 EH << target.DrawImage(&source, Rect(0, 0, size.cx, size.cy)); | |
| 47 } | |
| 48 | |
| 49 HBITMAP bmp = NULL; | |
| 50 EH << resized.GetHBITMAP(Gdiplus::Color::White, &bmp); | |
| 51 return bmp; | |
| 52 } catch (...) { | |
| 53 PFC_ASSERT(!"Should not get here"); | |
| 54 return NULL; | |
| 55 } | |
| 56 } | |
| 57 | |
| 58 std::unique_ptr<Gdiplus::Image> GdiplusImageFromMem(const void* ptr, size_t bytes) { | |
| 59 using namespace Gdiplus; | |
| 60 GdiplusErrorHandler EH; | |
| 61 | |
| 62 CComPtr<IStream> stream; | |
| 63 stream.p = SHCreateMemStream((const BYTE*)ptr, pfc::downcast_guarded<UINT>(bytes)); | |
| 64 if (!stream) throw std::bad_alloc(); | |
| 65 std::unique_ptr<Image> source ( new Image(stream.p) ); | |
| 66 EH << source->GetLastStatus(); | |
| 67 return source; | |
| 68 } | |
| 69 | |
| 70 std::unique_ptr< Gdiplus::Bitmap > GdiplusResizeImage(Gdiplus::Image* source, CSize size, Gdiplus::PixelFormat pf) { | |
| 71 PFC_ASSERT(size.cx > 0 && size.cy > 0); | |
| 72 using namespace Gdiplus; | |
| 73 GdiplusErrorHandler EH; | |
| 74 std::unique_ptr<Bitmap> resized ( new Bitmap(size.cx, size.cy, pf) ); | |
| 75 EH << resized->GetLastStatus(); | |
| 76 Graphics target (resized.get() ); | |
| 77 EH << target.GetLastStatus(); | |
| 78 EH << target.SetInterpolationMode(InterpolationModeHighQuality); | |
| 79 EH << target.Clear(Color(0, 0, 0, 0)); | |
| 80 EH << target.DrawImage(source, Rect(0, 0, size.cx, size.cy)); | |
| 81 return resized; | |
| 82 } | |
| 83 | |
| 84 HICON GdiplusLoadIconFromMem(const void* ptr, size_t bytes, CSize size) { | |
| 85 using namespace Gdiplus; | |
| 86 try { | |
| 87 | |
| 88 GdiplusErrorHandler EH; | |
| 89 auto source = GdiplusImageFromMem(ptr, bytes); | |
| 90 auto resized = GdiplusResizeImage(source.get(), size); | |
| 91 HICON icon = NULL; | |
| 92 EH << resized->GetHICON(&icon); | |
| 93 return icon; | |
| 94 } catch (...) { | |
| 95 PFC_ASSERT(!"Should not get here"); | |
| 96 return NULL; | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 HICON GdiplusLoadIcon(UINT id, const TCHAR* resType, CSize size) { | |
| 101 GdiplusIconArg_t arg = { size }; | |
| 102 return GdiplusLoadIconEx(id, resType, arg); | |
| 103 } | |
| 104 | |
| 105 HICON GdiplusLoadIconEx(UINT id, const TCHAR* resType, GdiplusIconArg_t const& arg) { | |
| 106 using namespace Gdiplus; | |
| 107 try { | |
| 108 auto stream = WinLoadResourceAsStream(GetThisModuleHandle(), MAKEINTRESOURCE(id), resType); | |
| 109 | |
| 110 GdiplusErrorHandler EH; | |
| 111 | |
| 112 Bitmap resized(arg.size.cx, arg.size.cy, PixelFormat32bppARGB); | |
| 113 EH << resized.GetLastStatus(); | |
| 114 | |
| 115 { | |
| 116 Image source(stream); | |
| 117 EH << source.GetLastStatus(); | |
| 118 | |
| 119 Graphics target(&resized); | |
| 120 EH << target.GetLastStatus(); | |
| 121 EH << target.SetInterpolationMode(InterpolationModeHighQuality); | |
| 122 EH << target.Clear(Color(0, 0, 0, 0)); | |
| 123 EH << target.DrawImage(&source, Rect(0, 0, arg.size.cx, arg.size.cy)); | |
| 124 } | |
| 125 | |
| 126 | |
| 127 if (arg.transform) arg.transform(&resized); | |
| 128 | |
| 129 HICON icon = NULL; | |
| 130 EH << resized.GetHICON(&icon); | |
| 131 return icon; | |
| 132 } catch (...) { | |
| 133 PFC_ASSERT(!"Should not get here"); | |
| 134 return NULL; | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 HICON GdiplusLoadPNGIcon(UINT id, CSize size) { | |
| 139 return GdiplusLoadIcon(id, _T("PNG"), size); | |
| 140 } | |
| 141 | |
| 142 HICON LoadPNGIcon(UINT id, CSize size) { | |
| 143 GdiplusScope scope; | |
| 144 return GdiplusLoadPNGIcon(id, size); | |
| 145 } | |
| 146 | |
| 147 void GdiplusLoadButtonPNG(CIcon& icon, HWND btn_, UINT image, GdiplusBitmapTransform_t transform) { | |
| 148 CButton btn(btn_); | |
| 149 if (icon == NULL) { | |
| 150 CRect client; WIN32_OP_D(btn.GetClientRect(client)); | |
| 151 CSize size = client.Size(); | |
| 152 int v = MulDiv(pfc::min_t<int>(size.cx, size.cy), 3, 4); | |
| 153 if (v < 8) v = 8; | |
| 154 | |
| 155 GdiplusIconArg_t arg; | |
| 156 arg.size = CSize(v, v); | |
| 157 arg.transform = transform; | |
| 158 icon = GdiplusLoadIconEx(image, L"PNG", arg); | |
| 159 } | |
| 160 btn.SetIcon(icon); | |
| 161 } | |
| 162 | |
| 163 std::unique_ptr<Gdiplus::Bitmap> GdiplusLoadResource(UINT id, const TCHAR* resType) { | |
| 164 using namespace Gdiplus; | |
| 165 GdiplusErrorHandler EH; | |
| 166 | |
| 167 auto stream = WinLoadResourceAsStream(GetThisModuleHandle(), MAKEINTRESOURCE(id), resType); | |
| 168 | |
| 169 std::unique_ptr<Bitmap> img ( new Bitmap(stream) ); | |
| 170 EH << img->GetLastStatus(); | |
| 171 return img; | |
| 172 } | |
| 173 | |
| 174 std::unique_ptr<Gdiplus::Bitmap> GdiplusLoadResourceAsSize(UINT id, const TCHAR* resType, CSize size) { | |
| 175 auto source = GdiplusLoadResource(id, resType); | |
| 176 return GdiplusResizeImage(source.get(), size); | |
| 177 } | |
| 178 | |
| 179 void GdiplusDimImage(Gdiplus::Bitmap* bmp) { | |
| 180 using namespace Gdiplus; | |
| 181 GdiplusErrorHandler EH; | |
| 182 Gdiplus::Rect r(0, 0, bmp->GetWidth(), bmp->GetHeight()); | |
| 183 BitmapData data = {}; | |
| 184 EH << bmp->LockBits(&r, ImageLockModeRead | ImageLockModeWrite, PixelFormat32bppARGB, &data); | |
| 185 | |
| 186 BYTE* scan = (BYTE*)data.Scan0; | |
| 187 for (UINT y = 0; y < data.Height; ++y) { | |
| 188 BYTE* px = scan; | |
| 189 for (UINT x = 0; x < data.Width; ++x) { | |
| 190 //px[0] = _dimPixel(px[0]); | |
| 191 //px[1] = _dimPixel(px[1]); | |
| 192 //px[2] = _dimPixel(px[2]); | |
| 193 px[3] /= 3; | |
| 194 px += 4; | |
| 195 } | |
| 196 scan += data.Stride; | |
| 197 } | |
| 198 | |
| 199 EH << bmp->UnlockBits(&data); | |
| 200 } | |
| 201 | |
| 202 void GdiplusInvertImage(Gdiplus::Bitmap* bmp) { | |
| 203 using namespace Gdiplus; | |
| 204 GdiplusErrorHandler EH; | |
| 205 Gdiplus::Rect r(0, 0, bmp->GetWidth(), bmp->GetHeight()); | |
| 206 BitmapData data = {}; | |
| 207 EH << bmp->LockBits(&r, ImageLockModeRead | ImageLockModeWrite, PixelFormat32bppARGB, &data); | |
| 208 | |
| 209 BYTE* scan = (BYTE*)data.Scan0; | |
| 210 for (UINT y = 0; y < data.Height; ++y) { | |
| 211 BYTE* px = scan; | |
| 212 for (UINT x = 0; x < data.Width; ++x) { | |
| 213 unsigned v = (unsigned)px[0] + (unsigned)px[1] + (unsigned)px[2]; | |
| 214 v /= 3; | |
| 215 px[0] = px[1] = px[2] = (BYTE)(255 - v); | |
| 216 px += 4; | |
| 217 } | |
| 218 scan += data.Stride; | |
| 219 } | |
| 220 | |
| 221 EH << bmp->UnlockBits(&data); | |
| 222 } | |
| 223 | |
| 224 #pragma comment(lib, "gdiplus.lib") |
