1
0

imageLoader.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include "./imageLoader.h"
  2. #include "./common.h"
  3. #include "../api.h"
  4. #include <api/service/waservicefactory.h>
  5. #include <shlwapi.h>
  6. template <class api_T>
  7. void ImageLoader_ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
  8. {
  9. if (WASABI_API_SVC)
  10. {
  11. waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);
  12. if (factory)
  13. api_t = (api_T *)factory->getInterface();
  14. }
  15. }
  16. typedef BOOL (CALLBACK *IMAGEDATAPROCESSOR)(const void * /*data*/, size_t /*dataSize*/, ULONG_PTR /*param*/);
  17. typedef struct __LOADDATAPARAM
  18. {
  19. BOOL premultiply;
  20. INT cx;
  21. INT cy;
  22. void *pixels;
  23. } LOADDATAPARAM;
  24. typedef struct __GETDIMENSIONPARAM
  25. {
  26. INT cx;
  27. INT cy;
  28. } GETDIMENSIONPARAM;
  29. static BOOL CALLBACK ImageLoader_LoadDataCallback(const void *data, size_t size, ULONG_PTR param)
  30. {
  31. LOADDATAPARAM *loadParam = (LOADDATAPARAM*)param;
  32. if (NULL == loadParam) return FALSE;
  33. if (NULL == WASABI_API_PNGLOADER)
  34. {
  35. ImageLoader_ServiceBuild(WASABI_API_PNGLOADER, pngLoaderGUID);
  36. if (NULL == WASABI_API_PNGLOADER)
  37. return FALSE;
  38. }
  39. loadParam->pixels = (FALSE == loadParam->premultiply) ?
  40. WASABI_API_PNGLOADER->loadImageData(data, (INT)size, &loadParam->cx, &loadParam->cy) :
  41. WASABI_API_PNGLOADER->loadImage(data, (INT)size, &loadParam->cx, &loadParam->cy);
  42. return (NULL != loadParam->pixels);
  43. }
  44. static BOOL CALLBACK ImageLoader_GetDimensionsCallback(const void *data, size_t size, ULONG_PTR param)
  45. {
  46. GETDIMENSIONPARAM *dimensionParam = (GETDIMENSIONPARAM*)param;
  47. if (NULL == dimensionParam) return FALSE;
  48. if (NULL == WASABI_API_PNGLOADER)
  49. {
  50. ImageLoader_ServiceBuild(WASABI_API_PNGLOADER, pngLoaderGUID);
  51. if (NULL == WASABI_API_PNGLOADER)
  52. return FALSE;
  53. }
  54. return WASABI_API_PNGLOADER->getDimensions(data, (INT)size, &dimensionParam->cx, &dimensionParam->cy);
  55. }
  56. static BOOL ImageLoader_ProcessResource(HINSTANCE hInstance, LPCWSTR pszName, LPCWSTR pszType, IMAGEDATAPROCESSOR processor, ULONG_PTR param)
  57. {
  58. HRSRC res = FindResourceW(hInstance, pszName, pszType);
  59. if (NULL == res) return FALSE;
  60. BOOL fSucceeded = FALSE;
  61. HANDLE handle = LoadResource(hInstance, res);
  62. if (NULL != handle)
  63. {
  64. UINT resourceSize = SizeofResource(hInstance, res);
  65. if (0 != resourceSize)
  66. {
  67. void *resourceData = LockResource(handle);
  68. if (NULL != resourceData)
  69. fSucceeded = processor(resourceData, resourceSize, param);
  70. }
  71. FreeResource(handle);
  72. }
  73. return fSucceeded;
  74. }
  75. static HRESULT ImageLoader_ParseResProtocol(LPWSTR pszAddress, LPCWSTR defaultType, HINSTANCE *module, LPCWSTR *resourceName, LPCWSTR *resourceType)
  76. {
  77. if (NULL == module || NULL == resourceName || NULL == resourceType)
  78. return E_POINTER;
  79. if (NULL == pszAddress || L'\0' == *pszAddress)
  80. return E_INVALIDARG;
  81. INT cchAddress = lstrlenW(pszAddress);
  82. const WCHAR szPrefix[] = L"res://";
  83. INT cchPrefix = ARRAYSIZE(szPrefix) - 1;
  84. if (cchAddress <= cchPrefix)
  85. return S_FALSE;
  86. if (CSTR_EQUAL != CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, pszAddress, cchPrefix, szPrefix, cchPrefix))
  87. return S_FALSE;
  88. pszAddress += cchPrefix;
  89. cchAddress -= cchPrefix;
  90. LPWSTR resType = NULL;
  91. LPWSTR resName = NULL;
  92. LPWSTR p = pszAddress + cchAddress;
  93. while (p != pszAddress && L'/' != *p) p--;
  94. if (p != pszAddress && p < (pszAddress + cchAddress))
  95. {
  96. resName = p + 1;
  97. *p = L'\0';
  98. p--;
  99. }
  100. if (NULL == resName || L'\0' == *resName)
  101. return E_FAIL;
  102. while (p != pszAddress && L'/' != *p) p--;
  103. if (p != pszAddress && p < resName)
  104. {
  105. resType = p + 1;
  106. if (L'\0' == *resType)
  107. {
  108. resType = NULL;
  109. }
  110. else
  111. {
  112. resType = p + 1;
  113. *p = L'\0';
  114. p--;
  115. }
  116. }
  117. HINSTANCE hModule;
  118. hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
  119. if (NULL == hModule)
  120. {
  121. UINT errorCode = GetLastError();
  122. if (NULL != resType)
  123. {
  124. *(resType - 1) = L'/';
  125. resType = NULL;
  126. hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
  127. if (NULL == hModule) errorCode = GetLastError();
  128. }
  129. if (ERROR_SUCCESS != errorCode)
  130. return HRESULT_FROM_WIN32(errorCode);
  131. }
  132. if (NULL == resType)
  133. resType = (LPWSTR)defaultType;
  134. if (NULL != resType && FALSE == IS_INTRESOURCE(resType) && L'#' == *resType)
  135. {
  136. INT typeId;
  137. if (FALSE != StrToIntExW(resType + 1, STIF_DEFAULT, &typeId))
  138. resType = MAKEINTRESOURCEW(typeId);
  139. }
  140. if (NULL != resName && FALSE == IS_INTRESOURCE(resName) && L'#' == *resName)
  141. {
  142. INT nameId;
  143. if (FALSE != StrToIntExW(resName + 1, STIF_DEFAULT, &nameId))
  144. resName = MAKEINTRESOURCEW(nameId);
  145. }
  146. *module = hModule;
  147. *resourceName = resName;
  148. *resourceType = resType;
  149. return S_OK;
  150. }
  151. static BOOL ImageLoader_ProcessFile(LPCWSTR pszPath, IMAGEDATAPROCESSOR processor, ULONG_PTR param)
  152. {
  153. HINSTANCE resModule;
  154. LPCWSTR resName, resType;
  155. BOOL fSucceeded = FALSE;
  156. LPWSTR name = LoginBox_CopyString(pszPath);
  157. HRESULT hr = ImageLoader_ParseResProtocol(name, RT_RCDATA, &resModule, &resName, &resType);
  158. if (S_OK == hr)
  159. {
  160. fSucceeded = ImageLoader_ProcessResource(resModule, resName, resType, processor, param);
  161. LoginBox_FreeString(name);
  162. return fSucceeded;
  163. }
  164. LoginBox_FreeString(name);
  165. if (FAILED(hr))
  166. return FALSE;
  167. HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  168. if (INVALID_HANDLE_VALUE == hFile)
  169. return FALSE;
  170. UINT resourceSize = GetFileSize(hFile, NULL);
  171. if (INVALID_FILE_SIZE != resourceSize)
  172. {
  173. void *resourceData = malloc(resourceSize);
  174. if (NULL != resourceData)
  175. {
  176. DWORD readed = 0;
  177. if (0 != ReadFile(hFile, resourceData, resourceSize, &readed, NULL) || resourceSize != readed)
  178. fSucceeded = processor(resourceData, resourceSize, param);
  179. free(resourceData);
  180. }
  181. }
  182. CloseHandle(hFile);
  183. return fSucceeded;
  184. }
  185. void *ImageLoader_LoadData(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, INT *widthOut, INT *heightOut)
  186. {
  187. BOOL fSucceeded;
  188. LOADDATAPARAM param;
  189. param.premultiply = fPremultiply;
  190. if (NULL == hInstance && !IS_INTRESOURCE(pszName))
  191. fSucceeded = ImageLoader_ProcessFile(pszName, ImageLoader_LoadDataCallback, (ULONG_PTR)&param);
  192. else
  193. fSucceeded = ImageLoader_ProcessResource(hInstance, pszName, RT_RCDATA, ImageLoader_LoadDataCallback, (ULONG_PTR)&param);
  194. if (FALSE == fSucceeded)
  195. {
  196. if (NULL != widthOut) *widthOut = 0;
  197. if (NULL != heightOut) *heightOut = 0;
  198. return NULL;
  199. }
  200. if (NULL != widthOut) *widthOut = param.cx;
  201. if (NULL != heightOut) *heightOut = param.cy;
  202. return param.pixels;
  203. }
  204. void ImageLoader_FreeData(void *data)
  205. {
  206. if (NULL == data)
  207. return;
  208. if (NULL == WASABI_API_MEMMNGR)
  209. {
  210. ImageLoader_ServiceBuild(WASABI_API_MEMMNGR, memMgrApiServiceGuid);
  211. if (NULL == WASABI_API_MEMMNGR) return;
  212. }
  213. WASABI_API_MEMMNGR->sysFree(data);
  214. }
  215. HBITMAP ImageLoader_LoadBitmapEx(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, BITMAPINFOHEADER *headerInfo, void **dataOut)
  216. {
  217. INT imageCX, imageCY;
  218. void *data = ImageLoader_LoadData(hInstance, pszName, fPremultiply, &imageCX, &imageCY);
  219. if (NULL == data) return NULL;
  220. ZeroMemory(headerInfo, sizeof(BITMAPINFOHEADER));
  221. headerInfo->biSize = sizeof(BITMAPINFOHEADER);
  222. headerInfo->biCompression = BI_RGB;
  223. headerInfo->biBitCount = 32;
  224. headerInfo->biPlanes = 1;
  225. headerInfo->biWidth = imageCX;
  226. headerInfo->biHeight = -imageCY;
  227. void *pixelData;
  228. HBITMAP bitmap = CreateDIBSection(NULL, (LPBITMAPINFO)headerInfo, DIB_RGB_COLORS, &pixelData, NULL, 0);
  229. if (NULL != bitmap)
  230. {
  231. if (NULL != dataOut) *dataOut = pixelData;
  232. CopyMemory(pixelData, data, headerInfo->biWidth * abs(headerInfo->biHeight) * sizeof(DWORD));
  233. }
  234. else
  235. {
  236. if (NULL != dataOut) *dataOut = NULL;
  237. }
  238. ImageLoader_FreeData(data);
  239. return bitmap;
  240. }
  241. HBITMAP ImageLoader_LoadBitmap(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, INT *widthOut, INT *heightOut)
  242. {
  243. BITMAPINFOHEADER header;
  244. HBITMAP bitmap = ImageLoader_LoadBitmapEx(hInstance, pszName, fPremultiply, &header, NULL);
  245. if (NULL != bitmap)
  246. {
  247. if (NULL != widthOut) *widthOut = header.biWidth;
  248. if (NULL != heightOut) *heightOut = header.biHeight;
  249. }
  250. else
  251. {
  252. if (NULL != widthOut) *widthOut = 0;
  253. if (NULL != heightOut) *heightOut = 0;
  254. }
  255. return bitmap;
  256. }
  257. BOOL ImageLoader_GetDimensions(HINSTANCE hInstance, LPCWSTR pszName, INT *widthOut, INT *heightOut)
  258. {
  259. BOOL fSucceeded;
  260. GETDIMENSIONPARAM param;
  261. if (NULL == hInstance && !IS_INTRESOURCE(pszName))
  262. fSucceeded = ImageLoader_ProcessFile(pszName, ImageLoader_GetDimensionsCallback, (ULONG_PTR)&param);
  263. else
  264. fSucceeded = ImageLoader_ProcessResource(hInstance, pszName, RT_RCDATA, ImageLoader_GetDimensionsCallback, (ULONG_PTR)&param);
  265. if (FALSE == fSucceeded)
  266. {
  267. if (NULL != widthOut) *widthOut = 0;
  268. if (NULL != heightOut) *heightOut = 0;
  269. return FALSE;
  270. }
  271. if (NULL != widthOut) *widthOut = param.cx;
  272. if (NULL != heightOut) *heightOut = param.cy;
  273. return TRUE;
  274. }