From 43412229b7159ed5ea44863424a764a31d971685 Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Thu, 11 Dec 2003 22:55:03 +0000 Subject: [PATCH] Implemented 16bpp to 16bpp scaling. Only stretch now, shrinking works incorrectly! If you find errors in the code - email me. svn path=/trunk/; revision=6961 --- reactos/subsys/win32k/dib/dib16bpp.c | 207 ++++++++++++++++++++++++++- 1 file changed, 204 insertions(+), 3 deletions(-) diff --git a/reactos/subsys/win32k/dib/dib16bpp.c b/reactos/subsys/win32k/dib/dib16bpp.c index d701b0bd760..9382b365bda 100644 --- a/reactos/subsys/win32k/dib/dib16bpp.c +++ b/reactos/subsys/win32k/dib/dib16bpp.c @@ -16,10 +16,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dib16bpp.c,v 1.11 2003/12/08 18:05:30 fireball Exp $ */ +/* $Id: dib16bpp.c,v 1.12 2003/12/11 22:55:03 fireball Exp $ */ #undef WIN32_LEAN_AND_MEAN #include #include +#include #include #include #include @@ -338,14 +339,214 @@ DIB_16BPP_BitBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, return TRUE; } + +/* +======================================= + Stretching functions goes below + Some parts of code are based on an + article "Bresenhame image scaling" + Dr. Dobb Journal, May 2002 +======================================= +*/ + +typedef unsigned short PIXEL; + +// DON'T FIX BUGS IN THIS FUNCTION YET +// BUT EMAIL INFO ABOUT IT TO aleksey at studiocerebral.com +// THIS IS WORK IN PROGRESS !! + +/* 16-bit HiColor (565 format) */ +inline unsigned short average(unsigned short a, unsigned short b) +{ +/* + if (a == b) { + return a; + } else { + unsigned short mask = ~ (((a | b) & 0x0410) << 1); + return ((a & mask) + (b & mask)) >> 1; + }*/ /* if */ + return a; // FIXME: Temp hack to remove "PCB-effect" from the image +} + +// DON'T FIX BUGS IN THIS FUNCTION YET +// BUT EMAIL INFO ABOUT IT TO aleksey at studiocerebral.com +// THIS IS WORK IN PROGRESS !! +void ScaleLineAvg16(unsigned short *Target, unsigned short *Source, int SrcWidth, int TgtWidth) +{ + int NumPixels = TgtWidth; + int IntPart = SrcWidth / TgtWidth; + int FractPart = SrcWidth % TgtWidth; + int Mid = TgtWidth / 2; + int E = 0; + int skip; + WORD p; + + skip = (TgtWidth < SrcWidth) ? 0 : (TgtWidth / (2*SrcWidth) + 1); + NumPixels -= skip; + + while (NumPixels-- > 0) { + p = *Source; + if (E >= Mid) + p = average(p, *(Source+1)); + *Target++ = p; + Source += IntPart; + E += FractPart; + if (E >= TgtWidth) { + E -= TgtWidth; + Source++; + } /* if */ + } /* while */ + while (skip-- > 0) + *Target++ = *Source; +} + +// DON'T FIX BUGS IN THIS FUNCTION YET +// BUT EMAIL INFO ABOUT IT TO aleksey at studiocerebral.com +// THIS IS WORK IN PROGRESS !! +void ScaleRectAvg(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, + int TgtWidth, int TgtHeight, int srcPitch, int dstPitch) +{ + int NumPixels = TgtHeight; + //int IntPart = ceil(((float)SrcHeight / TgtHeight) * (float)SrcWidth); + int IntPart = (SrcHeight / TgtHeight) * SrcWidth; + int FractPart = SrcHeight % TgtHeight; + int Mid = TgtHeight / 2; + int E = 0; + int skip; + PIXEL *ScanLine, *ScanLineAhead; + PIXEL *PrevSource = NULL; + PIXEL *PrevSourceAhead = NULL; + + skip = (TgtHeight < SrcHeight) ? 0 : (TgtHeight / (2*SrcHeight) + 1); + NumPixels -= skip; + + ScanLine = (PIXEL*)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); // FIXME: Should we use PagedPool here? + ScanLineAhead = (PIXEL *)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); + + while (NumPixels-- > 0) { + if (Source != PrevSource) { + if (Source == PrevSourceAhead) { + /* the next scan line has already been scaled and stored in + * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead + * point to + */ + PIXEL *tmp = ScanLine; + ScanLine = ScanLineAhead; + ScanLineAhead = tmp; + } else { + ScaleLineAvg16(ScanLine, Source, SrcWidth, TgtWidth); + } /* if */ + PrevSource = Source; + } /* if */ + + if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + srcPitch)) { + int x; + ScaleLineAvg16(ScanLineAhead, (PIXEL *)((BYTE *)Source + srcPitch), SrcWidth, TgtWidth); + for (x = 0; x < TgtWidth; x++) + ScanLine[x] = average(ScanLine[x], ScanLineAhead[x]); + PrevSourceAhead = (PIXEL *)((BYTE *)Source + srcPitch); + } /* if */ + + memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); + Target = (PIXEL *)((BYTE *)Target + dstPitch); + Source += IntPart; // <----- + E += FractPart; + if (E >= TgtHeight) { + E -= TgtHeight; + Source = (PIXEL *)((BYTE *)Source + srcPitch); + } /* if */ + } /* while */ + + if (skip > 0 && Source != PrevSource) + ScaleLineAvg16(ScanLine, Source, SrcWidth, TgtWidth); + while (skip-- > 0) { + memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); + Target = (PIXEL *)((BYTE *)Target + dstPitch); + } /* while */ + + ExFreePool(ScanLine); + ExFreePool(ScanLineAhead); +} + +// DON'T FIX BUGS IN THIS FUNCTION YET +// BUT EMAIL INFO ABOUT IT TO aleksey at studiocerebral.com +// THIS IS WORK IN PROGRESS !! BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL* BrushOrigin, XLATEOBJ *ColorTranslation, ULONG Mode) { - DbgPrint("DIB_16BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel); - return FALSE; + BYTE *SourceLine, *DestLine; + + DbgPrint("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n", + SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom, + DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); + + switch(SourceGDI->BitsPerPixel) + { + case 1: + return FALSE; + break; + + case 4: + return FALSE; + break; + + case 8: + return FALSE; + break; + + case 16: + SourceLine = SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + 2 * SourceRect->left; + DestLine = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 2 * DestRect->left; + /* + y=0; + for (j = SourceRect->top; j < SourceRect->bottom; j++) + { + dday = -1000; + + while (dday < 0) + { + dday += izoom; + x=0; + DestBits = DestLine; + SourceBits = SourceLine; + for (i = SourceRect->left; i < SourceRect->right; i++) + { + *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, *((WORD *)SourceBits)); + SourceBits += 2; + DestBits += 2; + x++; + } + + //SourceLine += SourceSurf->lDelta; + DestLine += DestSurf->lDelta; + lines++; + } + SourceLine += SourceSurf->lDelta; + }*/ + ScaleRectAvg((PIXEL *)DestLine, (PIXEL *)SourceLine, + SourceRect->right-SourceRect->left, SourceRect->bottom-SourceRect->top, + DestRect->right-DestRect->left, DestRect->bottom-DestRect->top, SourceSurf->lDelta, DestSurf->lDelta); + break; + + case 24: + return FALSE; + break; + + case 32: + return FALSE; + break; + + default: + //DbgPrint("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + return FALSE; + } + + + + return TRUE; } /* EOF */