xref: /reactos/dll/win32/uxtheme/pngsup.cpp (revision b3194e32)
1 /*
2  * PROJECT:     ReactOS uxtheme.dll
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     Support for PNG images in visual styles
5  * COPYRIGHT:   Copyright 2023 Ethan Rodensky <splitwirez@gmail.com>
6  */
7 
8 #include "uxthemep.h"
9 
10 #include <ole2.h>
11 #include <objidl.h>
12 #include <gdiplus.h>
13 #include <gdipluscolor.h>
14 #include <winreg.h>
15 #include <shlwapi.h>
16 
17 BOOL
18 MSSTYLES_TryLoadPng(
19     _In_ HINSTANCE hTheme,
20     _In_ LPCWSTR szFile,
21     _In_ LPCWSTR type,
22     _Out_ HBITMAP *phBitmap)
23 {
24     BOOL ret = FALSE;
25 
26     HRSRC hRes = FindResourceW(hTheme, szFile, type);
27     if (!hRes)
28         return FALSE;
29 
30     HGLOBAL hAlloc = LoadResource(hTheme, hRes);
31     if (!hAlloc)
32         return FALSE;
33 
34     DWORD dwSize = SizeofResource(hTheme, hRes);
35     LPVOID pData = LockResource(hAlloc);
36     if ((!pData) || (dwSize <= 0))
37     {
38         FreeResource(hAlloc);
39         return FALSE;
40     }
41 
42     IStream* stream = SHCreateMemStream((BYTE*)pData, dwSize);
43     if (stream)
44     {
45         Gdiplus::Bitmap* gdipBitmap = Gdiplus::Bitmap::FromStream(stream, FALSE);
46         stream->Release();
47         if (gdipBitmap)
48         {
49             ret = gdipBitmap->GetHBITMAP(Gdiplus::Color(0, 0, 0, 0), phBitmap) == Gdiplus::Ok;
50             delete gdipBitmap;
51         }
52     }
53 
54     UnlockResource(pData);
55     FreeResource(hAlloc);
56     return ret;
57 }
58 
59 BOOL
60 prepare_png_alpha(
61     _In_ HBITMAP png,
62     _Out_ BOOL* hasAlpha)
63 {
64     DIBSECTION dib;
65     int n;
66     BYTE* p;
67 
68     *hasAlpha = FALSE;
69 
70     if (!png || GetObjectW( png, sizeof(dib), &dib ) != sizeof(dib))
71         return FALSE;
72 
73     if (dib.dsBm.bmBitsPixel != 32)
74         /* nothing to do */
75         return TRUE;
76 
77     p = (BYTE*)dib.dsBm.bmBits;
78     n = dib.dsBmih.biHeight * dib.dsBmih.biWidth;
79     while (n-- > 0)
80     {
81         int a = p[3] + 1;
82         if (a < 256)
83         {
84             p[0] = MulDiv(p[0], 256, a);
85             p[1] = MulDiv(p[1], 256, a);
86             p[2] = MulDiv(p[2], 256, a);
87 
88             *hasAlpha = TRUE;
89         }
90         p += 4;
91     }
92 
93     return TRUE;
94 }
95