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

/****************************** Module Header ******************************\
* Module Name: cldib.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
*
* 09-26-95 ChrisWil Ported dib-scale code.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/*
* Constants.
*/
#define FX1 65536 // 1.0 in fixed point
/*
* Local Macros.
*/
#define BPPTOINDEX(bpp) ((UINT)(bpp) >> 3)
#define RGBQ(r,g,b) RGB(b, g, r)
#define RGBQR(rgb) GetBValue(rgb)
#define RGBQG(rgb) GetGValue(rgb)
#define RGBQB(rgb) GetRValue(rgb)
#define Pel4(p,x) (BYTE)(((x) & 1) ? (((LPBYTE)(p))[(x)/2] & 15) : (((LPBYTE)(p))[(x)/2] >> 4))
#define Pel8(p,x) (BYTE)(((LPBYTE)(p))[(x)])
#define Pel16(p,x) (((WORD UNALIGNED *)(p))[(x)])
#define Pel24(p,x) (*(DWORD UNALIGNED *)((LPBYTE)(p) + (x) * 3))
/*
* Function Typedefs.
*/
typedef VOID (*SCALEPROC)(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
typedef VOID (*INITPROC)(LPBITMAPINFOHEADER);
/*
* Local Routines.
*/
BOOL ScaleDIB(LPBITMAPINFOHEADER, LPVOID, LPBITMAPINFOHEADER, LPVOID);
VOID InitDst8(LPBITMAPINFOHEADER);
VOID Scale48(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
VOID Scale88(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
VOID Scale424(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
VOID Scale824(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
VOID Scale2424(LPDWORD, LPBYTE, long, int, int, int, int, LPBYTE, long, int, int);
BYTE Map8(COLORREF);
COLORREF MixRGBI(LPDWORD, BYTE, BYTE,BYTE, BYTE, int, int);
COLORREF MixRGB(DWORD, DWORD, DWORD, DWORD, int, int);
/*
* Globals needed for color-mapping of resources.
*/
SCALEPROC ScaleProc[4][4] = {
NULL, Scale48, NULL, Scale424,
NULL, Scale88, NULL, Scale824,
NULL, NULL , NULL, NULL,
NULL, NULL , NULL, Scale2424
};
INITPROC InitDst[] = {
NULL, InitDst8, NULL, NULL
};
BYTE rmap[256], gmap[256], bmap[256];
/***************************************************************************\
* SmartStretchDIBits
*
* calls GDI StretchDIBits, unless the stretch is 2:1 and the source
* is 4bpp, then is does it itself in a nice way.
*
* this optimization should just be put into GDI.
*
* can we change the passed bits? I assume we cant, could avoid a alloc
* if so.
*
\***************************************************************************/
int SmartStretchDIBits(
HDC hdc,
int xD,
int yD,
int dxD,
int dyD,
int xS,
int yS,
int dxS,
int dyS,
LPVOID lpBits,
LPBITMAPINFO lpbi,
UINT wUsage,
DWORD rop)
{
LPBYTE lpBitsNew;
UINT bpp;
RGBQUAD rgb;
LPBITMAPINFOHEADER lpbiNew = NULL;
int i;
/*
* thunk to USER32
*/
UserAssert(rop == SRCCOPY);
UserAssert(wUsage == DIB_RGB_COLORS);
UserAssert(xS == 0 && yS == 0);
if ((GetDIBColorTable(hdc, 0, 1, &rgb) != 1) &&
(dxD != dxS || dyD != dyS) && // 1:1 stretch just call GDI
(dxD >= dxS/2) && (dyD >= dyS/2) && // less than 1:2 shrink call GDI
(lpbi->bmiHeader.biCompression == 0) && // must be un-compressed
(lpbi->bmiHeader.biBitCount == 4 || // input must be 4,8,24
lpbi->bmiHeader.biBitCount == 8 ||
lpbi->bmiHeader.biBitCount == 24)) {
bpp = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
bpp = (bpp > 8 ? 24 : 8);
lpbiNew = (LPBITMAPINFOHEADER)UserLocalAlloc(0,
sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)) +
(UINT)((((dxD * bpp) / 8) + 3) & ~3) * (UINT)dyD);
if (lpbiNew) {
*lpbiNew = lpbi->bmiHeader;
lpbiNew->biWidth = dxD;
lpbiNew->biHeight = dyD;
lpbiNew->biBitCount = (WORD)bpp;
lpBitsNew = (LPBYTE)lpbiNew +
sizeof(BITMAPINFOHEADER) +
(256 * sizeof(RGBQUAD));
if (ScaleDIB((LPBITMAPINFOHEADER)lpbi,
(LPVOID)lpBits,
lpbiNew,
lpBitsNew)) {
lpbi = (LPBITMAPINFO)lpbiNew;
lpBits = lpBitsNew;
dxS = dxD;
dyS = dyD;
}
}
}
i = StretchDIBits(hdc,
xD,
yD,
dxD,
dyD,
xS,
yS,
dxS,
dyS,
lpBits,
lpbi,
wUsage,
rop);
if (lpbiNew)
UserLocalFree(lpbiNew);
return i;
}
/***************************************************************************\
* ScaleDIB
*
* Parameters
* ----------
* lpbiSrc - BITMAPINFO of source.
* lpSrc - Input bits to crunch.
* lpbiDst - BITMAPINFO of destination.
* lpDst - Output bits to crunch.
*
*
\***************************************************************************/
BOOL ScaleDIB(
LPBITMAPINFOHEADER lpbiSrc,
LPVOID lpSrc,
LPBITMAPINFOHEADER lpbiDst,
LPVOID lpDst)
{
LPBYTE pbSrc;
LPBYTE pbDst;
LPDWORD pal;
int dxSrc;
int dySrc;
int dxDst;
int dyDst;
int iSrc;
int iDst;
int x0;
int y0;
int sdx;
int sdy;
LONG WidthBytesSrc;
LONG WidthBytesDst;
if ((lpbiSrc->biCompression != BI_RGB) ||
(lpbiDst->biCompression != BI_RGB)) {
return FALSE;
}
iSrc = BPPTOINDEX(lpbiSrc->biBitCount);
iDst = BPPTOINDEX(lpbiDst->biBitCount);
if (ScaleProc[iSrc][iDst] == NULL)
return FALSE;
dxSrc = (int)lpbiSrc->biWidth;
dySrc = (int)lpbiSrc->biHeight;
dxDst = (int)lpbiDst->biWidth;
dyDst = (int)lpbiDst->biHeight;
WidthBytesDst = BitmapWidth(lpbiDst->biWidth, lpbiDst->biBitCount);
WidthBytesSrc = BitmapWidth(lpbiSrc->biWidth, lpbiSrc->biBitCount);
lpbiDst->biSizeImage = (WidthBytesDst * dyDst);
pbSrc = (LPBYTE)lpSrc;
pbDst = (LPBYTE)lpDst;
pal = (LPDWORD)(lpbiSrc + 1);
if (InitDst[iDst])
InitDst[iDst](lpbiDst);
if ((dxSrc == (dxDst * 2)) && (dySrc == (dyDst * 2))) {
sdx = FX1 * 2;
sdy = FX1 * 2;
y0 = FX1 / 2;
x0 = FX1 / 2;
} else {
sdx = (dxSrc - 1) * FX1 / (dxDst - 1);
sdy = (dySrc - 1) * FX1 / (dyDst - 1);
y0 = 0;
x0 = 0;
}
/*
* Make sure we don't croak on a bad bitmap since this can hose winlogon
* if it's the desktop wallpaper.
*/
try {
ScaleProc[iSrc][iDst](pal,
pbSrc,
WidthBytesSrc,
x0,
y0,
sdx,
sdy,
pbDst,
WidthBytesDst,
dxDst,
dyDst);
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
return FALSE;
}
return TRUE;
}
/***************************************************************************\
* Scale48
*
*
\***************************************************************************/
VOID Scale48(
LPDWORD pal,
LPBYTE pbSrc,
LONG WidthBytesSrc,
int x0,
int y0,
int sdx,
int sdy,
LPBYTE pbDst,
LONG WidthBytesDst,
int dxDst,
int dyDst)
{
BYTE b0;
BYTE b1;
BYTE b2;
BYTE b3;
LPBYTE pb;
int x;
int y;
UINT sx;
UINT sy;
for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
pb = pbSrc + (WidthBytesSrc * (sy / FX1));
for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
b0 = Pel4(pb, (sx / FX1));
b1 = Pel4(pb, (sx / FX1) + 1);
b2 = Pel4(pb + WidthBytesSrc, (sx / FX1));
b3 = Pel4(pb + WidthBytesSrc, (sx / FX1) + 1);
pbDst[x] = Map8(MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1));
}
pbDst += WidthBytesDst;
}
}
/***************************************************************************\
* Scale88
*
*
\***************************************************************************/
VOID Scale88(
LPDWORD pal,
LPBYTE pbSrc,
LONG WidthBytesSrc,
int x0,
int y0,
int sdx,
int sdy,
LPBYTE pbDst,
LONG WidthBytesDst,
int dxDst,
int dyDst)
{
BYTE b0;
BYTE b1;
BYTE b2;
BYTE b3;
LPBYTE pb;
int x;
int y;
UINT sx;
UINT sy;
for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
pb = pbSrc + (WidthBytesSrc * (sy / FX1));
for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
b0 = Pel8(pb, (sx / FX1));
b1 = Pel8(pb, (sx / FX1) + 1);
b2 = Pel8(pb + WidthBytesSrc, (sx / FX1));
b3 = Pel8(pb + WidthBytesSrc, (sx / FX1) + 1);
pbDst[x] = Map8(MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1));
}
pbDst += WidthBytesDst;
}
}
/***************************************************************************\
* Scale424
*
*
\***************************************************************************/
VOID Scale424(
LPDWORD pal,
LPBYTE pbSrc,
LONG WidthBytesSrc,
int x0,
int y0,
int sdx,
int sdy,
LPBYTE pbDst,
LONG WidthBytesDst,
int dxDst,
int dyDst)
{
BYTE b0;
BYTE b1;
BYTE b2;
BYTE b3;
LPBYTE pb;
int x;
int y;
UINT sx;
UINT sy;
COLORREF rgb;
for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
pb = pbSrc + (WidthBytesSrc * (sy / FX1));
for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
b0 = Pel4(pb, (sx / FX1));
b1 = Pel4(pb, (sx / FX1) + 1);
b2 = Pel4(pb + WidthBytesSrc, (sx / FX1));
b3 = Pel4(pb + WidthBytesSrc, (sx / FX1) + 1);
rgb = MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1);
*pbDst++ = GetBValue(rgb);
*pbDst++ = GetGValue(rgb);
*pbDst++ = GetRValue(rgb);
}
pbDst += (WidthBytesDst - (dxDst * 3));
}
}
/***************************************************************************\
* Scale824
*
*
\***************************************************************************/
VOID Scale824(
LPDWORD pal,
LPBYTE pbSrc,
LONG WidthBytesSrc,
int x0,
int y0,
int sdx,
int sdy,
LPBYTE pbDst,
LONG WidthBytesDst,
int dxDst,
int dyDst)
{
BYTE b0;
BYTE b1;
BYTE b2;
BYTE b3;
LPBYTE pb;
int x;
int y;
UINT sx;
UINT sy;
COLORREF rgb;
for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
pb = pbSrc + (WidthBytesSrc * (sy / FX1));
for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
b0 = Pel8(pb, (sx / FX1));
b1 = Pel8(pb, (sx / FX1) + 1);
b2 = Pel8(pb + WidthBytesSrc, (sx / FX1));
b3 = Pel8(pb + WidthBytesSrc, (sx / FX1) + 1);
rgb = MixRGBI(pal, b0, b1, b2, b3, sx % FX1, sy % FX1);
*pbDst++ = GetBValue(rgb);
*pbDst++ = GetGValue(rgb);
*pbDst++ = GetRValue(rgb);
}
pbDst += (WidthBytesDst - (dxDst * 3));
}
}
/***************************************************************************\
* Scale2424
*
*
\***************************************************************************/
VOID Scale2424(
LPDWORD pal,
LPBYTE pbSrc,
LONG WidthBytesSrc,
int x0,
int y0,
int sdx,
int sdy,
LPBYTE pbDst,
LONG WidthBytesDst,
int dxDst,
int dyDst)
{
DWORD bgr0;
DWORD bgr1;
DWORD bgr2;
DWORD bgr3;
LPBYTE pb;
int x;
int y;
UINT sx;
UINT sy;
COLORREF rgb;
UNREFERENCED_PARAMETER(pal);
for (sy=y0, y=0; y < dyDst; y++, sy+=sdy) {
pb = pbSrc + (WidthBytesSrc * (sy / FX1));
for (sx=x0, x=0; x < dxDst; x++, sx+=sdx) {
bgr0 = Pel24(pb, (sx / FX1));
bgr1 = Pel24(pb, (sx / FX1) + 1);
bgr2 = Pel24(pb + WidthBytesSrc, (sx / FX1));
bgr3 = Pel24(pb + WidthBytesSrc, (sx / FX1) + 1);
rgb = MixRGB(bgr0, bgr1, bgr2, bgr3, sx % FX1, sy % FX1);
*pbDst++ = GetBValue(rgb);
*pbDst++ = GetGValue(rgb);
*pbDst++ = GetRValue(rgb);
}
pbDst += (WidthBytesDst - (dxDst * 3));
}
}
/***************************************************************************\
* MixRGB
*
* r0 x r1
* y *
* r2 r3
*
* Note: inputs are RGBQUADs, output is a COLORREF.
*
\***************************************************************************/
COLORREF MixRGB(
DWORD r0,
DWORD r1,
DWORD r2,
DWORD r3,
int x,
int y)
{
int r;
int g;
int b;
if (x == 0 && y == 0) {
r = RGBQR(r0);
g = RGBQG(r0);
b = RGBQB(r0);
} else if (x == 0) {
r = ((FX1-y) * RGBQR(r0) + y * RGBQR(r2))/FX1;
g = ((FX1-y) * RGBQG(r0) + y * RGBQG(r2))/FX1;
b = ((FX1-y) * RGBQB(r0) + y * RGBQB(r2))/FX1;
}
else if (y == 0)
{
r = ((FX1-x) * RGBQR(r0) + x * RGBQR(r1))/FX1;
g = ((FX1-x) * RGBQG(r0) + x * RGBQG(r1))/FX1;
b = ((FX1-x) * RGBQB(r0) + x * RGBQB(r1))/FX1;
}
else if (x == FX1/2 && y == FX1/2)
{
r = (RGBQR(r0) + RGBQR(r1) + RGBQR(r2) + RGBQR(r3))/4;
g = (RGBQG(r0) + RGBQG(r1) + RGBQG(r2) + RGBQG(r3))/4;
b = (RGBQB(r0) + RGBQB(r1) + RGBQB(r2) + RGBQB(r3))/4;
}
else
{
r =((ULONG)RGBQR(r0) * (FX1-x) / FX1 * (FX1-y) + (ULONG)RGBQR(r1) * x / FX1 * (FX1-y) +
(ULONG)RGBQR(r2) * (FX1-x) / FX1 * y + (ULONG)RGBQR(r3) * x / FX1 * y )/FX1;
g =((ULONG)RGBQG(r0) * (FX1-x) / FX1 * (FX1-y) + (ULONG)RGBQG(r1) * x / FX1 * (FX1-y) +
(ULONG)RGBQG(r2) * (FX1-x) / FX1 * y + (ULONG)RGBQG(r3) * x / FX1 * y )/FX1;
b =((ULONG)RGBQB(r0) * (FX1-x) / FX1 * (FX1-y) + (ULONG)RGBQB(r1) * x / FX1 * (FX1-y) +
(ULONG)RGBQB(r2) * (FX1-x) / FX1 * y + (ULONG)RGBQB(r3) * x / FX1 * y )/FX1;
}
return RGB(r,g,b);
}
/***************************************************************************\
* MixRGBI
*
*
\***************************************************************************/
_inline COLORREF MixRGBI(
LPDWORD pal,
BYTE b0,
BYTE b1,
BYTE b2,
BYTE b3,
int x,
int y)
{
if (((b0 == b1) && (b1 == b2) && (b2 == b3)) || ((x == 0) && (y == 0)))
return RGBX(pal[b0]);
else
return MixRGB(pal[b0], pal[b1], pal[b2], pal[b3], x, y);
}
/***************************************************************************\
* InitDst8
*
*
\***************************************************************************/
_inline VOID InitDst8(
LPBITMAPINFOHEADER lpbi)
{
int r;
int g;
int b;
LPDWORD pdw;
pdw = (LPDWORD)(lpbi + 1);
lpbi->biClrUsed = 6*6*6;
for (r=0; r < 6; r++) {
for (g=0; g < 6; g++) {
for (b=0; b < 6; b++) {
*pdw++ = RGBQ((r * 255) / 5, (g * 255) / 5, (b * 255) / 5);
}
}
}
for (b=0; b < 256; b++) {
bmap[b] = (b * 5 + 128) / 255;
gmap[b] = 6 * bmap[b];
rmap[b] = 36 * bmap[b];
}
}
/***************************************************************************\
* Map8
*
*
\***************************************************************************/
_inline BYTE Map8(
COLORREF rgb)
{
return rmap[GetRValue(rgb)] +
gmap[GetGValue(rgb)] +
bmap[GetBValue(rgb)];
}