pngLoader.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. #include "main.h"
  2. #include "./pngLoader.h"
  3. #include "./browserObject.h"
  4. #include "./ifc_wasabihelper.h"
  5. #include <shlwapi.h>
  6. #include <strsafe.h>
  7. #ifndef LOAD_LIBRARY_AS_IMAGE_RESOURCE
  8. #define LOAD_LIBRARY_AS_IMAGE_RESOURCE 0x000000020
  9. #endif //LOAD_LIBRARY_AS_IMAGE_RESOURCE
  10. PngLoader::PngLoader(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply)
  11. : ref(1), instance(hInstance), name(NULL), flags(0)
  12. {
  13. name = Plugin_DuplicateResString(pszName);
  14. if (FALSE != fPremultiply)
  15. flags |= flagPremultiply;
  16. }
  17. PngLoader::~PngLoader()
  18. {
  19. Plugin_FreeResString(name);
  20. }
  21. HRESULT PngLoader::CreateInstance(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, ifc_omimageloader **imageLoader)
  22. {
  23. if (NULL == imageLoader) return E_POINTER;
  24. *imageLoader = NULL;
  25. if (NULL == pszName) return E_INVALIDARG;
  26. *imageLoader = new PngLoader(hInstance, pszName, fPremultiply);
  27. if (NULL == *imageLoader) return E_OUTOFMEMORY;
  28. return S_OK;
  29. }
  30. size_t PngLoader::AddRef()
  31. {
  32. return InterlockedIncrement((LONG*)&ref);
  33. }
  34. size_t PngLoader::Release()
  35. {
  36. if (0 == ref)
  37. return ref;
  38. LONG r = InterlockedDecrement((LONG*)&ref);
  39. if (0 == r)
  40. delete(this);
  41. return r;
  42. }
  43. int PngLoader::QueryInterface(GUID interface_guid, void **object)
  44. {
  45. return E_NOINTERFACE;
  46. }
  47. static HRESULT PngLoader_LoadResourceData(const void *data, unsigned int size, void **dataOut, int *cx, int *cy, BOOL fPremultiply)
  48. {
  49. if (NULL == data) return E_INVALIDARG;
  50. svc_imageLoader *loader = NULL;
  51. ifc_wasabihelper *wasabi = NULL;
  52. if (FAILED(Plugin_GetWasabiHelper(&wasabi))) return E_UNEXPECTED;
  53. HRESULT hr = wasabi->GetPngLoader(&loader);
  54. wasabi->Release();
  55. if (FAILED(hr)) return hr;
  56. *dataOut = (FALSE == fPremultiply) ?
  57. loader->loadImageData(data, size, cx, cy) :
  58. loader->loadImage(data, size, cx, cy);
  59. if (NULL == *dataOut)
  60. hr = E_OUTOFMEMORY;
  61. loader->Release();
  62. return hr;
  63. }
  64. static HRESULT PngLoader_LoadFromResource(HINSTANCE hInstance, LPCWSTR pszName, LPCWSTR pszType, void **dataOut, int *cx, int *cy, BOOL fPremultiply)
  65. {
  66. UINT errorCode = 0;
  67. HRSRC res = FindResourceW(hInstance, pszName, pszType);
  68. if (NULL == res)
  69. {
  70. errorCode = GetLastError();
  71. return HRESULT_FROM_WIN32(errorCode);
  72. }
  73. HRESULT hr;
  74. HANDLE handle = LoadResource(hInstance, res);
  75. if (NULL == handle)
  76. {
  77. errorCode = GetLastError();
  78. hr = HRESULT_FROM_WIN32(errorCode);
  79. }
  80. else
  81. {
  82. UINT resourceSize = SizeofResource(hInstance, res);
  83. if (0 == resourceSize)
  84. {
  85. errorCode = GetLastError();
  86. hr = HRESULT_FROM_WIN32(errorCode);
  87. }
  88. else
  89. {
  90. void *resourceData = LockResource(handle);
  91. if (NULL == resourceData)
  92. hr = E_OUTOFMEMORY;
  93. else
  94. hr = PngLoader_LoadResourceData(resourceData, resourceSize, dataOut, cx, cy, fPremultiply);
  95. }
  96. FreeResource(handle);
  97. }
  98. return hr;
  99. }
  100. static HRESULT PngLoader_ParseResProtocol(LPWSTR pszAddress, LPCWSTR defaultType, HINSTANCE *module, LPCWSTR *resourceName, LPCWSTR *resourceType)
  101. {
  102. if (NULL == module || NULL == resourceName || NULL == resourceType)
  103. return E_POINTER;
  104. if (NULL == pszAddress || L'\0' == *pszAddress)
  105. return E_INVALIDARG;
  106. INT cchAddress = lstrlenW(pszAddress);
  107. const WCHAR szPrefix[] = L"res://";
  108. INT cchPrefix = ARRAYSIZE(szPrefix) - 1;
  109. if (cchAddress <= cchPrefix)
  110. return S_FALSE;
  111. if (CSTR_EQUAL != CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, pszAddress, cchPrefix, szPrefix, cchPrefix))
  112. return S_FALSE;
  113. pszAddress += cchPrefix;
  114. cchAddress -= cchPrefix;
  115. LPWSTR resType = NULL;
  116. LPWSTR resName = NULL;
  117. LPWSTR p = pszAddress + cchAddress;
  118. while (p != pszAddress && L'/' != *p) p--;
  119. if (p != pszAddress && p < (pszAddress + cchAddress))
  120. {
  121. resName = p + 1;
  122. *p = L'\0';
  123. p--;
  124. }
  125. if (NULL == resName || L'\0' == *resName)
  126. return E_FAIL;
  127. while (p != pszAddress && L'/' != *p) p--;
  128. if (p != pszAddress && p < resName)
  129. {
  130. resType = p + 1;
  131. if (L'\0' == *resType)
  132. {
  133. resType = NULL;
  134. }
  135. else
  136. {
  137. resType = p + 1;
  138. *p = L'\0';
  139. p--;
  140. }
  141. }
  142. HINSTANCE hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
  143. if (NULL == hModule)
  144. {
  145. UINT errorCode = GetLastError();
  146. if (NULL != resType)
  147. {
  148. *(resType - 1) = L'/';
  149. resType = NULL;
  150. hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
  151. if (NULL == hModule) errorCode = GetLastError();
  152. }
  153. if (ERROR_SUCCESS != errorCode)
  154. return HRESULT_FROM_WIN32(errorCode);
  155. }
  156. if (NULL == resType)
  157. resType = (LPWSTR)defaultType;
  158. if (NULL != resType && FALSE == IS_INTRESOURCE(resType) && L'#' == *resType)
  159. {
  160. INT typeId = 0;
  161. if (FALSE != StrToIntExW(resType + 1, STIF_DEFAULT, &typeId))
  162. resType = MAKEINTRESOURCEW(typeId);
  163. }
  164. if (NULL != resName && FALSE == IS_INTRESOURCE(resName) && L'#' == *resName)
  165. {
  166. INT nameId;
  167. if (FALSE != StrToIntExW(resName + 1, STIF_DEFAULT, &nameId))
  168. resName = MAKEINTRESOURCEW(nameId);
  169. }
  170. *module = hModule;
  171. *resourceName = resName;
  172. *resourceType = resType;
  173. return S_OK;
  174. }
  175. static HRESULT PngLoader_LoadFromFile(LPWSTR pszPath, void **dataOut, int *cx, int *cy, BOOL fPremultiply)
  176. {
  177. HINSTANCE resModule = NULL;
  178. LPCWSTR resName = NULL, resType = NULL;
  179. HRESULT hr = PngLoader_ParseResProtocol(pszPath, RT_RCDATA, &resModule, &resName, &resType);
  180. if (S_OK == hr)
  181. return PngLoader_LoadFromResource(resModule, resName, resType, dataOut, cx, cy, fPremultiply);
  182. if (FAILED(hr))
  183. return hr;
  184. UINT errorCode = 0;
  185. HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  186. if (INVALID_HANDLE_VALUE == hFile)
  187. {
  188. errorCode = GetLastError();
  189. return HRESULT_FROM_WIN32(errorCode);
  190. }
  191. UINT resourceSize = GetFileSize(hFile, NULL);
  192. if (INVALID_FILE_SIZE == resourceSize)
  193. {
  194. errorCode = GetLastError();
  195. hr = HRESULT_FROM_WIN32(errorCode);
  196. }
  197. else
  198. {
  199. void *resourceData = malloc(resourceSize);
  200. if (NULL == resourceData)
  201. hr = E_OUTOFMEMORY;
  202. else
  203. {
  204. DWORD readed = 0;
  205. if (0 == ReadFile(hFile, resourceData, resourceSize, &readed, NULL) || resourceSize != readed)
  206. {
  207. errorCode = GetLastError();
  208. hr = HRESULT_FROM_WIN32(errorCode);
  209. }
  210. else
  211. {
  212. hr = PngLoader_LoadResourceData(resourceData, resourceSize, dataOut, cx, cy, fPremultiply);
  213. }
  214. free(resourceData);
  215. }
  216. }
  217. CloseHandle(hFile);
  218. return hr;
  219. }
  220. HRESULT PngLoader::LoadData(int *widthOut, int *heightOut, void** dataOut)
  221. {
  222. if (NULL == dataOut)
  223. return E_POINTER;
  224. *dataOut = NULL;
  225. return (NULL == instance && !IS_INTRESOURCE(name))?
  226. PngLoader_LoadFromFile(name, dataOut, widthOut, heightOut, (0 != (flagPremultiply & flags))) :
  227. PngLoader_LoadFromResource(instance, name, RT_RCDATA, dataOut, widthOut, heightOut, (0 != (flagPremultiply & flags)));
  228. }
  229. HRESULT PngLoader::FreeData(void *data)
  230. {
  231. if (NULL == data)
  232. return S_FALSE;
  233. ifc_wasabihelper *wasabi = NULL;
  234. HRESULT hr = Plugin_GetWasabiHelper(&wasabi);
  235. if (SUCCEEDED(hr) && wasabi != NULL)
  236. {
  237. api_memmgr *memoryManager = NULL;
  238. hr = wasabi->GetMemoryManager(&memoryManager);
  239. if (SUCCEEDED(hr) && memoryManager != NULL)
  240. {
  241. memoryManager->sysFree(data);
  242. memoryManager->Release();
  243. }
  244. wasabi->Release();
  245. }
  246. return hr;
  247. }
  248. HRESULT PngLoader::LoadBitmapEx(HBITMAP *bitmapOut, BITMAPINFOHEADER *headerInfo, void **dataOut)
  249. {
  250. INT imageCX, imageCY;
  251. if(NULL == bitmapOut) return E_POINTER;
  252. void *data = NULL;
  253. HRESULT hr = LoadData(&imageCX, &imageCY, &data);
  254. if (FAILED(hr)) return hr;
  255. ZeroMemory(headerInfo, sizeof(BITMAPINFOHEADER));
  256. headerInfo->biSize = sizeof(BITMAPINFOHEADER);
  257. headerInfo->biCompression = BI_RGB;
  258. headerInfo->biBitCount = 32;
  259. headerInfo->biPlanes = 1;
  260. headerInfo->biWidth = imageCX;
  261. headerInfo->biHeight = -imageCY;
  262. *bitmapOut = CreateDIBSection(NULL, (LPBITMAPINFO)headerInfo, DIB_RGB_COLORS, dataOut, NULL, 0);
  263. if (NULL != (*bitmapOut))
  264. {
  265. CopyMemory((*dataOut), data, headerInfo->biWidth * abs(headerInfo->biHeight) * sizeof(DWORD));
  266. }
  267. else
  268. {
  269. *dataOut = NULL;
  270. hr = E_FAIL;
  271. }
  272. FreeData(data);
  273. return hr;
  274. }
  275. HRESULT PngLoader::LoadBitmap(HBITMAP *bitmapOut, int *widthOut, int *heightOut)
  276. {
  277. BITMAPINFOHEADER header = {0};
  278. void *pixelData = NULL;
  279. if(NULL == bitmapOut) return E_POINTER;
  280. HRESULT hr = LoadBitmapEx(bitmapOut, &header, &pixelData);
  281. if (SUCCEEDED(hr))
  282. {
  283. if (NULL != widthOut) *widthOut = header.biWidth;
  284. if (NULL != heightOut) *heightOut = header.biHeight;
  285. }
  286. else
  287. {
  288. if (NULL != widthOut) *widthOut = 0;
  289. if (NULL != heightOut) *heightOut = 0;
  290. }
  291. return hr;
  292. }
  293. #define CBCLASS PngLoader
  294. START_DISPATCH;
  295. CB(ADDREF, AddRef);
  296. CB(RELEASE, Release);
  297. CB(QUERYINTERFACE, QueryInterface);
  298. CB(API_LOADDATA, LoadData);
  299. CB(API_FREEDATA, FreeData);
  300. CB(API_LOADBITMAP, LoadBitmap);
  301. CB(API_LOADBITMAPEX, LoadBitmapEx);
  302. END_DISPATCH;
  303. #undef CBCLASS