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