aboutsummaryrefslogtreecommitdiff
path: root/Src/auth/Loginbox/imageLoader.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/auth/Loginbox/imageLoader.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/auth/Loginbox/imageLoader.cpp')
-rw-r--r--Src/auth/Loginbox/imageLoader.cpp331
1 files changed, 331 insertions, 0 deletions
diff --git a/Src/auth/Loginbox/imageLoader.cpp b/Src/auth/Loginbox/imageLoader.cpp
new file mode 100644
index 00000000..f82128a3
--- /dev/null
+++ b/Src/auth/Loginbox/imageLoader.cpp
@@ -0,0 +1,331 @@
+#include "./imageLoader.h"
+#include "./common.h"
+#include "../api.h"
+
+#include <api/service/waservicefactory.h>
+
+#include <shlwapi.h>
+
+template <class api_T>
+void ImageLoader_ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
+{
+ if (WASABI_API_SVC)
+ {
+ waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);
+ if (factory)
+ api_t = (api_T *)factory->getInterface();
+ }
+}
+
+typedef BOOL (CALLBACK *IMAGEDATAPROCESSOR)(const void * /*data*/, size_t /*dataSize*/, ULONG_PTR /*param*/);
+
+
+typedef struct __LOADDATAPARAM
+{
+ BOOL premultiply;
+ INT cx;
+ INT cy;
+ void *pixels;
+} LOADDATAPARAM;
+
+typedef struct __GETDIMENSIONPARAM
+{
+ INT cx;
+ INT cy;
+} GETDIMENSIONPARAM;
+
+static BOOL CALLBACK ImageLoader_LoadDataCallback(const void *data, size_t size, ULONG_PTR param)
+{
+ LOADDATAPARAM *loadParam = (LOADDATAPARAM*)param;
+ if (NULL == loadParam) return FALSE;
+
+ if (NULL == WASABI_API_PNGLOADER)
+ {
+ ImageLoader_ServiceBuild(WASABI_API_PNGLOADER, pngLoaderGUID);
+ if (NULL == WASABI_API_PNGLOADER)
+ return FALSE;
+ }
+
+ loadParam->pixels = (FALSE == loadParam->premultiply) ?
+ WASABI_API_PNGLOADER->loadImageData(data, (INT)size, &loadParam->cx, &loadParam->cy) :
+ WASABI_API_PNGLOADER->loadImage(data, (INT)size, &loadParam->cx, &loadParam->cy);
+
+ return (NULL != loadParam->pixels);
+}
+
+static BOOL CALLBACK ImageLoader_GetDimensionsCallback(const void *data, size_t size, ULONG_PTR param)
+{
+ GETDIMENSIONPARAM *dimensionParam = (GETDIMENSIONPARAM*)param;
+ if (NULL == dimensionParam) return FALSE;
+
+ if (NULL == WASABI_API_PNGLOADER)
+ {
+ ImageLoader_ServiceBuild(WASABI_API_PNGLOADER, pngLoaderGUID);
+ if (NULL == WASABI_API_PNGLOADER)
+ return FALSE;
+ }
+
+ return WASABI_API_PNGLOADER->getDimensions(data, (INT)size, &dimensionParam->cx, &dimensionParam->cy);
+}
+
+static BOOL ImageLoader_ProcessResource(HINSTANCE hInstance, LPCWSTR pszName, LPCWSTR pszType, IMAGEDATAPROCESSOR processor, ULONG_PTR param)
+{
+ HRSRC res = FindResourceW(hInstance, pszName, pszType);
+ if (NULL == res) return FALSE;
+
+ BOOL fSucceeded = FALSE;
+ HANDLE handle = LoadResource(hInstance, res);
+ if (NULL != handle)
+ {
+ UINT resourceSize = SizeofResource(hInstance, res);
+ if (0 != resourceSize)
+ {
+ void *resourceData = LockResource(handle);
+ if (NULL != resourceData)
+ fSucceeded = processor(resourceData, resourceSize, param);
+ }
+ FreeResource(handle);
+ }
+ return fSucceeded;
+}
+
+static HRESULT ImageLoader_ParseResProtocol(LPWSTR pszAddress, LPCWSTR defaultType, HINSTANCE *module, LPCWSTR *resourceName, LPCWSTR *resourceType)
+{
+ if (NULL == module || NULL == resourceName || NULL == resourceType)
+ return E_POINTER;
+
+ if (NULL == pszAddress || L'\0' == *pszAddress)
+ return E_INVALIDARG;
+
+ INT cchAddress = lstrlenW(pszAddress);
+ const WCHAR szPrefix[] = L"res://";
+ INT cchPrefix = ARRAYSIZE(szPrefix) - 1;
+ if (cchAddress <= cchPrefix)
+ return S_FALSE;
+
+ if (CSTR_EQUAL != CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, pszAddress, cchPrefix, szPrefix, cchPrefix))
+ return S_FALSE;
+
+ pszAddress += cchPrefix;
+ cchAddress -= cchPrefix;
+
+ LPWSTR resType = NULL;
+ LPWSTR resName = NULL;
+
+ LPWSTR p = pszAddress + cchAddress;
+ while (p != pszAddress && L'/' != *p) p--;
+ if (p != pszAddress && p < (pszAddress + cchAddress))
+ {
+ resName = p + 1;
+ *p = L'\0';
+ p--;
+ }
+
+ if (NULL == resName || L'\0' == *resName)
+ return E_FAIL;
+
+
+ while (p != pszAddress && L'/' != *p) p--;
+ if (p != pszAddress && p < resName)
+ {
+ resType = p + 1;
+ if (L'\0' == *resType)
+ {
+ resType = NULL;
+ }
+ else
+ {
+ resType = p + 1;
+ *p = L'\0';
+ p--;
+ }
+ }
+
+ HINSTANCE hModule;
+ hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
+ if (NULL == hModule)
+ {
+ UINT errorCode = GetLastError();
+ if (NULL != resType)
+ {
+ *(resType - 1) = L'/';
+ resType = NULL;
+ hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
+ if (NULL == hModule) errorCode = GetLastError();
+ }
+
+ if (ERROR_SUCCESS != errorCode)
+ return HRESULT_FROM_WIN32(errorCode);
+ }
+
+ if (NULL == resType)
+ resType = (LPWSTR)defaultType;
+
+ if (NULL != resType && FALSE == IS_INTRESOURCE(resType) && L'#' == *resType)
+ {
+ INT typeId;
+ if (FALSE != StrToIntExW(resType + 1, STIF_DEFAULT, &typeId))
+ resType = MAKEINTRESOURCEW(typeId);
+ }
+
+ if (NULL != resName && FALSE == IS_INTRESOURCE(resName) && L'#' == *resName)
+ {
+ INT nameId;
+ if (FALSE != StrToIntExW(resName + 1, STIF_DEFAULT, &nameId))
+ resName = MAKEINTRESOURCEW(nameId);
+ }
+
+ *module = hModule;
+ *resourceName = resName;
+ *resourceType = resType;
+ return S_OK;
+}
+
+static BOOL ImageLoader_ProcessFile(LPCWSTR pszPath, IMAGEDATAPROCESSOR processor, ULONG_PTR param)
+{
+ HINSTANCE resModule;
+ LPCWSTR resName, resType;
+
+ BOOL fSucceeded = FALSE;
+
+ LPWSTR name = LoginBox_CopyString(pszPath);
+ HRESULT hr = ImageLoader_ParseResProtocol(name, RT_RCDATA, &resModule, &resName, &resType);
+ if (S_OK == hr)
+ {
+ fSucceeded = ImageLoader_ProcessResource(resModule, resName, resType, processor, param);
+ LoginBox_FreeString(name);
+ return fSucceeded;
+ }
+
+ LoginBox_FreeString(name);
+
+ if (FAILED(hr))
+ return FALSE;
+
+ HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+ if (INVALID_HANDLE_VALUE == hFile)
+ return FALSE;
+
+ UINT resourceSize = GetFileSize(hFile, NULL);
+ if (INVALID_FILE_SIZE != resourceSize)
+ {
+ void *resourceData = malloc(resourceSize);
+ if (NULL != resourceData)
+ {
+ DWORD readed = 0;
+ if (0 != ReadFile(hFile, resourceData, resourceSize, &readed, NULL) || resourceSize != readed)
+ fSucceeded = processor(resourceData, resourceSize, param);
+ free(resourceData);
+ }
+ }
+ CloseHandle(hFile);
+
+ return fSucceeded;
+}
+
+void *ImageLoader_LoadData(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, INT *widthOut, INT *heightOut)
+{
+ BOOL fSucceeded;
+ LOADDATAPARAM param;
+ param.premultiply = fPremultiply;
+ if (NULL == hInstance && !IS_INTRESOURCE(pszName))
+ fSucceeded = ImageLoader_ProcessFile(pszName, ImageLoader_LoadDataCallback, (ULONG_PTR)&param);
+ else
+ fSucceeded = ImageLoader_ProcessResource(hInstance, pszName, RT_RCDATA, ImageLoader_LoadDataCallback, (ULONG_PTR)&param);
+
+ if (FALSE == fSucceeded)
+ {
+ if (NULL != widthOut) *widthOut = 0;
+ if (NULL != heightOut) *heightOut = 0;
+ return NULL;
+ }
+
+ if (NULL != widthOut) *widthOut = param.cx;
+ if (NULL != heightOut) *heightOut = param.cy;
+
+ return param.pixels;
+}
+
+void ImageLoader_FreeData(void *data)
+{
+ if (NULL == data)
+ return;
+
+ if (NULL == WASABI_API_MEMMNGR)
+ {
+ ImageLoader_ServiceBuild(WASABI_API_MEMMNGR, memMgrApiServiceGuid);
+ if (NULL == WASABI_API_MEMMNGR) return;
+ }
+
+ WASABI_API_MEMMNGR->sysFree(data);
+}
+
+HBITMAP ImageLoader_LoadBitmapEx(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, BITMAPINFOHEADER *headerInfo, void **dataOut)
+{
+ INT imageCX, imageCY;
+
+ void *data = ImageLoader_LoadData(hInstance, pszName, fPremultiply, &imageCX, &imageCY);
+ if (NULL == data) return NULL;
+
+ ZeroMemory(headerInfo, sizeof(BITMAPINFOHEADER));
+ headerInfo->biSize = sizeof(BITMAPINFOHEADER);
+ headerInfo->biCompression = BI_RGB;
+ headerInfo->biBitCount = 32;
+ headerInfo->biPlanes = 1;
+ headerInfo->biWidth = imageCX;
+ headerInfo->biHeight = -imageCY;
+
+ void *pixelData;
+ HBITMAP bitmap = CreateDIBSection(NULL, (LPBITMAPINFO)headerInfo, DIB_RGB_COLORS, &pixelData, NULL, 0);
+ if (NULL != bitmap)
+ {
+ if (NULL != dataOut) *dataOut = pixelData;
+ CopyMemory(pixelData, data, headerInfo->biWidth * abs(headerInfo->biHeight) * sizeof(DWORD));
+ }
+ else
+ {
+ if (NULL != dataOut) *dataOut = NULL;
+ }
+
+ ImageLoader_FreeData(data);
+ return bitmap;
+}
+
+HBITMAP ImageLoader_LoadBitmap(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, INT *widthOut, INT *heightOut)
+{
+ BITMAPINFOHEADER header;
+ HBITMAP bitmap = ImageLoader_LoadBitmapEx(hInstance, pszName, fPremultiply, &header, NULL);
+ if (NULL != bitmap)
+ {
+ if (NULL != widthOut) *widthOut = header.biWidth;
+ if (NULL != heightOut) *heightOut = header.biHeight;
+ }
+ else
+ {
+ if (NULL != widthOut) *widthOut = 0;
+ if (NULL != heightOut) *heightOut = 0;
+ }
+ return bitmap;
+}
+
+BOOL ImageLoader_GetDimensions(HINSTANCE hInstance, LPCWSTR pszName, INT *widthOut, INT *heightOut)
+{
+ BOOL fSucceeded;
+ GETDIMENSIONPARAM param;
+ if (NULL == hInstance && !IS_INTRESOURCE(pszName))
+ fSucceeded = ImageLoader_ProcessFile(pszName, ImageLoader_GetDimensionsCallback, (ULONG_PTR)&param);
+ else
+ fSucceeded = ImageLoader_ProcessResource(hInstance, pszName, RT_RCDATA, ImageLoader_GetDimensionsCallback, (ULONG_PTR)&param);
+
+ if (FALSE == fSucceeded)
+ {
+ if (NULL != widthOut) *widthOut = 0;
+ if (NULL != heightOut) *heightOut = 0;
+ return FALSE;
+ }
+
+ if (NULL != widthOut) *widthOut = param.cx;
+ if (NULL != heightOut) *heightOut = param.cy;
+
+ return TRUE;
+} \ No newline at end of file