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