2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: dib16bpp.c,v 1.15 2003/12/18 18:30:48 fireball Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
24 #include <win32k/bitmaps.h>
25 #include <win32k/debug.h>
27 #include <ddk/winddi.h>
28 #include "../eng/objects.h"
32 DIB_16BPP_PutPixel(PSURFOBJ SurfObj
, LONG x
, LONG y
, ULONG c
)
34 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
;
35 PWORD addr
= (PWORD
)byteaddr
+ x
;
41 DIB_16BPP_GetPixel(PSURFOBJ SurfObj
, LONG x
, LONG y
)
43 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
;
44 PWORD addr
= (PWORD
)byteaddr
+ x
;
46 return (ULONG
)(*addr
);
50 DIB_16BPP_HLine(PSURFOBJ SurfObj
, LONG x1
, LONG x2
, LONG y
, ULONG c
)
52 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
;
53 PWORD addr
= (PWORD
)byteaddr
+ x1
;
64 DIB_16BPP_VLine(PSURFOBJ SurfObj
, LONG x
, LONG y1
, LONG y2
, ULONG c
)
66 PBYTE byteaddr
= SurfObj
->pvScan0
+ y1
* SurfObj
->lDelta
;
67 PWORD addr
= (PWORD
)byteaddr
+ x
;
68 LONG lDelta
= SurfObj
->lDelta
;
70 byteaddr
= (PBYTE
)addr
;
75 addr
= (PWORD
)byteaddr
;
80 DIB_16BPP_BitBltSrcCopy(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
81 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
82 PRECTL DestRect
, POINTL
*SourcePoint
,
83 XLATEOBJ
*ColorTranslation
)
85 LONG i
, j
, sx
, sy
, xColor
, f1
;
86 PBYTE SourceBits
, DestBits
, SourceLine
, DestLine
;
87 PBYTE SourceBits_4BPP
, SourceLine_4BPP
;
88 DestBits
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + 2 * DestRect
->left
;
90 switch(SourceGDI
->BitsPerPixel
)
96 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
99 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
101 if(DIB_1BPP_GetPixel(SourceSurf
, sx
, sy
) == 0)
103 DIB_16BPP_PutPixel(DestSurf
, i
, j
, XLATEOBJ_iXlate(ColorTranslation
, 0));
105 DIB_16BPP_PutPixel(DestSurf
, i
, j
, XLATEOBJ_iXlate(ColorTranslation
, 1));
114 SourceBits_4BPP
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + (SourcePoint
->x
>> 1);
116 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
118 SourceLine_4BPP
= SourceBits_4BPP
;
122 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
124 xColor
= XLATEOBJ_iXlate(ColorTranslation
,
125 (*SourceLine_4BPP
& altnotmask
[sx
&1]) >> (4 * (1-(sx
& 1))));
126 DIB_16BPP_PutPixel(DestSurf
, i
, j
, xColor
);
127 if(f1
== 1) { SourceLine_4BPP
++; f1
= 0; } else { f1
= 1; }
131 SourceBits_4BPP
+= SourceSurf
->lDelta
;
136 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + SourcePoint
->x
;
139 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
141 SourceBits
= SourceLine
;
144 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
146 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, *SourceBits
);
151 SourceLine
+= SourceSurf
->lDelta
;
152 DestLine
+= DestSurf
->lDelta
;
157 if (NULL
== ColorTranslation
|| 0 != (ColorTranslation
->flXlate
& XO_TRIVIAL
))
159 if (DestRect
->top
< SourcePoint
->y
)
161 SourceBits
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
162 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
164 RtlMoveMemory(DestBits
, SourceBits
, 2 * (DestRect
->right
- DestRect
->left
));
165 SourceBits
+= SourceSurf
->lDelta
;
166 DestBits
+= DestSurf
->lDelta
;
171 SourceBits
= SourceSurf
->pvScan0
+ ((SourcePoint
->y
+ DestRect
->bottom
- DestRect
->top
- 1) * SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
172 DestBits
= DestSurf
->pvScan0
+ ((DestRect
->bottom
- 1) * DestSurf
->lDelta
) + 2 * DestRect
->left
;
173 for (j
= DestRect
->bottom
- 1; DestRect
->top
<= j
; j
--)
175 RtlMoveMemory(DestBits
, SourceBits
, 2 * (DestRect
->right
- DestRect
->left
));
176 SourceBits
-= SourceSurf
->lDelta
;
177 DestBits
-= DestSurf
->lDelta
;
183 if (DestRect
->top
< SourcePoint
->y
)
185 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
187 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
189 SourceBits
= SourceLine
;
191 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
193 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, *((WORD
*)SourceBits
));
197 SourceLine
+= SourceSurf
->lDelta
;
198 DestLine
+= DestSurf
->lDelta
;
203 SourceLine
= SourceSurf
->pvScan0
+ ((SourcePoint
->y
+ DestRect
->bottom
- DestRect
->top
- 1) * SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
204 DestLine
= DestSurf
->pvScan0
+ ((DestRect
->bottom
- 1) * DestSurf
->lDelta
) + 2 * DestRect
->left
;
205 for (j
= DestRect
->bottom
- 1; DestRect
->top
<= j
; j
--)
207 SourceBits
= SourceLine
;
209 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
211 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, *((WORD
*)SourceBits
));
215 SourceLine
-= SourceSurf
->lDelta
;
216 DestLine
-= DestSurf
->lDelta
;
223 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 3 * SourcePoint
->x
;
226 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
228 SourceBits
= SourceLine
;
231 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
233 xColor
= (*(SourceBits
+ 2) << 0x10) +
234 (*(SourceBits
+ 1) << 0x08) +
236 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, xColor
);
241 SourceLine
+= SourceSurf
->lDelta
;
242 DestLine
+= DestSurf
->lDelta
;
247 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 4 * SourcePoint
->x
;
250 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
252 SourceBits
= SourceLine
;
255 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
257 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, *((PDWORD
) SourceBits
));
262 SourceLine
+= SourceSurf
->lDelta
;
263 DestLine
+= DestSurf
->lDelta
;
268 DbgPrint("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);
276 DIB_16BPP_BitBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
277 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
278 PRECTL DestRect
, POINTL
*SourcePoint
,
279 PBRUSHOBJ Brush
, PPOINTL BrushOrigin
,
280 XLATEOBJ
*ColorTranslation
, ULONG Rop4
)
283 ULONG Dest
, Source
, Pattern
;
285 BOOL UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
286 BOOL UsesPattern
= ((Rop4
& 0xF00000) >> 4) != (Rop4
& 0x0F0000);
287 LONG RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x1);
291 return(DIB_16BPP_BitBltSrcCopy(DestSurf
, SourceSurf
, DestGDI
, SourceGDI
, DestRect
, SourcePoint
, ColorTranslation
));
297 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
300 DestBits
= (PULONG
)(DestSurf
->pvScan0
+ 2 * DestRect
->left
+ j
* DestSurf
->lDelta
);
301 for (i
=DestRect
->left
; i
<RoundedRight
; i
+=2, DestBits
++)
306 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, sx
+ (i
- DestRect
->left
), sy
, ColorTranslation
);
307 Source
|= DIB_GetSource(SourceSurf
, SourceGDI
, sx
+ (i
- DestRect
->left
) + 1, sy
, ColorTranslation
) << 16;
311 /* FIXME: No support for pattern brushes. */
312 Pattern
= (Brush
->iSolidColor
& 0xFFFF) |
313 ((Brush
->iSolidColor
& 0xFFFF) << 16);
315 *DestBits
= DIB_DoRop(Rop4
, Dest
, Source
, Pattern
);
317 if (i
< DestRect
->right
)
320 for (; i
< DestRect
->right
; i
++)
324 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, sx
+ (i
- DestRect
->left
), sy
, ColorTranslation
);
328 /* FIXME: No support for pattern brushes. */
329 Pattern
= (Brush
->iSolidColor
& 0xFFFF) |
330 ((Brush
->iSolidColor
& 0xFFFF) << 16);
332 DIB_16BPP_PutPixel(DestSurf
, i
, j
, DIB_DoRop(Rop4
, Dest
, Source
, Pattern
) & 0xFFFF);
344 =======================================
345 Stretching functions goes below
346 Some parts of code are based on an
347 article "Bresenhame image scaling"
348 Dr. Dobb Journal, May 2002
349 =======================================
352 typedef unsigned short PIXEL
;
354 /* 16-bit HiColor (565 format) */
355 inline PIXEL
average16(PIXEL a
, PIXEL b
)
357 // This one doesn't work
362 unsigned short mask = ~ (((a | b) & 0x0410) << 1);
363 return ((a & mask) + (b & mask)) >> 1;
366 // This one should be correct, but it's too long
368 unsigned char r1, g1, b1, r2, g2, b2, rr, gr, br;
371 r1 = (a & 0xF800) >> 11;
372 g1 = (a & 0x7E0) >> 5;
375 r2 = (b & 0xF800) >> 11;
376 g2 = (b & 0x7E0) >> 5;
383 res = (rr << 11) + (gr << 5) + br;
387 return a
; // FIXME: Depend on SetStretchMode
390 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
391 void ScaleLineAvg16(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int TgtWidth
)
393 int NumPixels
= TgtWidth
;
394 int IntPart
= SrcWidth
/ TgtWidth
;
395 int FractPart
= SrcWidth
% TgtWidth
;
396 int Mid
= TgtWidth
/ 2;
401 skip
= (TgtWidth
< SrcWidth
) ? 0 : (TgtWidth
/ (2*SrcWidth
) + 1);
404 while (NumPixels
-- > 0) {
407 p
= average16(p
, *(Source
+1));
420 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
421 void ScaleRectAvg16(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int SrcHeight
,
422 int TgtWidth
, int TgtHeight
, int srcPitch
, int dstPitch
)
424 int NumPixels
= TgtHeight
;
425 int IntPart
= (SrcHeight
/ TgtHeight
) * (SrcWidth
+1);
426 int FractPart
= SrcHeight
% TgtHeight
;
427 int Mid
= TgtHeight
/ 2;
430 PIXEL
*ScanLine
, *ScanLineAhead
;
431 PIXEL
*PrevSource
= NULL
;
432 PIXEL
*PrevSourceAhead
= NULL
;
434 skip
= (TgtHeight
< SrcHeight
) ? 0 : (TgtHeight
/ (2*SrcHeight
) + 1);
437 ScanLine
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
)); // FIXME: Should we use PagedPool here?
438 ScanLineAhead
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
));
440 while (NumPixels
-- > 0) {
441 if (Source
!= PrevSource
) {
442 if (Source
== PrevSourceAhead
) {
443 /* the next scan line has already been scaled and stored in
444 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
447 PIXEL
*tmp
= ScanLine
;
448 ScanLine
= ScanLineAhead
;
451 ScaleLineAvg16(ScanLine
, Source
, SrcWidth
, TgtWidth
);
456 if (E
>= Mid
&& PrevSourceAhead
!= (PIXEL
*)((BYTE
*)Source
+ srcPitch
)) {
458 ScaleLineAvg16(ScanLineAhead
, (PIXEL
*)((BYTE
*)Source
+ srcPitch
), SrcWidth
, TgtWidth
);
459 for (x
= 0; x
< TgtWidth
; x
++)
460 ScanLine
[x
] = average16(ScanLine
[x
], ScanLineAhead
[x
]);
461 PrevSourceAhead
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
464 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
465 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
468 if (E
>= TgtHeight
) {
470 Source
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
474 if (skip
> 0 && Source
!= PrevSource
)
475 ScaleLineAvg16(ScanLine
, Source
, SrcWidth
, TgtWidth
);
477 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
478 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
481 ExFreePool(ScanLine
);
482 ExFreePool(ScanLineAhead
);
485 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
486 BOOLEAN
DIB_16BPP_StretchBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
487 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
488 RECTL
* DestRect
, RECTL
*SourceRect
,
489 POINTL
* MaskOrigin
, POINTL
* BrushOrigin
,
490 XLATEOBJ
*ColorTranslation
, ULONG Mode
)
492 BYTE
*SourceLine
, *DestLine
;
494 DbgPrint("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
495 SourceGDI
->BitsPerPixel
, SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
,
496 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
498 switch(SourceGDI
->BitsPerPixel
)
513 SourceLine
= SourceSurf
->pvScan0
+ (SourceRect
->top
* SourceSurf
->lDelta
) + 2 * SourceRect
->left
;
514 DestLine
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + 2 * DestRect
->left
;
516 ScaleRectAvg16((PIXEL
*)DestLine
, (PIXEL
*)SourceLine
,
517 SourceRect
->right
-SourceRect
->left
, SourceRect
->bottom
-SourceRect
->top
,
518 DestRect
->right
-DestRect
->left
, DestRect
->bottom
-DestRect
->top
, SourceSurf
->lDelta
, DestSurf
->lDelta
);
530 DbgPrint("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);