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.

656 lines
17 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: cldib.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. *
  7. * 09-26-95 ChrisWil Ported dib-scale code.
  8. \***************************************************************************/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. /*
  12. * Constants.
  13. */
  14. #define FX1 65536 // 1.0 in fixed point
  15. /*
  16. * Local Macros.
  17. */
  18. #define BPPTOINDEX(bpp) ((UINT)(bpp) >> 3)
  19. #define RGBQ(r,g,b) RGB(b, g, r)
  20. #define RGBQR(rgb) GetBValue(rgb)
  21. #define RGBQG(rgb) GetGValue(rgb)
  22. #define RGBQB(rgb) GetRValue(rgb)
  23. #define Pel4(p,x) (BYTE)(((x) & 1) ? (((LPBYTE)(p))[(x)/2] & 15) : (((LPBYTE)(p))[(x)/2] >> 4))
  24. #define Pel8(p,x) (BYTE)(((LPBYTE)(p))[(x)])
  25. #define Pel16(p,x) (((WORD UNALIGNED *)(p))[(x)])
  26. #define Pel24(p,x) (*(DWORD UNALIGNED *)((LPBYTE)(p) + (x) * 3))
  27. /*
  28. * Function Typedefs.
  29. */
  30. typedef VOID (*SCALEPROC)(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
  31. typedef VOID (*INITPROC)(LPBITMAPINFOHEADER);
  32. /*
  33. * Local Routines.
  34. */
  35. BOOL ScaleDIB(LPBITMAPINFOHEADER, LPVOID, LPBITMAPINFOHEADER, LPVOID);
  36. VOID InitDst8(LPBITMAPINFOHEADER);
  37. VOID Scale48(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
  38. VOID Scale88(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
  39. VOID Scale424(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
  40. VOID Scale824(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
  41. VOID Scale2424(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
  42. BYTE Map8(COLORREF);
  43. COLORREF MixRGBI(LPDWORD, BYTE, BYTE,BYTE, BYTE, int, int);
  44. COLORREF MixRGB(DWORD, DWORD, DWORD, DWORD, int, int);
  45. /*
  46. * Globals needed for color-mapping of resources.
  47. */
  48. SCALEPROC ScaleProc[4][4] = {
  49. NULL, Scale48, NULL, Scale424,
  50. NULL, Scale88, NULL, Scale824,
  51. NULL, NULL , NULL, NULL,
  52. NULL, NULL , NULL, Scale2424
  53. };
  54. INITPROC InitDst[] = {
  55. NULL, InitDst8, NULL, NULL
  56. };
  57. BYTE rmap[256], gmap[256], bmap[256];
  58. /***************************************************************************\
  59. * SmartStretchDIBits
  60. *
  61. * calls GDI StretchDIBits, unless the stretch is 2:1 and the source
  62. * is 4bpp, then is does it itself in a nice way.
  63. *
  64. * this optimization should just be put into GDI.
  65. *
  66. * can we change the passed bits? I assume we cant, could avoid a alloc
  67. * if so.
  68. *
  69. \***************************************************************************/
  70. int SmartStretchDIBits(
  71. HDC hdc,
  72. int xD,
  73. int yD,
  74. int dxD,
  75. int dyD,
  76. int xS,
  77. int yS,
  78. int dxS,
  79. int dyS,
  80. LPVOID lpBits,
  81. LPBITMAPINFO lpbi,
  82. UINT wUsage,
  83. DWORD rop)
  84. {
  85. LPBYTE lpBitsNew;
  86. UINT bpp;
  87. RGBQUAD rgb;
  88. LPBITMAPINFOHEADER lpbiNew = NULL;
  89. int i;
  90. /*
  91. * thunk to USER32
  92. */
  93. UserAssert(rop == SRCCOPY);
  94. UserAssert(wUsage == DIB_RGB_COLORS);
  95. UserAssert(xS == 0 && yS == 0);
  96. if ((GetDIBColorTable(hdc, 0, 1, &rgb) != 1) &&
  97. (dxD != dxS || dyD != dyS) && // 1:1 stretch just call GDI
  98. (dxD >= dxS/2) && (dyD >= dyS/2) && // less than 1:2 shrink call GDI
  99. (lpbi->bmiHeader.biCompression == 0) && // must be un-compressed
  100. (lpbi->bmiHeader.biBitCount == 4 || // input must be 4,8,24
  101. lpbi->bmiHeader.biBitCount == 8 ||
  102. lpbi->bmiHeader.biBitCount == 24)) {
  103. bpp = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
  104. bpp = (bpp > 8 ? 24 : 8);
  105. lpbiNew = (LPBITMAPINFOHEADER)UserLocalAlloc(0,
  106. sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)) +
  107. (UINT)((((dxD * bpp) / 8) + 3) & ~3) * (UINT)dyD);
  108. if (lpbiNew) {
  109. *lpbiNew = lpbi->bmiHeader;
  110. lpbiNew->biWidth = dxD;
  111. lpbiNew->biHeight = dyD;
  112. lpbiNew->biBitCount = (WORD)bpp;
  113. lpBitsNew = (LPBYTE)lpbiNew +
  114. sizeof(BITMAPINFOHEADER) +
  115. (256 * sizeof(RGBQUAD));
  116. if (ScaleDIB((LPBITMAPINFOHEADER)lpbi,
  117. (LPVOID)lpBits,
  118. lpbiNew,
  119. lpBitsNew)) {
  120. lpbi = (LPBITMAPINFO)lpbiNew;
  121. lpBits = lpBitsNew;
  122. dxS = dxD;
  123. dyS = dyD;
  124. }
  125. }
  126. }
  127. i = StretchDIBits(hdc,
  128. xD,
  129. yD,
  130. dxD,
  131. dyD,
  132. xS,
  133. yS,
  134. dxS,
  135. dyS,
  136. lpBits,
  137. lpbi,
  138. wUsage,
  139. rop);
  140. if (lpbiNew)
  141. UserLocalFree(lpbiNew);
  142. return i;
  143. }
  144. /***************************************************************************\
  145. * ScaleDIB
  146. *
  147. * Parameters
  148. * ----------
  149. * lpbiSrc - BITMAPINFO of source.
  150. * lpSrc - Input bits to crunch.
  151. * lpbiDst - BITMAPINFO of destination.
  152. * lpDst - Output bits to crunch.
  153. *
  154. *
  155. \***************************************************************************/
  156. BOOL ScaleDIB(
  157. LPBITMAPINFOHEADER lpbiSrc,
  158. LPVOID lpSrc,
  159. LPBITMAPINFOHEADER lpbiDst,
  160. LPVOID lpDst)
  161. {
  162. LPBYTE pbSrc;
  163. LPBYTE pbDst;
  164. LPDWORD pal;
  165. int dxSrc;
  166. int dySrc;
  167. int dxDst;
  168. int dyDst;
  169. int iSrc;
  170. int iDst;
  171. int x0;
  172. int y0;
  173. int sdx;
  174. int sdy;
  175. LONG WidthBytesSrc;
  176. LONG WidthBytesDst;
  177. if ((lpbiSrc->biCompression != BI_RGB) ||
  178. (lpbiDst->biCompression != BI_RGB)) {
  179. return FALSE;
  180. }
  181. iSrc = BPPTOINDEX(lpbiSrc->biBitCount);
  182. iDst = BPPTOINDEX(lpbiDst->biBitCount);
  183. if (ScaleProc[iSrc][iDst] == NULL)
  184. return FALSE;
  185. dxSrc = (int)lpbiSrc->biWidth;
  186. dySrc = (int)lpbiSrc->biHeight;
  187. dxDst = (int)lpbiDst->biWidth;
  188. dyDst = (int)lpbiDst->biHeight;
  189. WidthBytesDst = BitmapWidth(lpbiDst->biWidth, lpbiDst->biBitCount);
  190. WidthBytesSrc = BitmapWidth(lpbiSrc->biWidth, lpbiSrc->biBitCount);
  191. lpbiDst->biSizeImage = (WidthBytesDst * dyDst);
  192. pbSrc = (LPBYTE)lpSrc;
  193. pbDst = (LPBYTE)lpDst;
  194. pal = (LPDWORD)(lpbiSrc + 1);
  195. if (InitDst[iDst])
  196. InitDst[iDst](lpbiDst);
  197. if ((dxSrc == (dxDst * 2)) && (dySrc == (dyDst * 2))) {
  198. sdx = FX1 * 2;
  199. sdy = FX1 * 2;
  200. y0 = FX1 / 2;
  201. x0 = FX1 / 2;
  202. } else {
  203. sdx = (dxSrc - 1) * FX1 / (dxDst - 1);
  204. sdy = (dySrc - 1) * FX1 / (dyDst - 1);
  205. y0 = 0;
  206. x0 = 0;
  207. }
  208. /*
  209. * Make sure we don't croak on a bad bitmap since this can hose winlogon
  210. * if it's the desktop wallpaper.
  211. */
  212. try {
  213. ScaleProc[iSrc][iDst](pal,
  214. pbSrc,
  215. WidthBytesSrc,
  216. x0,
  217. y0,
  218. sdx,
  219. sdy,
  220. pbDst,
  221. WidthBytesDst,
  222. dxDst,
  223. dyDst);
  224. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  225. return FALSE;
  226. }
  227. return TRUE;
  228. }
  229. /***************************************************************************\
  230. * Scale48
  231. *
  232. *
  233. \***************************************************************************/
  234. VOID Scale48(
  235. LPDWORD pal,
  236. LPBYTE pbSrc,
  237. LONG WidthBytesSrc,
  238. int x0,
  239. int y0,
  240. int sdx,
  241. int sdy,
  242. LPBYTE pbDst,
  243. LONG WidthBytesDst,
  244. int dxDst,
  245. int dyDst)
  246. {
  247. BYTE b0;
  248. BYTE b1;
  249. BYTE b2;
  250. BYTE b3;
  251. LPBYTE pb;
  252. int x;
  253. int y;
  254. UINT sx;
  255. UINT sy;
  256. for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
  257. pb = pbSrc + (WidthBytesSrc * (sy / FX1));
  258. for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
  259. b0 = Pel4(pb, (sx / FX1));
  260. b1 = Pel4(pb, (sx / FX1) + 1);
  261. b2 = Pel4(pb + WidthBytesSrc, (sx / FX1));
  262. b3 = Pel4(pb + WidthBytesSrc, (sx / FX1) + 1);
  263. pbDst[x] = Map8(MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1));
  264. }
  265. pbDst += WidthBytesDst;
  266. }
  267. }
  268. /***************************************************************************\
  269. * Scale88
  270. *
  271. *
  272. \***************************************************************************/
  273. VOID Scale88(
  274. LPDWORD pal,
  275. LPBYTE pbSrc,
  276. LONG WidthBytesSrc,
  277. int x0,
  278. int y0,
  279. int sdx,
  280. int sdy,
  281. LPBYTE pbDst,
  282. LONG WidthBytesDst,
  283. int dxDst,
  284. int dyDst)
  285. {
  286. BYTE b0;
  287. BYTE b1;
  288. BYTE b2;
  289. BYTE b3;
  290. LPBYTE pb;
  291. int x;
  292. int y;
  293. UINT sx;
  294. UINT sy;
  295. for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
  296. pb = pbSrc + (WidthBytesSrc * (sy / FX1));
  297. for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
  298. b0 = Pel8(pb, (sx / FX1));
  299. b1 = Pel8(pb, (sx / FX1) + 1);
  300. b2 = Pel8(pb + WidthBytesSrc, (sx / FX1));
  301. b3 = Pel8(pb + WidthBytesSrc, (sx / FX1) + 1);
  302. pbDst[x] = Map8(MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1));
  303. }
  304. pbDst += WidthBytesDst;
  305. }
  306. }
  307. /***************************************************************************\
  308. * Scale424
  309. *
  310. *
  311. \***************************************************************************/
  312. VOID Scale424(
  313. LPDWORD pal,
  314. LPBYTE pbSrc,
  315. LONG WidthBytesSrc,
  316. int x0,
  317. int y0,
  318. int sdx,
  319. int sdy,
  320. LPBYTE pbDst,
  321. LONG WidthBytesDst,
  322. int dxDst,
  323. int dyDst)
  324. {
  325. BYTE b0;
  326. BYTE b1;
  327. BYTE b2;
  328. BYTE b3;
  329. LPBYTE pb;
  330. int x;
  331. int y;
  332. UINT sx;
  333. UINT sy;
  334. COLORREF rgb;
  335. for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
  336. pb = pbSrc + (WidthBytesSrc * (sy / FX1));
  337. for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
  338. b0 = Pel4(pb, (sx / FX1));
  339. b1 = Pel4(pb, (sx / FX1) + 1);
  340. b2 = Pel4(pb + WidthBytesSrc, (sx / FX1));
  341. b3 = Pel4(pb + WidthBytesSrc, (sx / FX1) + 1);
  342. rgb = MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1);
  343. *pbDst++ = GetBValue(rgb);
  344. *pbDst++ = GetGValue(rgb);
  345. *pbDst++ = GetRValue(rgb);
  346. }
  347. pbDst += (WidthBytesDst - (dxDst * 3));
  348. }
  349. }
  350. /***************************************************************************\
  351. * Scale824
  352. *
  353. *
  354. \***************************************************************************/
  355. VOID Scale824(
  356. LPDWORD pal,
  357. LPBYTE pbSrc,
  358. LONG WidthBytesSrc,
  359. int x0,
  360. int y0,
  361. int sdx,
  362. int sdy,
  363. LPBYTE pbDst,
  364. LONG WidthBytesDst,
  365. int dxDst,
  366. int dyDst)
  367. {
  368. BYTE b0;
  369. BYTE b1;
  370. BYTE b2;
  371. BYTE b3;
  372. LPBYTE pb;
  373. int x;
  374. int y;
  375. UINT sx;
  376. UINT sy;
  377. COLORREF rgb;
  378. for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
  379. pb = pbSrc + (WidthBytesSrc * (sy / FX1));
  380. for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
  381. b0 = Pel8(pb, (sx / FX1));
  382. b1 = Pel8(pb, (sx / FX1) + 1);
  383. b2 = Pel8(pb + WidthBytesSrc, (sx / FX1));
  384. b3 = Pel8(pb + WidthBytesSrc, (sx / FX1) + 1);
  385. rgb = MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1);
  386. *pbDst++ = GetBValue(rgb);
  387. *pbDst++ = GetGValue(rgb);
  388. *pbDst++ = GetRValue(rgb);
  389. }
  390. pbDst += (WidthBytesDst - (dxDst * 3));
  391. }
  392. }
  393. /***************************************************************************\
  394. * Scale2424
  395. *
  396. *
  397. \***************************************************************************/
  398. VOID Scale2424(
  399. LPDWORD pal,
  400. LPBYTE pbSrc,
  401. LONG WidthBytesSrc,
  402. int x0,
  403. int y0,
  404. int sdx,
  405. int sdy,
  406. LPBYTE pbDst,
  407. LONG WidthBytesDst,
  408. int dxDst,
  409. int dyDst)
  410. {
  411. DWORD bgr0;
  412. DWORD bgr1;
  413. DWORD bgr2;
  414. DWORD bgr3;
  415. LPBYTE pb;
  416. int x;
  417. int y;
  418. UINT sx;
  419. UINT sy;
  420. COLORREF rgb;
  421. UNREFERENCED_PARAMETER(pal);
  422. for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
  423. pb = pbSrc + (WidthBytesSrc * (sy / FX1));
  424. for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
  425. bgr0 = Pel24(pb, (sx / FX1));
  426. bgr1 = Pel24(pb, (sx / FX1) + 1);
  427. bgr2 = Pel24(pb + WidthBytesSrc, (sx / FX1));
  428. bgr3 = Pel24(pb + WidthBytesSrc, (sx / FX1) + 1);
  429. rgb = MixRGB(bgr0, bgr1, bgr2, bgr3, sx % FX1, sy % FX1);
  430. *pbDst++ = GetBValue(rgb);
  431. *pbDst++ = GetGValue(rgb);
  432. *pbDst++ = GetRValue(rgb);
  433. }
  434. pbDst += (WidthBytesDst - (dxDst * 3));
  435. }
  436. }
  437. /***************************************************************************\
  438. * MixRGB
  439. *
  440. * r0 x r1
  441. * y *
  442. * r2 r3
  443. *
  444. * Note: inputs are RGBQUADs, output is a COLORREF.
  445. *
  446. \***************************************************************************/
  447. COLORREF MixRGB(
  448. DWORD r0,
  449. DWORD r1,
  450. DWORD r2,
  451. DWORD r3,
  452. int x,
  453. int y)
  454. {
  455. int r;
  456. int g;
  457. int b;
  458. if (x == 0 && y == 0) {
  459. r = RGBQR(r0);
  460. g = RGBQG(r0);
  461. b = RGBQB(r0);
  462. } else if (x == 0) {
  463. r = ((FX1-y) * RGBQR(r0) + y * RGBQR(r2))/FX1;
  464. g = ((FX1-y) * RGBQG(r0) + y * RGBQG(r2))/FX1;
  465. b = ((FX1-y) * RGBQB(r0) + y * RGBQB(r2))/FX1;
  466. }
  467. else if (y == 0)
  468. {
  469. r = ((FX1-x) * RGBQR(r0) + x * RGBQR(r1))/FX1;
  470. g = ((FX1-x) * RGBQG(r0) + x * RGBQG(r1))/FX1;
  471. b = ((FX1-x) * RGBQB(r0) + x * RGBQB(r1))/FX1;
  472. }
  473. else if (x == FX1/2 && y == FX1/2)
  474. {
  475. r = (RGBQR(r0) + RGBQR(r1) + RGBQR(r2) + RGBQR(r3))/4;
  476. g = (RGBQG(r0) + RGBQG(r1) + RGBQG(r2) + RGBQG(r3))/4;
  477. b = (RGBQB(r0) + RGBQB(r1) + RGBQB(r2) + RGBQB(r3))/4;
  478. }
  479. else
  480. {
  481. r =((ULONG)RGBQR(r0) * (FX1-x) / FX1 * (FX1-y) + (ULONG)RGBQR(r1) * x / FX1 * (FX1-y) +
  482. (ULONG)RGBQR(r2) * (FX1-x) / FX1 * y + (ULONG)RGBQR(r3) * x / FX1 * y )/FX1;
  483. g =((ULONG)RGBQG(r0) * (FX1-x) / FX1 * (FX1-y) + (ULONG)RGBQG(r1) * x / FX1 * (FX1-y) +
  484. (ULONG)RGBQG(r2) * (FX1-x) / FX1 * y + (ULONG)RGBQG(r3) * x / FX1 * y )/FX1;
  485. b =((ULONG)RGBQB(r0) * (FX1-x) / FX1 * (FX1-y) + (ULONG)RGBQB(r1) * x / FX1 * (FX1-y) +
  486. (ULONG)RGBQB(r2) * (FX1-x) / FX1 * y + (ULONG)RGBQB(r3) * x / FX1 * y )/FX1;
  487. }
  488. return RGB(r,g,b);
  489. }
  490. /***************************************************************************\
  491. * MixRGBI
  492. *
  493. *
  494. \***************************************************************************/
  495. _inline COLORREF MixRGBI(
  496. LPDWORD pal,
  497. BYTE b0,
  498. BYTE b1,
  499. BYTE b2,
  500. BYTE b3,
  501. int x,
  502. int y)
  503. {
  504. if (((b0 == b1) && (b1 == b2) && (b2 == b3)) || ((x == 0) && (y == 0)))
  505. return RGBX(pal[b0]);
  506. else
  507. return MixRGB(pal[b0], pal[b1], pal[b2], pal[b3], x, y);
  508. }
  509. /***************************************************************************\
  510. * InitDst8
  511. *
  512. *
  513. \***************************************************************************/
  514. _inline VOID InitDst8(
  515. LPBITMAPINFOHEADER lpbi)
  516. {
  517. int r;
  518. int g;
  519. int b;
  520. LPDWORD pdw;
  521. pdw = (LPDWORD)(lpbi + 1);
  522. lpbi->biClrUsed = 6*6*6;
  523. for (r=0; r < 6; r++) {
  524. for (g=0; g < 6; g++) {
  525. for (b=0; b < 6; b++) {
  526. *pdw++ = RGBQ((r * 255) / 5, (g * 255) / 5, (b * 255) / 5);
  527. }
  528. }
  529. }
  530. for (b=0; b < 256; b++) {
  531. bmap[b] = (b * 5 + 128) / 255;
  532. gmap[b] = 6 * bmap[b];
  533. rmap[b] = 36 * bmap[b];
  534. }
  535. }
  536. /***************************************************************************\
  537. * Map8
  538. *
  539. *
  540. \***************************************************************************/
  541. _inline BYTE Map8(
  542. COLORREF rgb)
  543. {
  544. return rmap[GetRValue(rgb)] +
  545. gmap[GetGValue(rgb)] +
  546. bmap[GetBValue(rgb)];
  547. }