Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cldib.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: cldib.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * 00007 * 09-26-95 ChrisWil Ported dib-scale code. 00008 \***************************************************************************/ 00009 00010 #include "precomp.h" 00011 #pragma hdrstop 00012 00013 /* 00014 * Constants. 00015 */ 00016 #define FX1 65536 // 1.0 in fixed point 00017 00018 00019 /* 00020 * Local Macros. 00021 */ 00022 #define BPPTOINDEX(bpp) ((UINT)(bpp) >> 3) 00023 00024 #define RGBQ(r,g,b) RGB(b, g, r) 00025 #define RGBQR(rgb) GetBValue(rgb) 00026 #define RGBQG(rgb) GetGValue(rgb) 00027 #define RGBQB(rgb) GetRValue(rgb) 00028 00029 #define Pel4(p,x) (BYTE)(((x) & 1) ? (((LPBYTE)(p))[(x)/2] & 15) : (((LPBYTE)(p))[(x)/2] >> 4)) 00030 #define Pel8(p,x) (BYTE)(((LPBYTE)(p))[(x)]) 00031 #define Pel16(p,x) (((WORD UNALIGNED *)(p))[(x)]) 00032 #define Pel24(p,x) (*(DWORD UNALIGNED *)((LPBYTE)(p) + (x) * 3)) 00033 00034 /* 00035 * Function Typedefs. 00036 */ 00037 typedef VOID (*SCALEPROC)(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int); 00038 typedef VOID (*INITPROC)(LPBITMAPINFOHEADER); 00039 00040 /* 00041 * Local Routines. 00042 */ 00043 BOOL ScaleDIB(LPBITMAPINFOHEADER, LPVOID, LPBITMAPINFOHEADER, LPVOID); 00044 VOID InitDst8(LPBITMAPINFOHEADER); 00045 VOID Scale48(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int); 00046 VOID Scale88(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int); 00047 VOID Scale424(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int); 00048 VOID Scale824(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int); 00049 VOID Scale2424(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int); 00050 BYTE Map8(COLORREF); 00051 COLORREF MixRGBI(LPDWORD, BYTE, BYTE,BYTE, BYTE, int, int); 00052 COLORREF MixRGB(DWORD, DWORD, DWORD, DWORD, int, int); 00053 00054 /* 00055 * Globals needed for color-mapping of resources. 00056 */ 00057 SCALEPROC ScaleProc[4][4] = { 00058 NULL, Scale48, NULL, Scale424, 00059 NULL, Scale88, NULL, Scale824, 00060 NULL, NULL , NULL, NULL, 00061 NULL, NULL , NULL, Scale2424 00062 }; 00063 00064 INITPROC InitDst[] = { 00065 NULL, InitDst8, NULL, NULL 00066 }; 00067 00068 BYTE rmap[256], gmap[256], bmap[256]; 00069 00070 00071 /***************************************************************************\ 00072 * SmartStretchDIBits 00073 * 00074 * calls GDI StretchDIBits, unless the stretch is 2:1 and the source 00075 * is 4bpp, then is does it itself in a nice way. 00076 * 00077 * this optimization should just be put into GDI. 00078 * 00079 * can we change the passed bits? I assume we cant, could avoid a alloc 00080 * if so. 00081 * 00082 \***************************************************************************/ 00083 00084 int SmartStretchDIBits( 00085 HDC hdc, 00086 int xD, 00087 int yD, 00088 int dxD, 00089 int dyD, 00090 int xS, 00091 int yS, 00092 int dxS, 00093 int dyS, 00094 LPVOID lpBits, 00095 LPBITMAPINFO lpbi, 00096 UINT wUsage, 00097 DWORD rop) 00098 { 00099 LPBYTE lpBitsNew; 00100 UINT bpp; 00101 RGBQUAD rgb; 00102 LPBITMAPINFOHEADER lpbiNew = NULL; 00103 00104 int i; 00105 00106 /* 00107 * thunk to USER32 00108 */ 00109 UserAssert(rop == SRCCOPY); 00110 UserAssert(wUsage == DIB_RGB_COLORS); 00111 UserAssert(xS == 0 && yS == 0); 00112 00113 if ((GetDIBColorTable(hdc, 0, 1, &rgb) != 1) && 00114 (dxD != dxS || dyD != dyS) && // 1:1 stretch just call GDI 00115 (dxD >= dxS/2) && (dyD >= dyS/2) && // less than 1:2 shrink call GDI 00116 (lpbi->bmiHeader.biCompression == 0) && // must be un-compressed 00117 (lpbi->bmiHeader.biBitCount == 4 || // input must be 4,8,24 00118 lpbi->bmiHeader.biBitCount == 8 || 00119 lpbi->bmiHeader.biBitCount == 24)) { 00120 00121 bpp = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES); 00122 00123 bpp = (bpp > 8 ? 24 : 8); 00124 00125 lpbiNew = (LPBITMAPINFOHEADER)UserLocalAlloc(0, 00126 sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)) + 00127 (UINT)((((dxD * bpp) / 8) + 3) & ~3) * (UINT)dyD); 00128 00129 if (lpbiNew) { 00130 00131 *lpbiNew = lpbi->bmiHeader; 00132 lpbiNew->biWidth = dxD; 00133 lpbiNew->biHeight = dyD; 00134 lpbiNew->biBitCount = (WORD)bpp; 00135 lpBitsNew = (LPBYTE)lpbiNew + 00136 sizeof(BITMAPINFOHEADER) + 00137 (256 * sizeof(RGBQUAD)); 00138 00139 if (ScaleDIB((LPBITMAPINFOHEADER)lpbi, 00140 (LPVOID)lpBits, 00141 lpbiNew, 00142 lpBitsNew)) { 00143 00144 lpbi = (LPBITMAPINFO)lpbiNew; 00145 lpBits = lpBitsNew; 00146 dxS = dxD; 00147 dyS = dyD; 00148 } 00149 } 00150 } 00151 00152 i = StretchDIBits(hdc, 00153 xD, 00154 yD, 00155 dxD, 00156 dyD, 00157 xS, 00158 yS, 00159 dxS, 00160 dyS, 00161 lpBits, 00162 lpbi, 00163 wUsage, 00164 rop); 00165 00166 if (lpbiNew) 00167 UserLocalFree(lpbiNew); 00168 00169 return i; 00170 } 00171 00172 /***************************************************************************\ 00173 * ScaleDIB 00174 * 00175 * Parameters 00176 * ---------- 00177 * lpbiSrc - BITMAPINFO of source. 00178 * lpSrc - Input bits to crunch. 00179 * lpbiDst - BITMAPINFO of destination. 00180 * lpDst - Output bits to crunch. 00181 * 00182 * 00183 \***************************************************************************/ 00184 00185 BOOL ScaleDIB( 00186 LPBITMAPINFOHEADER lpbiSrc, 00187 LPVOID lpSrc, 00188 LPBITMAPINFOHEADER lpbiDst, 00189 LPVOID lpDst) 00190 { 00191 LPBYTE pbSrc; 00192 LPBYTE pbDst; 00193 LPDWORD pal; 00194 int dxSrc; 00195 int dySrc; 00196 int dxDst; 00197 int dyDst; 00198 int iSrc; 00199 int iDst; 00200 int x0; 00201 int y0; 00202 int sdx; 00203 int sdy; 00204 LONG WidthBytesSrc; 00205 LONG WidthBytesDst; 00206 00207 if ((lpbiSrc->biCompression != BI_RGB) || 00208 (lpbiDst->biCompression != BI_RGB)) { 00209 return FALSE; 00210 } 00211 00212 iSrc = BPPTOINDEX(lpbiSrc->biBitCount); 00213 iDst = BPPTOINDEX(lpbiDst->biBitCount); 00214 00215 if (ScaleProc[iSrc][iDst] == NULL) 00216 return FALSE; 00217 00218 dxSrc = (int)lpbiSrc->biWidth; 00219 dySrc = (int)lpbiSrc->biHeight; 00220 00221 dxDst = (int)lpbiDst->biWidth; 00222 dyDst = (int)lpbiDst->biHeight; 00223 00224 WidthBytesDst = BitmapWidth(lpbiDst->biWidth, lpbiDst->biBitCount); 00225 WidthBytesSrc = BitmapWidth(lpbiSrc->biWidth, lpbiSrc->biBitCount); 00226 00227 lpbiDst->biSizeImage = (WidthBytesDst * dyDst); 00228 00229 pbSrc = (LPBYTE)lpSrc; 00230 pbDst = (LPBYTE)lpDst; 00231 00232 pal = (LPDWORD)(lpbiSrc + 1); 00233 00234 if (InitDst[iDst]) 00235 InitDst[iDst](lpbiDst); 00236 00237 if ((dxSrc == (dxDst * 2)) && (dySrc == (dyDst * 2))) { 00238 00239 sdx = FX1 * 2; 00240 sdy = FX1 * 2; 00241 y0 = FX1 / 2; 00242 x0 = FX1 / 2; 00243 00244 } else { 00245 00246 sdx = (dxSrc - 1) * FX1 / (dxDst - 1); 00247 sdy = (dySrc - 1) * FX1 / (dyDst - 1); 00248 y0 = 0; 00249 x0 = 0; 00250 } 00251 00252 /* 00253 * Make sure we don't croak on a bad bitmap since this can hose winlogon 00254 * if it's the desktop wallpaper. 00255 */ 00256 try { 00257 ScaleProc[iSrc][iDst](pal, 00258 pbSrc, 00259 WidthBytesSrc, 00260 x0, 00261 y0, 00262 sdx, 00263 sdy, 00264 pbDst, 00265 WidthBytesDst, 00266 dxDst, 00267 dyDst); 00268 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00269 return FALSE; 00270 } 00271 00272 return TRUE; 00273 } 00274 00275 /***************************************************************************\ 00276 * Scale48 00277 * 00278 * 00279 \***************************************************************************/ 00280 00281 VOID Scale48( 00282 LPDWORD pal, 00283 LPBYTE pbSrc, 00284 LONG WidthBytesSrc, 00285 int x0, 00286 int y0, 00287 int sdx, 00288 int sdy, 00289 LPBYTE pbDst, 00290 LONG WidthBytesDst, 00291 int dxDst, 00292 int dyDst) 00293 { 00294 BYTE b0; 00295 BYTE b1; 00296 BYTE b2; 00297 BYTE b3; 00298 LPBYTE pb; 00299 int x; 00300 int y; 00301 UINT sx; 00302 UINT sy; 00303 00304 for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) { 00305 00306 pb = pbSrc + (WidthBytesSrc * (sy / FX1)); 00307 00308 for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) { 00309 00310 b0 = Pel4(pb, (sx / FX1)); 00311 b1 = Pel4(pb, (sx / FX1) + 1); 00312 b2 = Pel4(pb + WidthBytesSrc, (sx / FX1)); 00313 b3 = Pel4(pb + WidthBytesSrc, (sx / FX1) + 1); 00314 00315 pbDst[x] = Map8(MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1)); 00316 } 00317 00318 pbDst += WidthBytesDst; 00319 } 00320 } 00321 00322 /***************************************************************************\ 00323 * Scale88 00324 * 00325 * 00326 \***************************************************************************/ 00327 00328 VOID Scale88( 00329 LPDWORD pal, 00330 LPBYTE pbSrc, 00331 LONG WidthBytesSrc, 00332 int x0, 00333 int y0, 00334 int sdx, 00335 int sdy, 00336 LPBYTE pbDst, 00337 LONG WidthBytesDst, 00338 int dxDst, 00339 int dyDst) 00340 { 00341 BYTE b0; 00342 BYTE b1; 00343 BYTE b2; 00344 BYTE b3; 00345 LPBYTE pb; 00346 int x; 00347 int y; 00348 UINT sx; 00349 UINT sy; 00350 00351 for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) { 00352 00353 pb = pbSrc + (WidthBytesSrc * (sy / FX1)); 00354 00355 for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) { 00356 00357 b0 = Pel8(pb, (sx / FX1)); 00358 b1 = Pel8(pb, (sx / FX1) + 1); 00359 b2 = Pel8(pb + WidthBytesSrc, (sx / FX1)); 00360 b3 = Pel8(pb + WidthBytesSrc, (sx / FX1) + 1); 00361 00362 pbDst[x] = Map8(MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1)); 00363 } 00364 00365 pbDst += WidthBytesDst; 00366 } 00367 } 00368 00369 /***************************************************************************\ 00370 * Scale424 00371 * 00372 * 00373 \***************************************************************************/ 00374 00375 VOID Scale424( 00376 LPDWORD pal, 00377 LPBYTE pbSrc, 00378 LONG WidthBytesSrc, 00379 int x0, 00380 int y0, 00381 int sdx, 00382 int sdy, 00383 LPBYTE pbDst, 00384 LONG WidthBytesDst, 00385 int dxDst, 00386 int dyDst) 00387 { 00388 BYTE b0; 00389 BYTE b1; 00390 BYTE b2; 00391 BYTE b3; 00392 LPBYTE pb; 00393 int x; 00394 int y; 00395 UINT sx; 00396 UINT sy; 00397 COLORREF rgb; 00398 00399 for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) { 00400 00401 pb = pbSrc + (WidthBytesSrc * (sy / FX1)); 00402 00403 for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) { 00404 00405 b0 = Pel4(pb, (sx / FX1)); 00406 b1 = Pel4(pb, (sx / FX1) + 1); 00407 b2 = Pel4(pb + WidthBytesSrc, (sx / FX1)); 00408 b3 = Pel4(pb + WidthBytesSrc, (sx / FX1) + 1); 00409 00410 rgb = MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1); 00411 00412 *pbDst++ = GetBValue(rgb); 00413 *pbDst++ = GetGValue(rgb); 00414 *pbDst++ = GetRValue(rgb); 00415 } 00416 00417 pbDst += (WidthBytesDst - (dxDst * 3)); 00418 } 00419 } 00420 00421 /***************************************************************************\ 00422 * Scale824 00423 * 00424 * 00425 \***************************************************************************/ 00426 00427 VOID Scale824( 00428 LPDWORD pal, 00429 LPBYTE pbSrc, 00430 LONG WidthBytesSrc, 00431 int x0, 00432 int y0, 00433 int sdx, 00434 int sdy, 00435 LPBYTE pbDst, 00436 LONG WidthBytesDst, 00437 int dxDst, 00438 int dyDst) 00439 { 00440 BYTE b0; 00441 BYTE b1; 00442 BYTE b2; 00443 BYTE b3; 00444 LPBYTE pb; 00445 int x; 00446 int y; 00447 UINT sx; 00448 UINT sy; 00449 COLORREF rgb; 00450 00451 for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) { 00452 00453 pb = pbSrc + (WidthBytesSrc * (sy / FX1)); 00454 00455 for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) { 00456 00457 b0 = Pel8(pb, (sx / FX1)); 00458 b1 = Pel8(pb, (sx / FX1) + 1); 00459 b2 = Pel8(pb + WidthBytesSrc, (sx / FX1)); 00460 b3 = Pel8(pb + WidthBytesSrc, (sx / FX1) + 1); 00461 00462 rgb = MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1); 00463 00464 *pbDst++ = GetBValue(rgb); 00465 *pbDst++ = GetGValue(rgb); 00466 *pbDst++ = GetRValue(rgb); 00467 } 00468 00469 pbDst += (WidthBytesDst - (dxDst * 3)); 00470 } 00471 } 00472 00473 /***************************************************************************\ 00474 * Scale2424 00475 * 00476 * 00477 \***************************************************************************/ 00478 00479 VOID Scale2424( 00480 LPDWORD pal, 00481 LPBYTE pbSrc, 00482 LONG WidthBytesSrc, 00483 int x0, 00484 int y0, 00485 int sdx, 00486 int sdy, 00487 LPBYTE pbDst, 00488 LONG WidthBytesDst, 00489 int dxDst, 00490 int dyDst) 00491 { 00492 DWORD bgr0; 00493 DWORD bgr1; 00494 DWORD bgr2; 00495 DWORD bgr3; 00496 LPBYTE pb; 00497 int x; 00498 int y; 00499 UINT sx; 00500 UINT sy; 00501 COLORREF rgb; 00502 00503 UNREFERENCED_PARAMETER(pal); 00504 00505 for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) { 00506 00507 pb = pbSrc + (WidthBytesSrc * (sy / FX1)); 00508 00509 for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) { 00510 00511 bgr0 = Pel24(pb, (sx / FX1)); 00512 bgr1 = Pel24(pb, (sx / FX1) + 1); 00513 bgr2 = Pel24(pb + WidthBytesSrc, (sx / FX1)); 00514 bgr3 = Pel24(pb + WidthBytesSrc, (sx / FX1) + 1); 00515 00516 rgb = MixRGB(bgr0, bgr1, bgr2, bgr3, sx % FX1, sy % FX1); 00517 00518 *pbDst++ = GetBValue(rgb); 00519 *pbDst++ = GetGValue(rgb); 00520 *pbDst++ = GetRValue(rgb); 00521 } 00522 00523 pbDst += (WidthBytesDst - (dxDst * 3)); 00524 } 00525 } 00526 00527 /***************************************************************************\ 00528 * MixRGB 00529 * 00530 * r0 x r1 00531 * y * 00532 * r2 r3 00533 * 00534 * Note: inputs are RGBQUADs, output is a COLORREF. 00535 * 00536 \***************************************************************************/ 00537 00538 COLORREF MixRGB( 00539 DWORD r0, 00540 DWORD r1, 00541 DWORD r2, 00542 DWORD r3, 00543 int x, 00544 int y) 00545 { 00546 int r; 00547 int g; 00548 int b; 00549 00550 if (x == 0 && y == 0) { 00551 00552 r = RGBQR(r0); 00553 g = RGBQG(r0); 00554 b = RGBQB(r0); 00555 00556 } else if (x == 0) { 00557 00558 r = ((FX1-y) * RGBQR(r0) + y * RGBQR(r2))/FX1; 00559 g = ((FX1-y) * RGBQG(r0) + y * RGBQG(r2))/FX1; 00560 b = ((FX1-y) * RGBQB(r0) + y * RGBQB(r2))/FX1; 00561 } 00562 else if (y == 0) 00563 { 00564 r = ((FX1-x) * RGBQR(r0) + x * RGBQR(r1))/FX1; 00565 g = ((FX1-x) * RGBQG(r0) + x * RGBQG(r1))/FX1; 00566 b = ((FX1-x) * RGBQB(r0) + x * RGBQB(r1))/FX1; 00567 } 00568 else if (x == FX1/2 && y == FX1/2) 00569 { 00570 r = (RGBQR(r0) + RGBQR(r1) + RGBQR(r2) + RGBQR(r3))/4; 00571 g = (RGBQG(r0) + RGBQG(r1) + RGBQG(r2) + RGBQG(r3))/4; 00572 b = (RGBQB(r0) + RGBQB(r1) + RGBQB(r2) + RGBQB(r3))/4; 00573 } 00574 else 00575 { 00576 r =((ULONG)RGBQR(r0) * (FX1-x) / FX1 * (FX1-y) + (ULONG)RGBQR(r1) * x / FX1 * (FX1-y) + 00577 (ULONG)RGBQR(r2) * (FX1-x) / FX1 * y + (ULONG)RGBQR(r3) * x / FX1 * y )/FX1; 00578 00579 g =((ULONG)RGBQG(r0) * (FX1-x) / FX1 * (FX1-y) + (ULONG)RGBQG(r1) * x / FX1 * (FX1-y) + 00580 (ULONG)RGBQG(r2) * (FX1-x) / FX1 * y + (ULONG)RGBQG(r3) * x / FX1 * y )/FX1; 00581 00582 b =((ULONG)RGBQB(r0) * (FX1-x) / FX1 * (FX1-y) + (ULONG)RGBQB(r1) * x / FX1 * (FX1-y) + 00583 (ULONG)RGBQB(r2) * (FX1-x) / FX1 * y + (ULONG)RGBQB(r3) * x / FX1 * y )/FX1; 00584 } 00585 00586 return RGB(r,g,b); 00587 } 00588 00589 /***************************************************************************\ 00590 * MixRGBI 00591 * 00592 * 00593 \***************************************************************************/ 00594 00595 _inline COLORREF MixRGBI( 00596 LPDWORD pal, 00597 BYTE b0, 00598 BYTE b1, 00599 BYTE b2, 00600 BYTE b3, 00601 int x, 00602 int y) 00603 { 00604 if (((b0 == b1) && (b1 == b2) && (b2 == b3)) || ((x == 0) && (y == 0))) 00605 return RGBX(pal[b0]); 00606 else 00607 return MixRGB(pal[b0], pal[b1], pal[b2], pal[b3], x, y); 00608 } 00609 00610 /***************************************************************************\ 00611 * InitDst8 00612 * 00613 * 00614 \***************************************************************************/ 00615 00616 _inline VOID InitDst8( 00617 LPBITMAPINFOHEADER lpbi) 00618 { 00619 int r; 00620 int g; 00621 int b; 00622 LPDWORD pdw; 00623 00624 pdw = (LPDWORD)(lpbi + 1); 00625 lpbi->biClrUsed = 6*6*6; 00626 00627 for (r=0; r < 6; r++) { 00628 00629 for (g=0; g < 6; g++) { 00630 00631 for (b=0; b < 6; b++) { 00632 *pdw++ = RGBQ((r * 255) / 5, (g * 255) / 5, (b * 255) / 5); 00633 } 00634 } 00635 } 00636 00637 for (b=0; b < 256; b++) { 00638 bmap[b] = (b * 5 + 128) / 255; 00639 gmap[b] = 6 * bmap[b]; 00640 rmap[b] = 36 * bmap[b]; 00641 } 00642 } 00643 00644 /***************************************************************************\ 00645 * Map8 00646 * 00647 * 00648 \***************************************************************************/ 00649 00650 _inline BYTE Map8( 00651 COLORREF rgb) 00652 { 00653 return rmap[GetRValue(rgb)] + 00654 gmap[GetGValue(rgb)] + 00655 bmap[GetBValue(rgb)]; 00656 }

Generated on Sat May 15 19:39:24 2004 for test by doxygen 1.3.7