00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
#include "precomp.h"
00011
#pragma hdrstop
00012
00013
00014
00015
00016 #define FX1 65536 // 1.0 in fixed point
00017
00018
00019
00020
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
00036
00037 typedef VOID (*
SCALEPROC)(LPDWORD, LPBYTE,
long,
int,
int,
int,
int, LPBYTE,
long,
int,
int);
00038 typedef VOID (*
INITPROC)(LPBITMAPINFOHEADER);
00039
00040
00041
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
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
00073
00074
00075
00076
00077
00078
00079
00080
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
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) &&
00115 (dxD >= dxS/2) && (dyD >= dyS/2) &&
00116 (lpbi->bmiHeader.biCompression == 0) &&
00117 (lpbi->bmiHeader.biBitCount == 4 ||
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
00174
00175
00176
00177
00178
00179
00180
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
00254
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
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
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
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
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
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
00529
00530
00531
00532
00533
00534
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
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
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
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 }