Windows NT 4.0 source code leak
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.

581 lines
16 KiB

4 years ago
  1. /*
  2. *
  3. * iaverage.c Image averaging
  4. *
  5. * (C) Copyright Microsoft Corporation 1993. All rights reserved.
  6. *
  7. */
  8. #include <windows.h>
  9. #include <windowsx.h>
  10. #include <mmsystem.h>
  11. #include <win32.h>
  12. #include <memory.h>
  13. #include <stdlib.h>
  14. #include <ctype.h>
  15. #include <memory.h>
  16. #include <string.h>
  17. #include <msvideo.h>
  18. #include "ivideo32.h"
  19. #include "iaverage.h"
  20. #define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
  21. #define DIBWIDTHBYTES(bi) (int)WIDTHBYTES((int)(bi).biWidth * (int)(bi).biBitCount)
  22. #define RGB16(r,g,b) ((((WORD)(r) >> 3) << 10) | \
  23. (((WORD)(g) >> 3) << 5) | \
  24. (((WORD)(b) >> 3) ) )
  25. typedef BYTE HUGE * HPBYTE;
  26. typedef WORD HUGE * HPWORD;
  27. typedef DWORD HUGE * HPDWORD;
  28. #ifdef _WIN32
  29. typedef RGBQUAD FAR * LPRGBQUAD;
  30. #endif
  31. #ifdef _WIN32
  32. #define _fmemcpy memcpy
  33. #endif
  34. /* Description:
  35. A sequence of images are averaged together using 16 bit
  36. accumulators for each of the Red, Green, and Blue components.
  37. The final processing step is to divide the accumulated values
  38. by the number of frames averaged, and transfer the results back
  39. into the destination DIB.
  40. Certain death will result if the image format is changed between
  41. iaverageInit and iaverageFini calls.
  42. */
  43. //
  44. // table to map a 5bit index (0-31) to a 8 bit value (0-255)
  45. //
  46. static BYTE aw5to8[32] = {(BYTE)-1};
  47. /*
  48. * iaverageInit
  49. * Allocate memory for subsequent image averaging
  50. * Return FALSE on error
  51. *
  52. */
  53. BOOL iaverageInit (LPIAVERAGE FAR * lppia, LPBITMAPINFO lpbi, HPALETTE hPal)
  54. {
  55. DWORD dwSizeImage;
  56. LPIAVERAGE lpia;
  57. int i;
  58. *lppia = NULL;
  59. // Check for legal DIB formats
  60. if (lpbi->bmiHeader.biCompression != BI_RGB)
  61. return FALSE;
  62. if (lpbi->bmiHeader.biBitCount != 8 &&
  63. lpbi->bmiHeader.biBitCount != 16 &&
  64. lpbi->bmiHeader.biBitCount != 24 &&
  65. lpbi->bmiHeader.biBitCount != 32)
  66. return FALSE;
  67. //
  68. // init the 5bit to 8bit conversion table.
  69. //
  70. if (aw5to8[0] != 0)
  71. for (i=0; i<32; i++)
  72. aw5to8[i] = (BYTE)(i * 255 / 31);
  73. // Alloc memory for the image average structure
  74. lpia = (LPIAVERAGE) GlobalAllocPtr(GHND, sizeof (IAVERAGE));
  75. if (!lpia)
  76. return FALSE;
  77. // Save a copy of the header
  78. lpia->bi.bmiHeader = lpbi->bmiHeader;
  79. // and a copy of the color table and an inverse mapping table
  80. // if the image is 8 bit
  81. if (lpbi->bmiHeader.biBitCount == 8) {
  82. WORD r, g, b;
  83. LPBYTE lpB;
  84. hmemcpy (lpia->bi.bmiColors,
  85. lpbi->bmiColors,
  86. lpbi->bmiHeader.biClrUsed * sizeof (RGBQUAD));
  87. // Allocate and init the inverse LUT
  88. lpia->lpInverseMap= (LPBYTE) GlobalAllocPtr(GHND, 1024L * 32);
  89. lpB = lpia-> lpInverseMap;
  90. for (r = 0; r < 256; r += 8)
  91. for (g = 0; g < 256; g += 8)
  92. for (b = 0; b < 256; b += 8)
  93. *lpB++ = (BYTE) GetNearestPaletteIndex (hPal, RGB(r,g,b));
  94. }
  95. dwSizeImage = lpbi->bmiHeader.biSizeImage;
  96. lpia->lpRGB = (LPWORD) GlobalAllocPtr(GHND,
  97. dwSizeImage * sizeof (WORD) * 3);
  98. if (lpia->lpRGB == 0) {
  99. // Allocation failed, clean up
  100. iaverageFini (lpia);
  101. return FALSE;
  102. }
  103. *lppia = lpia;
  104. return TRUE;
  105. }
  106. /*
  107. * iaverageFini
  108. * Free memory used for image averaging
  109. * and the iaverage structure itself
  110. *
  111. */
  112. BOOL iaverageFini (LPIAVERAGE lpia)
  113. {
  114. if (lpia == NULL)
  115. return FALSE;
  116. if (lpia->lpInverseMap)
  117. GlobalFreePtr(lpia->lpInverseMap);
  118. if (lpia->lpRGB)
  119. GlobalFreePtr(lpia->lpRGB);
  120. GlobalFreePtr(lpia);
  121. return TRUE;
  122. }
  123. /*
  124. * iaverageZero
  125. * Zeros the accumulator
  126. *
  127. */
  128. BOOL iaverageZero (LPIAVERAGE lpia)
  129. {
  130. DWORD dwC;
  131. HPWORD hpW;
  132. if (lpia == NULL)
  133. return FALSE;
  134. hpW = (HPWORD) lpia->lpRGB;
  135. dwC = lpia->bi.bmiHeader.biSizeImage * 3;
  136. while (--dwC)
  137. *hpW++ = 0;
  138. lpia-> iCount = 0;
  139. return TRUE;
  140. }
  141. /*
  142. * iaverageSum
  143. * Add the current image into the accumulator
  144. * Image format must be 16 or 24 bit RGB
  145. */
  146. BOOL iaverageSum (LPIAVERAGE lpia, LPVOID lpBits)
  147. {
  148. HPWORD hpRGB;
  149. DWORD dwC;
  150. WORD wRGB16;
  151. HPWORD hpW;
  152. HPBYTE hpB;
  153. WORD w;
  154. if (lpia == NULL)
  155. return FALSE;
  156. hpRGB = (HPWORD) lpia->lpRGB;
  157. if (lpia->bi.bmiHeader.biBitCount == 8) {
  158. hpB = (HPBYTE) lpBits;
  159. for (dwC = lpia->bi.bmiHeader.biSizeImage; --dwC; ) {
  160. w = (WORD) *hpB++;
  161. *hpRGB++ += lpia->bi.bmiColors[w].rgbBlue;
  162. *hpRGB++ += lpia->bi.bmiColors[w].rgbGreen;
  163. *hpRGB++ += lpia->bi.bmiColors[w].rgbRed;
  164. }
  165. }
  166. else if (lpia->bi.bmiHeader.biBitCount == 16) {
  167. hpW = (HPWORD) lpBits;
  168. for (dwC = lpia->bi.bmiHeader.biSizeImage / 2; --dwC; ) {
  169. wRGB16 = *hpW++;
  170. *hpRGB++ += aw5to8 [wRGB16 & 0x1f]; // b
  171. *hpRGB++ += aw5to8 [(wRGB16 >> 5) & 0x1f]; // g
  172. *hpRGB++ += aw5to8 [(wRGB16 >> 10) & 0x1f]; // r
  173. }
  174. }
  175. else if (lpia->bi.bmiHeader.biBitCount == 24) {
  176. hpB = (HPBYTE) lpBits;
  177. for (dwC = lpia->bi.bmiHeader.biSizeImage; --dwC; ) {
  178. *hpRGB++ += *hpB++;
  179. }
  180. }
  181. else if (lpia->bi.bmiHeader.biBitCount == 32) {
  182. hpB = (HPBYTE) lpBits;
  183. for (dwC = lpia->bi.bmiHeader.biSizeImage / 4; --dwC; ) {
  184. *hpRGB++ += *hpB++; // b
  185. *hpRGB++ += *hpB++; // g
  186. *hpRGB++ += *hpB++; // r
  187. hpB++;
  188. }
  189. }
  190. lpia-> iCount++; // Image counter
  191. return TRUE;
  192. }
  193. /*
  194. * iaverageDivide
  195. * Divide by the number of images captured, and xfer back into the
  196. * destination DIB.
  197. *
  198. */
  199. BOOL iaverageDivide (LPIAVERAGE lpia, LPVOID lpBits)
  200. {
  201. HPWORD hpRGB;
  202. WORD r, g, b, w;
  203. DWORD dwC;
  204. HPWORD hpW;
  205. HPBYTE hpB;
  206. if (lpia == NULL || lpia-> iCount == 0)
  207. return FALSE;
  208. hpRGB = (HPWORD) lpia->lpRGB;
  209. if (lpia->bi.bmiHeader.biBitCount == 8) {
  210. hpB = (HPBYTE) lpBits;
  211. for (dwC = lpia->bi.bmiHeader.biSizeImage; --dwC; ) {
  212. b = *hpRGB++ / lpia-> iCount;
  213. g = *hpRGB++ / lpia-> iCount;
  214. r = *hpRGB++ / lpia-> iCount;
  215. w = RGB16(r,g,b) & 0x7FFF;
  216. *hpB++ = * (lpia->lpInverseMap + w);
  217. }
  218. }
  219. else if (lpia->bi.bmiHeader.biBitCount == 16) {
  220. hpW = (HPWORD) lpBits;
  221. for (dwC = lpia->bi.bmiHeader.biSizeImage / 2; --dwC; ) {
  222. b = *hpRGB++ / lpia-> iCount;
  223. g = *hpRGB++ / lpia-> iCount;
  224. r = *hpRGB++ / lpia-> iCount;
  225. *hpW++ = RGB16 (r, g, b);
  226. }
  227. }
  228. else if (lpia->bi.bmiHeader.biBitCount == 24) {
  229. hpB = (HPBYTE) lpBits;
  230. for (dwC = lpia->bi.bmiHeader.biSizeImage; --dwC; ) {
  231. *hpB++ = (BYTE) (*hpRGB++ / lpia-> iCount);
  232. }
  233. }
  234. else if (lpia->bi.bmiHeader.biBitCount == 32) {
  235. hpB = (HPBYTE) lpBits;
  236. for (dwC = lpia->bi.bmiHeader.biSizeImage / 4; --dwC; ) {
  237. *hpB++ = (BYTE) (*hpRGB++ / lpia-> iCount); // b
  238. *hpB++ = (BYTE) (*hpRGB++ / lpia-> iCount); // g
  239. *hpB++ = (BYTE) (*hpRGB++ / lpia-> iCount); // r
  240. hpB++;
  241. }
  242. }
  243. return TRUE;
  244. }
  245. // The following appropriated from Toddla's CDIB
  246. /*****************************************************************************
  247. *
  248. * SumRGB
  249. *
  250. *****************************************************************************/
  251. #define SumRGB16(b0,b1,b2,b3) (\
  252. ((((WORD)pal.palPalEntry[b0].peRed + \
  253. (WORD)pal.palPalEntry[b1].peRed + \
  254. (WORD)pal.palPalEntry[b2].peRed + \
  255. (WORD)pal.palPalEntry[b3].peRed) \
  256. & 0x03E) << 5) | \
  257. \
  258. ((((WORD)pal.palPalEntry[b0].peGreen + \
  259. (WORD)pal.palPalEntry[b1].peGreen + \
  260. (WORD)pal.palPalEntry[b2].peGreen + \
  261. (WORD)pal.palPalEntry[b3].peGreen) \
  262. & 0x003E)) | \
  263. \
  264. ((((WORD)pal.palPalEntry[b0].peBlue + \
  265. (WORD)pal.palPalEntry[b1].peBlue + \
  266. (WORD)pal.palPalEntry[b2].peBlue + \
  267. (WORD)pal.palPalEntry[b3].peBlue) \
  268. & 0x003E) >> 5) )
  269. /*****************************************************************************
  270. *
  271. * RGB16
  272. *
  273. *****************************************************************************/
  274. typedef struct { BYTE b,g,r; } RGB24;
  275. #define rgb16(r,g,b) (\
  276. ((UINT)(r) << 10) | \
  277. ((UINT)(g) << 5) | \
  278. ((UINT)(b) << 0) )
  279. #define RGB16R(rgb) aw5to8[((UINT)(rgb) >> 10) & 0x1F]
  280. #define RGB16G(rgb) aw5to8[((UINT)(rgb) >> 5) & 0x1F]
  281. #define RGB16B(rgb) aw5to8[((UINT)(rgb) >> 0) & 0x1F]
  282. #define RGB16r(rgb) ((BYTE)((UINT)(rgb) >> 10) & 0x1F)
  283. #define RGB16g(rgb) ((BYTE)((UINT)(rgb) >> 5) & 0x1F)
  284. #define RGB16b(rgb) ((BYTE)((UINT)(rgb) >> 0) & 0x1F)
  285. /*****************************************************************************
  286. *
  287. * Pel() used for 24bit Crunch
  288. *
  289. *****************************************************************************/
  290. #define Pel(p,x) (BYTE)(BitCount == 1 ? Pel1(p,x) : \
  291. BitCount == 4 ? Pel4(p,x) : Pel8(p,x))
  292. #define Pel1(p,x) (BYTE)bit(((HPBYTE)(p))[(x)/8],7-((x)%8))
  293. #define Pel4(p,x) (BYTE)((x & 1) ? (((HPBYTE)(p))[(x)/2] & 15) : (((HPBYTE)(p))[(x)/2] >> 4))
  294. #define Pel8(p,x) (BYTE)(((HPBYTE)(p))[(x)])
  295. #define Pel16(p,x) (((HPWORD)(p))[(x)])
  296. #define Pel24(p,x) (((RGB24 HUGE *)(p))[(x)])
  297. /*****************************************************************************
  298. *
  299. * CrunchDIB - shrink a DIB down by 2 with color averaging
  300. *
  301. * this routine works on 8, 16, 24, and 32 bpp DIBs
  302. *
  303. * this routine can't be used "in place"
  304. *
  305. *****************************************************************************/
  306. BOOL CrunchDIB(
  307. LPIAVERAGE lpia, // image averaging structure
  308. LPBITMAPINFOHEADER lpbiSrc, // BITMAPINFO of source
  309. LPVOID lpSrc, // input bits to crunch
  310. LPBITMAPINFOHEADER lpbiDst, // BITMAPINFO of dest
  311. LPVOID lpDst) // output bits to crunch
  312. {
  313. HPBYTE pbSrc;
  314. HPBYTE pbDst;
  315. HPBYTE pb;
  316. HPWORD pw;
  317. BYTE r,g,b,b0,b1,b2,b3;
  318. WORD w0,w1,w2,w3;
  319. RGB24 rgb0,rgb1,rgb2,rgb3;
  320. int WidthBytesSrc;
  321. int WidthBytesDst;
  322. UINT x;
  323. UINT y;
  324. UINT dx;
  325. UINT dy;
  326. int i;
  327. COLORREF rgb;
  328. int BitCount;
  329. UINT aw5to8[32];
  330. struct {
  331. WORD palVersion;
  332. WORD palNumEntries;
  333. PALETTEENTRY palPalEntry[256];
  334. } pal;
  335. if (lpbiSrc->biCompression != BI_RGB)
  336. return FALSE;
  337. BitCount = (int)lpbiSrc->biBitCount;
  338. if (BitCount == 16)
  339. for (i=0; i<32; i++)
  340. aw5to8[i] = (UINT)i * 255u / 31u;
  341. dx = (int)lpbiDst->biWidth;
  342. WidthBytesDst = (((UINT)lpbiDst->biBitCount * dx + 31)&~31) / 8;
  343. dy = (int)lpbiSrc->biHeight;
  344. dx = (int)lpbiSrc->biWidth;
  345. WidthBytesSrc = (((UINT)lpbiSrc->biBitCount * dx + 31)&~31) / 8;
  346. dx &= ~1;
  347. dy &= ~1;
  348. pbSrc = lpSrc;
  349. pbDst = lpDst;
  350. if (lpbiSrc->biClrUsed == 0 && lpbiSrc->biBitCount <= 8)
  351. lpbiSrc->biClrUsed = (1 << (int)lpbiSrc->biBitCount);
  352. pal.palVersion = 0x300;
  353. pal.palNumEntries = (int)lpbiSrc->biClrUsed;
  354. for (i=0; i<(int)pal.palNumEntries; i++)
  355. {
  356. pal.palPalEntry[i].peRed = ((LPRGBQUAD)(lpbiSrc+1))[i].rgbRed;
  357. pal.palPalEntry[i].peGreen = ((LPRGBQUAD)(lpbiSrc+1))[i].rgbGreen;
  358. pal.palPalEntry[i].peBlue = ((LPRGBQUAD)(lpbiSrc+1))[i].rgbBlue;
  359. pal.palPalEntry[i].peFlags = 0;
  360. }
  361. if (lpbiDst->biBitCount == 8)
  362. _fmemcpy(lpbiDst+1,lpbiSrc+1,(int)lpbiSrc->biClrUsed*sizeof(RGBQUAD));
  363. if ((int)lpbiDst->biBitCount == (int)lpbiSrc->biBitCount)
  364. {
  365. switch((int)lpbiSrc->biBitCount)
  366. {
  367. case 8:
  368. for (y=0; y<dy; y+=2)
  369. {
  370. pb = pbDst;
  371. for (x=0; x<dx; x+=2)
  372. {
  373. b0 = Pel8(pbSrc,x);
  374. b1 = Pel8(pbSrc+WidthBytesSrc, x);
  375. b2 = Pel8(pbSrc,x+1);
  376. b3 = Pel8(pbSrc+WidthBytesSrc,x+1);
  377. r = (BYTE) ((
  378. (WORD)pal.palPalEntry[b0].peRed +
  379. (WORD)pal.palPalEntry[b1].peRed +
  380. (WORD)pal.palPalEntry[b2].peRed +
  381. (WORD)pal.palPalEntry[b3].peRed) >> 2);
  382. g = (BYTE) ((
  383. (WORD)pal.palPalEntry[b0].peGreen +
  384. (WORD)pal.palPalEntry[b1].peGreen +
  385. (WORD)pal.palPalEntry[b2].peGreen +
  386. (WORD)pal.palPalEntry[b3].peGreen) >> 2);
  387. b = (BYTE) ((
  388. (WORD)pal.palPalEntry[b0].peBlue +
  389. (WORD)pal.palPalEntry[b1].peBlue +
  390. (WORD)pal.palPalEntry[b2].peBlue +
  391. (WORD)pal.palPalEntry[b3].peBlue) >> 2);
  392. *pb++ = (BYTE)(*(lpia->lpInverseMap +
  393. RGB16 (r, g, b)));
  394. }
  395. pbSrc += WidthBytesSrc*2;
  396. pbDst += WidthBytesDst;
  397. }
  398. break;
  399. case 16:
  400. for (y=0; y<dy; y+=2)
  401. {
  402. pw = (HPWORD)pbDst;
  403. for (x=0; x<dx; x += 2)
  404. {
  405. w0 = Pel16(pbSrc,x);
  406. w1 = Pel16(pbSrc,x+1);
  407. w2 = Pel16(pbSrc+WidthBytesSrc,x);
  408. w3 = Pel16(pbSrc+WidthBytesSrc,x+1);
  409. r = ((BYTE)RGB16r(w0) + RGB16r(w1) + RGB16r(w2) + RGB16r(w3)) >> 2;
  410. g = ((BYTE)RGB16g(w0) + RGB16g(w1) + RGB16g(w2) + RGB16g(w3)) >> 2;
  411. b = ((BYTE)RGB16b(w0) + RGB16b(w1) + RGB16b(w2) + RGB16b(w3)) >> 2;
  412. *pw++ = rgb16(r,g,b);
  413. }
  414. pbSrc += WidthBytesSrc*2;
  415. pbDst += WidthBytesDst;
  416. }
  417. break;
  418. case 24:
  419. for (y=0; y<dy; y+=2)
  420. {
  421. pb = pbDst;
  422. for (x=0; x<dx; x += 2)
  423. {
  424. rgb0 = Pel24(pbSrc,x);
  425. rgb1 = Pel24(pbSrc,x+1);
  426. rgb2 = Pel24(pbSrc+WidthBytesSrc,x);
  427. rgb3 = Pel24(pbSrc+WidthBytesSrc,x+1);
  428. rgb = RGB(
  429. ((UINT)rgb0.r + rgb1.r + rgb2.r + rgb3.r)/4,
  430. ((UINT)rgb0.g + rgb1.g + rgb2.g + rgb3.g)/4,
  431. ((UINT)rgb0.b + rgb1.b + rgb2.b + rgb3.b)/4);
  432. *pb++ = GetBValue(rgb);
  433. *pb++ = GetGValue(rgb);
  434. *pb++ = GetRValue(rgb);
  435. }
  436. pbSrc += WidthBytesSrc*2;
  437. pbDst += WidthBytesDst;
  438. }
  439. break;
  440. case 32:
  441. for (y=0; y<dy; y+=2)
  442. {
  443. pb = pbDst;
  444. for (x=0; x<dx; x += 2)
  445. {
  446. rgb0 = Pel24(pbSrc,x);
  447. rgb1 = Pel24(pbSrc,x+1);
  448. rgb2 = Pel24(pbSrc+WidthBytesSrc,x);
  449. rgb3 = Pel24(pbSrc+WidthBytesSrc,x+1);
  450. rgb = RGB(
  451. ((UINT)rgb0.r + rgb1.r + rgb2.r + rgb3.r)/4,
  452. ((UINT)rgb0.g + rgb1.g + rgb2.g + rgb3.g)/4,
  453. ((UINT)rgb0.b + rgb1.b + rgb2.b + rgb3.b)/4);
  454. *pb++ = GetBValue(rgb);
  455. *pb++ = GetGValue(rgb);
  456. *pb++ = GetRValue(rgb);
  457. pb++;
  458. }
  459. pbSrc += WidthBytesSrc*2;
  460. pbDst += WidthBytesDst;
  461. }
  462. break;
  463. default:
  464. return FALSE;
  465. }
  466. }
  467. else
  468. {
  469. return FALSE;
  470. }
  471. return TRUE;
  472. }