Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

464 lines
12 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1997
  4. *
  5. * TITLE: Util.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 26 Dec, 1997
  12. *
  13. * DESCRIPTION:
  14. * Implementation of common utility functions.
  15. *
  16. *******************************************************************************/
  17. #include <objbase.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <tchar.h>
  21. #include "wia.h"
  22. #include "util.h"
  23. #include "wiadebug.h"
  24. /*******************************************************************************
  25. *
  26. * G O L B A L D A T A
  27. *
  28. *******************************************************************************/
  29. // extern HWND g_hWndListBox; // Optional debug listbox window handle.
  30. // extern HANDLE g_hfDebugLog; // Optional debug log file handle.
  31. // extern TCHAR g_szAppName[]; // Window caption.
  32. namespace Util
  33. {
  34. /*******************************************************************************
  35. *
  36. * SetBMI
  37. *
  38. * DESCRIPTION:
  39. * Setup bitmap info.
  40. *
  41. * PARAMETERS:
  42. *
  43. *******************************************************************************/
  44. void _stdcall SetBMI(
  45. PBITMAPINFO pbmi,
  46. LONG width,
  47. LONG height,
  48. LONG depth)
  49. {
  50. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  51. pbmi->bmiHeader.biWidth = width;
  52. pbmi->bmiHeader.biHeight = height;
  53. pbmi->bmiHeader.biPlanes = 1;
  54. pbmi->bmiHeader.biBitCount = (WORD) depth;
  55. pbmi->bmiHeader.biCompression = BI_RGB;
  56. pbmi->bmiHeader.biSizeImage = 0;
  57. pbmi->bmiHeader.biXPelsPerMeter = 0;
  58. pbmi->bmiHeader.biYPelsPerMeter = 0;
  59. pbmi->bmiHeader.biClrUsed = 0;
  60. pbmi->bmiHeader.biClrImportant = 0;
  61. }
  62. /*******************************************************************************
  63. *
  64. * AllocDibFileFromBits
  65. *
  66. * DESCRIPTION:
  67. * Given an unaligned bits buffer, allocate a buffer lager enough to hold the
  68. * DWORD aligned DIB file and fill it in.
  69. *
  70. * PARAMETERS:
  71. *
  72. *******************************************************************************/
  73. PBYTE _stdcall AllocDibFileFromBits(
  74. PBYTE pBits,
  75. UINT width,
  76. UINT height,
  77. UINT depth)
  78. {
  79. PBYTE pdib;
  80. UINT i, uiScanLineWidth, uiSrcScanLineWidth, cbDibSize;
  81. // Align scanline to ULONG boundary
  82. uiSrcScanLineWidth = (width * depth) / 8;
  83. uiScanLineWidth = (uiSrcScanLineWidth + 3) & 0xfffffffc;
  84. // Calculate DIB size and allocate memory for the DIB.
  85. cbDibSize = height * uiScanLineWidth;
  86. cbDibSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO);
  87. pdib = (PBYTE) LocalAlloc(0, cbDibSize);
  88. if (pdib) {
  89. PBITMAPFILEHEADER pbmfh = (PBITMAPFILEHEADER)pdib;
  90. PBITMAPINFO pbmi = (PBITMAPINFO)(pdib + sizeof(BITMAPFILEHEADER));
  91. PBYTE pb = (PBYTE)pbmi+ sizeof(BITMAPINFO);
  92. // Setup bitmap file header.
  93. pbmfh->bfType = 'MB';
  94. pbmfh->bfSize = cbDibSize;
  95. pbmfh->bfOffBits = static_cast<DWORD>(pb - pdib);
  96. // Setup bitmap info.
  97. SetBMI(pbmi,width, height, depth);
  98. WIA_TRACE(("AllocDibFileFromBits, uiScanLineWidth: %d, pdib: 0x%08X, pbmi: 0x%08X, pbits: 0x%08X", uiScanLineWidth, pdib, pbmi, pb));
  99. // Copy the bits.
  100. for (i = 0; i < height; i++) {
  101. memcpy(pb, pBits, uiSrcScanLineWidth);
  102. pb += uiScanLineWidth;
  103. pBits += uiScanLineWidth;
  104. }
  105. }
  106. else {
  107. WIA_ERROR(("AllocDibFileFromBits, LocalAlloc of %d bytes failed", cbDibSize));
  108. }
  109. return pdib;
  110. }
  111. /*******************************************************************************
  112. *
  113. * DIBBufferToBMP
  114. *
  115. * DESCRIPTION:
  116. * Make a BMP object from a DWORD aligned DIB file memory buffer
  117. *
  118. * PARAMETERS:
  119. *
  120. *******************************************************************************/
  121. HBITMAP _stdcall DIBBufferToBMP(HDC hDC, PBYTE pDib, BOOLEAN bFlip)
  122. {
  123. HBITMAP hBmp = NULL;
  124. PBITMAPINFO pbmi = (BITMAPINFO*)(pDib);
  125. PBYTE pBits = pDib + GetBmiSize(pbmi);
  126. if (bFlip) {
  127. pbmi->bmiHeader.biHeight = -pbmi->bmiHeader.biHeight;
  128. }
  129. hBmp = CreateDIBitmap(hDC, &pbmi->bmiHeader, CBM_INIT, pBits, pbmi, DIB_RGB_COLORS);
  130. if (!hBmp) {
  131. WIA_ERROR(("DIBBufferToBMP, CreateDIBitmap failed %d", GetLastError()));
  132. }
  133. return hBmp;
  134. }
  135. /*******************************************************************************
  136. *
  137. * ReadDIBFile
  138. *
  139. * DESCRIPTION:
  140. *
  141. * PARAMETERS:
  142. *
  143. *******************************************************************************/
  144. HRESULT _stdcall ReadDIBFile(LPTSTR pszFileName, PBYTE *ppDib)
  145. {
  146. HRESULT hr = S_FALSE;
  147. HANDLE hFile, hMap;
  148. PBYTE pFile, pBits;
  149. *ppDib = NULL;
  150. hFile = CreateFile(pszFileName,
  151. GENERIC_WRITE | GENERIC_READ,
  152. FILE_SHARE_WRITE,
  153. NULL,
  154. OPEN_EXISTING,
  155. FILE_ATTRIBUTE_NORMAL,
  156. NULL);
  157. if (hFile == INVALID_HANDLE_VALUE) {
  158. WIA_ERROR(("ReadDIBFile, unable to open %s", pszFileName));
  159. return hr;
  160. }
  161. hMap = CreateFileMapping(hFile,
  162. NULL,
  163. PAGE_READWRITE,
  164. 0,
  165. 0,
  166. NULL);
  167. if (!hMap) {
  168. WIA_ERROR(("ReadDIBFile, CreateFileMapping failed"));
  169. goto close_hfile_exit;
  170. }
  171. pFile = (PBYTE)MapViewOfFileEx(hMap,
  172. FILE_MAP_READ | FILE_MAP_WRITE,
  173. 0,
  174. 0,
  175. 0,
  176. NULL);
  177. if (pFile) {
  178. PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
  179. PBITMAPINFO pbmi = (PBITMAPINFO)(pFile + sizeof(BITMAPFILEHEADER));
  180. // validate bitmap
  181. if (pbmFile->bfType == 'MB') {
  182. // Calculate color table size.
  183. LONG bmiSize, ColorMapSize = 0;
  184. if (pbmi->bmiHeader.biBitCount == 1) {
  185. ColorMapSize = 2 - 1;
  186. } else if (pbmi->bmiHeader.biBitCount == 4) {
  187. ColorMapSize = 16 - 1;
  188. } else if (pbmi->bmiHeader.biBitCount == 8) {
  189. ColorMapSize = 256 - 1;
  190. }
  191. bmiSize = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * ColorMapSize;
  192. pBits = pFile + sizeof(BITMAPFILEHEADER) + bmiSize;
  193. *ppDib = AllocDibFileFromBits(pBits,
  194. pbmi->bmiHeader.biWidth,
  195. pbmi->bmiHeader.biHeight,
  196. pbmi->bmiHeader.biBitCount);
  197. if (*ppDib) {
  198. hr = S_OK;
  199. }
  200. }
  201. else {
  202. WIA_ERROR(("ReadDIBFile, %s is not a valid bitmap file", pszFileName));
  203. }
  204. }
  205. else {
  206. WIA_ERROR(("ReadDIBFile, MapViewOfFileEx failed"));
  207. goto close_hmap_exit;
  208. }
  209. UnmapViewOfFile(pFile);
  210. close_hmap_exit:
  211. CloseHandle(hMap);
  212. close_hfile_exit:
  213. CloseHandle(hFile);
  214. return hr;
  215. }
  216. /*******************************************************************************
  217. *
  218. * GetBmiSize
  219. *
  220. * DESCRIPTION:
  221. * Should never get biCompression == BI_RLE.
  222. *
  223. * PARAMETERS:
  224. *
  225. *******************************************************************************/
  226. LONG _stdcall GetBmiSize(PBITMAPINFO pbmi)
  227. {
  228. // determine the size of bitmapinfo
  229. LONG lSize = pbmi->bmiHeader.biSize;
  230. // no color table cases
  231. if (
  232. (pbmi->bmiHeader.biBitCount == 24) ||
  233. ((pbmi->bmiHeader.biBitCount == 32) &&
  234. (pbmi->bmiHeader.biCompression == BI_RGB))) {
  235. // no colors unless stated
  236. lSize += sizeof(RGBQUAD) * pbmi->bmiHeader.biClrUsed;
  237. return (lSize);
  238. }
  239. // bitfields cases
  240. if (((pbmi->bmiHeader.biBitCount == 32) &&
  241. (pbmi->bmiHeader.biCompression == BI_BITFIELDS)) ||
  242. (pbmi->bmiHeader.biBitCount == 16)) {
  243. lSize += 3 * sizeof(RGBQUAD);
  244. return (lSize);
  245. }
  246. // palette cases
  247. if (pbmi->bmiHeader.biBitCount == 1) {
  248. LONG lPal = pbmi->bmiHeader.biClrUsed;
  249. if ((lPal == 0) || (lPal > 2)) {
  250. lPal = 2;
  251. }
  252. lSize += lPal * sizeof(RGBQUAD);
  253. return (lSize);
  254. }
  255. // palette cases
  256. if (pbmi->bmiHeader.biBitCount == 4) {
  257. LONG lPal = pbmi->bmiHeader.biClrUsed;
  258. if ((lPal == 0) || (lPal > 16)) {
  259. lPal = 16;
  260. }
  261. lSize += lPal * sizeof(RGBQUAD);
  262. return (lSize);
  263. }
  264. // palette cases
  265. if (pbmi->bmiHeader.biBitCount == 8) {
  266. LONG lPal = pbmi->bmiHeader.biClrUsed;
  267. if ((lPal == 0) || (lPal > 256)) {
  268. lPal = 256;
  269. }
  270. lSize += lPal * sizeof(RGBQUAD);
  271. return (lSize);
  272. }
  273. // error
  274. return (0);
  275. }
  276. INT GetColorTableSize (UINT uBitCount, UINT uCompression)
  277. {
  278. INT nSize;
  279. switch(uBitCount)
  280. {
  281. case 32:
  282. if (uCompression != BI_BITFIELDS)
  283. {
  284. nSize = 0;
  285. break;
  286. }
  287. // fall through
  288. case 16:
  289. nSize = 3 * sizeof(DWORD);
  290. break;
  291. case 24:
  292. nSize = 0;
  293. break;
  294. default:
  295. nSize = ((UINT)1 << uBitCount) * sizeof(RGBQUAD);
  296. break;
  297. }
  298. return(nSize);
  299. }
  300. DWORD CalcBitsSize (UINT uWidth, UINT uHeight, UINT uBitCount, UINT uPlanes, int nAlign)
  301. {
  302. int nAWidth,nHeight,nABits;
  303. DWORD dwSize;
  304. nABits = (nAlign << 3);
  305. nAWidth = nABits-1;
  306. // Determine the size of the bitmap based on the (nAlign) size. Convert
  307. // this to size-in-bytes.
  308. //
  309. nHeight = uHeight * uPlanes;
  310. dwSize = (DWORD)(((uWidth * uBitCount) + nAWidth) / nABits) * nHeight;
  311. dwSize = dwSize * nAlign;
  312. return(dwSize);
  313. }
  314. //
  315. // Converts hBitmap to a DIB
  316. //
  317. HGLOBAL _stdcall BitmapToDIB (HDC hdc, HBITMAP hBitmap)
  318. {
  319. BITMAP bm;
  320. HANDLE hDib;
  321. PBYTE lpDib,lpBits;
  322. DWORD dwLength;
  323. DWORD dwBits;
  324. UINT uColorTable;
  325. INT iNeedMore;
  326. BOOL bDone;
  327. INT nBitCount;
  328. // Get the size of the bitmap. These values are used to setup the memory
  329. // requirements for the DIB.
  330. //
  331. if(GetObject(hBitmap,sizeof(BITMAP),reinterpret_cast<PVOID>(&bm)))
  332. {
  333. nBitCount = bm.bmBitsPixel * bm.bmPlanes;
  334. uColorTable = GetColorTableSize((UINT)nBitCount, BI_RGB);
  335. dwBits = CalcBitsSize(bm.bmWidth,bm.bmHeight,nBitCount,1,sizeof(DWORD));
  336. do
  337. {
  338. bDone = TRUE;
  339. dwLength = dwBits + sizeof(BITMAPINFOHEADER) + uColorTable;
  340. // Create the DIB. First, to the size of the bitmap.
  341. //
  342. if(hDib = GlobalAlloc(GHND,dwLength))
  343. {
  344. if(lpDib = reinterpret_cast<PBYTE>(GlobalLock(hDib)))
  345. {
  346. ((LPBITMAPINFOHEADER)lpDib)->biSize = sizeof(BITMAPINFOHEADER);
  347. ((LPBITMAPINFOHEADER)lpDib)->biWidth = (DWORD)bm.bmWidth;
  348. ((LPBITMAPINFOHEADER)lpDib)->biHeight = (DWORD)bm.bmHeight;
  349. ((LPBITMAPINFOHEADER)lpDib)->biPlanes = 1;
  350. ((LPBITMAPINFOHEADER)lpDib)->biBitCount = (WORD)nBitCount;
  351. ((LPBITMAPINFOHEADER)lpDib)->biCompression = 0;
  352. ((LPBITMAPINFOHEADER)lpDib)->biSizeImage = 0;
  353. ((LPBITMAPINFOHEADER)lpDib)->biXPelsPerMeter = 0;
  354. ((LPBITMAPINFOHEADER)lpDib)->biYPelsPerMeter = 0;
  355. ((LPBITMAPINFOHEADER)lpDib)->biClrUsed = 0;
  356. ((LPBITMAPINFOHEADER)lpDib)->biClrImportant = 0;
  357. // Get the size of the bitmap.
  358. // The biSizeImage contains the bytes
  359. // necessary to store the DIB.
  360. //
  361. GetDIBits(hdc,hBitmap,0,bm.bmHeight,NULL,(LPBITMAPINFO)lpDib,DIB_RGB_COLORS);
  362. iNeedMore = ((LPBITMAPINFOHEADER)lpDib)->biSizeImage - dwBits;
  363. if ( iNeedMore > 0 )
  364. {
  365. dwBits = dwBits + (((iNeedMore + 3) / 4)*4);
  366. bDone = FALSE;
  367. }
  368. else
  369. {
  370. lpBits = lpDib+sizeof(BITMAPINFOHEADER)+uColorTable;
  371. GetDIBits(hdc,hBitmap,0,bm.bmHeight,lpBits,(LPBITMAPINFO)lpDib,DIB_RGB_COLORS);
  372. GlobalUnlock(hDib);
  373. return(hDib);
  374. }
  375. GlobalUnlock(hDib);
  376. }
  377. GlobalFree(hDib);
  378. }
  379. }
  380. while (!bDone);
  381. }
  382. return(NULL);
  383. }
  384. }; // End Namespace Util