ReactOS 0.4.15-dev-7834-g00c4b3d
atlimagedx.h
Go to the documentation of this file.
1/*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Loading/Saving an image file with getting/setting resolution
5 * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#pragma once
9
10#include <atlimage.h>
11
12namespace GPDE = Gdiplus::DllExports;
13
15{
16protected:
18
19public:
21 {
22 _shared()->AddRef();
23 }
24
26 {
27 if (m_hBitmap)
29
30 _shared()->Release();
31 }
32
34 {
35 if (m_hBitmap)
37 m_hBitmap = hbm;
38 }
39
41 {
42 HBITMAP hbmOld = m_hBitmap;
44 return hbmOld;
45 }
46
47 BOOL GetResolution(Gdiplus::GpImage *pImage, float *pxDpi, float *pyDpi)
48 {
49 if (!get_fn(_shared()->m_GetImageHorizontalResolution, "GdipGetImageHorizontalResolution") ||
50 !get_fn(_shared()->m_GetImageVerticalResolution, "GdipGetImageVerticalResolution"))
51 {
52 return FALSE;
53 }
54
55 if (pxDpi)
57 if (pyDpi)
58 _shared()->m_GetImageVerticalResolution(pImage, pyDpi);
59
60 return TRUE;
61 }
62
63 BOOL SetResolution(Gdiplus::GpBitmap *pBitmap, float xDpi, float yDpi)
64 {
65 if (!get_fn(_shared()->m_BitmapSetResolution, "GdipBitmapSetResolution"))
66 return FALSE;
67
68 _shared()->m_BitmapSetResolution(pBitmap, xDpi, yDpi);
69 return TRUE;
70 }
71
72 HRESULT LoadDx(LPCWSTR pszFileName, float *pxDpi, float *pyDpi) throw()
73 {
74 using namespace Gdiplus;
75
76 _shared()->AddRef();
77
78 if (!get_fn(_shared()->m_CreateBitmapFromFile, "GdipCreateBitmapFromFile") ||
79 !get_fn(_shared()->m_CreateHBITMAPFromBitmap, "GdipCreateHBITMAPFromBitmap") ||
80 !get_fn(_shared()->m_DisposeImage, "GdipDisposeImage"))
81 {
82 _shared()->Release();
83 return E_FAIL;
84 }
85
86 // create a GpBitmap object from file
87 GpBitmap *pBitmap = NULL;
88 if (_shared()->m_CreateBitmapFromFile(pszFileName, &pBitmap) != Ok)
89 {
90 _shared()->Release();
91 return E_FAIL;
92 }
93
94 // get an HBITMAP
96 Color color(0xFF, 0xFF, 0xFF);
97 Status status = _shared()->m_CreateHBITMAPFromBitmap(pBitmap, &hbm, color.GetValue());
98
99 // get the resolution
100 if (pxDpi || pyDpi)
101 GetResolution((GpImage*)pBitmap, pxDpi, pyDpi);
102
103 // delete GpBitmap
104 _shared()->m_DisposeImage(pBitmap);
105
106 // attach it
107 if (status == Ok)
108 Attach(hbm);
109
110 _shared()->Release();
111 return (status == Ok ? S_OK : E_FAIL);
112 }
113
115 float xDpi = 0, float yDpi = 0) throw()
116 {
117 using namespace Gdiplus;
118
119 _shared()->AddRef();
120
121 if (!get_fn(_shared()->m_CreateBitmapFromHBITMAP, "GdipCreateBitmapFromHBITMAP") ||
122 !get_fn(_shared()->m_SaveImageToFile, "GdipSaveImageToFile") ||
123 !get_fn(_shared()->m_DisposeImage, "GdipDisposeImage"))
124 {
125 _shared()->Release();
126 return E_FAIL;
127 }
128
129 // create a GpBitmap from HBITMAP
130 GpBitmap *pBitmap = NULL;
132
133 // set the resolution
134 SetResolution(pBitmap, xDpi, yDpi);
135
136 // Get encoders
137 UINT cEncoders = 0;
138 ImageCodecInfo* pEncoders = GetAllEncoders(cEncoders);
139
140 // if the file type is null, get the file type from extension
141 CLSID clsid;
142 if (::IsEqualGUID(guidFileType, GUID_NULL))
143 {
145 clsid = FindCodecForExtension(strExt, pEncoders, cEncoders);
146 }
147 else
148 {
149 clsid = FindCodecForFileType(guidFileType, pEncoders, cEncoders);
150 }
151
152 delete[] pEncoders;
153
154 // save to file
156
157 // destroy GpBitmap
158 _shared()->m_DisposeImage(pBitmap);
159
160 _shared()->Release();
161
162 return (status == Ok ? S_OK : E_FAIL);
163 }
164
166 {
167 _shared()->AddRef();
168
169 UINT cEncoders;
170 Gdiplus::ImageCodecInfo* pEncoders = GetAllEncoders(cEncoders);
171
172 CLSID clsid = FindCodecForExtension(pchDotExt, pEncoders, cEncoders);
174 delete[] pEncoders;
175
176 _shared()->Release();
177 return ret;
178 }
179
180protected:
181 using FN_Startup = decltype(&Gdiplus::GdiplusStartup);
182 using FN_Shutdown = decltype(&Gdiplus::GdiplusShutdown);
183 using FN_GetImageHorizontalResolution = decltype(&GPDE::GdipGetImageHorizontalResolution);
184 using FN_GetImageVerticalResolution = decltype(&GPDE::GdipGetImageVerticalResolution);
185 using FN_BitmapSetResolution = decltype(&GPDE::GdipBitmapSetResolution);
186 using FN_CreateBitmapFromHBITMAP = decltype(&GPDE::GdipCreateBitmapFromHBITMAP);
187 using FN_CreateBitmapFromFile = decltype(&GPDE::GdipCreateBitmapFromFile);
188 using FN_CreateHBITMAPFromBitmap = decltype(&GPDE::GdipCreateHBITMAPFromBitmap);
189 using FN_SaveImageToFile = decltype(&GPDE::GdipSaveImageToFile);
190 using FN_DisposeImage = decltype(&GPDE::GdipDisposeImage);
191 using FN_GetImageEncodersSize = decltype(&GPDE::GdipGetImageEncodersSize);
192 using FN_GetImageEncoders = decltype(&GPDE::GdipGetImageEncoders);
193
194 struct SHARED
195 {
210
212 {
213 if (m_hGdiPlus)
214 return m_hGdiPlus;
215
216 m_hGdiPlus = ::LoadLibraryW(L"gdiplus.dll");
217 if (!m_hGdiPlus)
218 return NULL;
219
221 m_Shutdown = (FN_Shutdown)GetProcAddress(m_hGdiPlus, "GdiplusShutdown");
222 if (!Startup || !m_Shutdown)
223 {
226 return NULL;
227 }
228
229 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
230 Startup(&m_dwToken, &gdiplusStartupInput, NULL);
231
232 return m_hGdiPlus;
233 }
234
235 void Free()
236 {
238 ZeroMemory(this, sizeof(*this));
239 }
240
242 {
243 return ++m_cRefs;
244 }
245
247 {
248 if (--m_cRefs == 0)
249 {
250 Free();
251 return 0;
252 }
253 return m_cRefs;
254 }
255 };
256
257 static SHARED* _shared()
258 {
259 static SHARED s_shared;
260 return &s_shared;
261 }
262
263 static Gdiplus::ImageCodecInfo* GetAllEncoders(UINT& cEncoders)
264 {
265 Gdiplus::ImageCodecInfo *ret = NULL;
266 UINT total_size;
267
268 if (!get_fn(_shared()->m_GetImageEncodersSize, "GdipGetImageEncodersSize") ||
269 !get_fn(_shared()->m_GetImageEncoders, "GdipGetImageEncoders"))
270 {
271 cEncoders = 0;
272 return NULL;
273 }
274
275 _shared()->m_GetImageEncodersSize(&cEncoders, &total_size);
276 if (total_size == 0)
277 return NULL;
278
279 ret = new Gdiplus::ImageCodecInfo[total_size / sizeof(ret[0])];
280 if (ret == NULL)
281 {
282 cEncoders = 0;
283 return NULL;
284 }
285
286 _shared()->m_GetImageEncoders(cEncoders, total_size, ret);
287
288 return ret; // needs delete[]
289 }
290
291 template <typename FN_T>
292 static bool get_fn(FN_T& fn, const char *name)
293 {
294 if (fn)
295 return true;
296 HINSTANCE hGdiPlus = _shared()->Init();
297 fn = reinterpret_cast<FN_T>(::GetProcAddress(hGdiPlus, name));
298 return fn != NULL;
299 }
300
301 // CImage::FindCodecForExtension is private. We have to duplicate it at here...
302 static CLSID
303 FindCodecForExtension(LPCWSTR dotext, const Gdiplus::ImageCodecInfo *pCodecs, UINT nCodecs)
304 {
305 for (UINT i = 0; i < nCodecs; ++i)
306 {
307 CStringW strSpecs(pCodecs[i].FilenameExtension);
308 int ichOld = 0, ichSep;
309 for (;;)
310 {
311 ichSep = strSpecs.Find(L';', ichOld);
312
313 CStringW strSpec;
314 if (ichSep < 0)
315 strSpec = strSpecs.Mid(ichOld);
316 else
317 strSpec = strSpecs.Mid(ichOld, ichSep - ichOld);
318
319 int ichDot = strSpec.ReverseFind(L'.');
320 if (ichDot >= 0)
321 strSpec = strSpec.Mid(ichDot);
322
323 if (!dotext || strSpec.CompareNoCase(dotext) == 0)
324 return pCodecs[i].Clsid;
325
326 if (ichSep < 0)
327 break;
328
329 ichOld = ichSep + 1;
330 }
331 }
332 return CLSID_NULL;
333 }
334
335 // CImage::FindCodecForFileType is private. We have to duplicate it at here...
336 static CLSID
337 FindCodecForFileType(REFGUID guidFileType, const Gdiplus::ImageCodecInfo *pCodecs, UINT nCodecs)
338 {
339 for (UINT iInfo = 0; iInfo < nCodecs; ++iInfo)
340 {
341 if (::IsEqualGUID(pCodecs[iInfo].FormatID, guidFileType))
342 return pCodecs[iInfo].Clsid;
343 }
344 return CLSID_NULL;
345 }
346};
int CompareNoCase(_In_z_ PCXSTR psz) const
Definition: cstringt.h:743
int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart=0) const noexcept
Definition: cstringt.h:696
CStringT Mid(int iFirst, int nCount) const
Definition: cstringt.h:748
int ReverseFind(_In_ XCHAR ch) const noexcept
Definition: cstringt.h:730
decltype(&GPDE::GdipGetImageEncoders) FN_GetImageEncoders
Definition: atlimagedx.h:192
decltype(&GPDE::GdipGetImageHorizontalResolution) FN_GetImageHorizontalResolution
Definition: atlimagedx.h:183
HRESULT SaveDx(LPCWSTR pszFileName, REFGUID guidFileType=GUID_NULL, float xDpi=0, float yDpi=0)
Definition: atlimagedx.h:114
decltype(&GPDE::GdipGetImageVerticalResolution) FN_GetImageVerticalResolution
Definition: atlimagedx.h:184
decltype(&GPDE::GdipDisposeImage) FN_DisposeImage
Definition: atlimagedx.h:190
static BOOL IsExtensionSupported(PWCHAR pchDotExt)
Definition: atlimagedx.h:165
decltype(&GPDE::GdipGetImageEncodersSize) FN_GetImageEncodersSize
Definition: atlimagedx.h:191
CImageDx()
Definition: atlimagedx.h:20
HRESULT LoadDx(LPCWSTR pszFileName, float *pxDpi, float *pyDpi)
Definition: atlimagedx.h:72
HBITMAP m_hBitmap
Definition: atlimagedx.h:17
BOOL GetResolution(Gdiplus::GpImage *pImage, float *pxDpi, float *pyDpi)
Definition: atlimagedx.h:47
static Gdiplus::ImageCodecInfo * GetAllEncoders(UINT &cEncoders)
Definition: atlimagedx.h:263
BOOL SetResolution(Gdiplus::GpBitmap *pBitmap, float xDpi, float yDpi)
Definition: atlimagedx.h:63
decltype(&Gdiplus::GdiplusStartup) FN_Startup
Definition: atlimagedx.h:181
decltype(&Gdiplus::GdiplusShutdown) FN_Shutdown
Definition: atlimagedx.h:182
decltype(&GPDE::GdipBitmapSetResolution) FN_BitmapSetResolution
Definition: atlimagedx.h:185
static bool get_fn(FN_T &fn, const char *name)
Definition: atlimagedx.h:292
~CImageDx()
Definition: atlimagedx.h:25
decltype(&GPDE::GdipCreateHBITMAPFromBitmap) FN_CreateHBITMAPFromBitmap
Definition: atlimagedx.h:188
decltype(&GPDE::GdipCreateBitmapFromHBITMAP) FN_CreateBitmapFromHBITMAP
Definition: atlimagedx.h:186
static CLSID FindCodecForFileType(REFGUID guidFileType, const Gdiplus::ImageCodecInfo *pCodecs, UINT nCodecs)
Definition: atlimagedx.h:337
static CLSID FindCodecForExtension(LPCWSTR dotext, const Gdiplus::ImageCodecInfo *pCodecs, UINT nCodecs)
Definition: atlimagedx.h:303
static SHARED * _shared()
Definition: atlimagedx.h:257
decltype(&GPDE::GdipCreateBitmapFromFile) FN_CreateBitmapFromFile
Definition: atlimagedx.h:187
decltype(&GPDE::GdipSaveImageToFile) FN_SaveImageToFile
Definition: atlimagedx.h:189
HBITMAP Detach()
Definition: atlimagedx.h:40
void Attach(HBITMAP hbm)
Definition: atlimagedx.h:33
#define E_FAIL
Definition: ddrawi.h:102
static BYTE Startup[]
Definition: dem.c:1121
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
#define LoadLibraryW(x)
Definition: compat.h:747
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:447
unsigned int BOOL
Definition: ntddk_ex.h:94
pKey DeleteObject()
Status
Definition: gdiplustypes.h:25
@ Ok
Definition: gdiplustypes.h:26
GLuint color
Definition: glext.h:6243
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define S_OK
Definition: intsafe.h:52
#define GUID_NULL
Definition: ks.h:106
static HBITMAP
Definition: button.c:44
REFCLSID clsid
Definition: msctf.c:82
unsigned int UINT
Definition: ndis.h:50
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define CLSID_NULL
Definition: guiddef.h:99
FN_GetImageEncoders m_GetImageEncoders
Definition: atlimagedx.h:209
HINSTANCE m_hGdiPlus
Definition: atlimagedx.h:196
FN_DisposeImage m_DisposeImage
Definition: atlimagedx.h:207
FN_CreateBitmapFromHBITMAP m_CreateBitmapFromHBITMAP
Definition: atlimagedx.h:203
FN_CreateBitmapFromFile m_CreateBitmapFromFile
Definition: atlimagedx.h:204
FN_GetImageHorizontalResolution m_GetImageHorizontalResolution
Definition: atlimagedx.h:200
FN_BitmapSetResolution m_BitmapSetResolution
Definition: atlimagedx.h:202
FN_GetImageEncodersSize m_GetImageEncodersSize
Definition: atlimagedx.h:208
FN_Shutdown m_Shutdown
Definition: atlimagedx.h:199
HINSTANCE Init()
Definition: atlimagedx.h:211
FN_GetImageVerticalResolution m_GetImageVerticalResolution
Definition: atlimagedx.h:201
ULONG_PTR m_dwToken
Definition: atlimagedx.h:198
FN_CreateHBITMAPFromBitmap m_CreateHBITMAPFromBitmap
Definition: atlimagedx.h:205
FN_SaveImageToFile m_SaveImageToFile
Definition: atlimagedx.h:206
Definition: scsiwmi.h:51
Definition: name.c:39
Definition: ps.c:97
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint16_t * PWCHAR
Definition: typedefs.h:56
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:44
int ret
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
#define ZeroMemory
Definition: winbase.h:1712
_In_ BOOLEAN SetResolution
Definition: exfuncs.h:1078
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185