Leaked source code of windows server 2003
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.

570 lines
17 KiB

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