| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- #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)¶m);
- else
- fSucceeded = ImageLoader_ProcessResource(hInstance, pszName, RT_RCDATA, ImageLoader_LoadDataCallback, (ULONG_PTR)¶m);
- 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)¶m);
- else
- fSucceeded = ImageLoader_ProcessResource(hInstance, pszName, RT_RCDATA, ImageLoader_GetDimensionsCallback, (ULONG_PTR)¶m);
- 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;
- }
|