2 * DIB Engine conversions Primitives
4 * Copyright 2009 Massimo Del Fedele
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv
);
28 static inline COLORREF
SwapColors(DWORD c
)
30 return ((c
& 0x0000ff) << 16) | (c
& 0x00ff00) | ((c
& 0xff0000) >> 16);
34 static inline DWORD
PlaceField32(BYTE c
, int shift
, int len
)
44 static inline WORD
PlaceField16(BYTE c
, int shift
, int len
)
54 static inline BYTE
GetField32(DWORD dwColor
, int shift
, int len
)
56 dwColor
= dwColor
& (((1 << (len
)) - 1) << shift
);
57 dwColor
= dwColor
<< (32 - (shift
+ len
)) >> 24;
61 /* ----------------------------------------------------------------*/
62 /* CONVERT PRIMITIVES */
63 /* converts (part of) line of any DIB format from/to DIB32_RGB one */
64 BOOL
_DIBDRV_GetLine32_RGB(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
66 DWORD
*dwBuf
= (DWORD
*)buf
;
69 #ifdef DIBDRV_CHECK_RANGES
71 if(line
< 0 || line
>= bmp
->height
)
79 if(startx
+ width
> bmp
->width
)
80 width
= bmp
->width
- startx
;
85 src
= (DWORD
*)((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 4 * startx
);
91 BOOL
_DIBDRV_GetLine32_BITFIELDS(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
93 DWORD
*dwBuf
= (DWORD
*)buf
;
96 #ifdef DIBDRV_CHECK_RANGES
98 if(line
< 0 || line
>= bmp
->height
)
106 if(startx
+ width
> bmp
->width
)
107 width
= bmp
->width
- startx
;
112 src
= (DWORD
*)((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 4 * startx
);
113 for(; width
; width
--)
116 GetField32(*src
, bmp
->redShift
, bmp
->redLen
) << 16 |
117 GetField32(*src
, bmp
->greenShift
, bmp
->greenLen
) << 8 |
118 GetField32(*src
, bmp
->blueShift
, bmp
->blueLen
);
124 BOOL
_DIBDRV_GetLine24(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
126 BYTE
*bBuf
= (BYTE
*)buf
;
129 #ifdef DIBDRV_CHECK_RANGES
131 if(line
< 0 || line
>= bmp
->height
)
139 if(startx
+ width
> bmp
->width
)
140 width
= bmp
->width
- startx
;
145 src
= ((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 3 * startx
);
146 for(; width
; width
--)
156 BOOL
_DIBDRV_GetLine16_RGB(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
158 DWORD
*dwBuf
= (DWORD
*)buf
;
162 #ifdef DIBDRV_CHECK_RANGES
164 if(line
< 0 || line
>= bmp
->height
)
172 if(startx
+ width
> bmp
->width
)
173 width
= bmp
->width
- startx
;
178 src
= (WORD
*)((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 2 * startx
);
179 for(; width
; width
--)
182 /* 0RRR|RRGG|GGGB|BBBB */
183 *dwBuf
++ = ((b
& 0x1f) << 3) | ((b
& 0x3e0) << 6) | ((b
& 0x7c00) << 9);
188 BOOL
_DIBDRV_GetLine16_BITFIELDS(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
190 DWORD
*dwBuf
= (DWORD
*)buf
;
194 #ifdef DIBDRV_CHECK_RANGES
196 if(line
< 0 || line
>= bmp
->height
)
204 if(startx
+ width
> bmp
->width
)
205 width
= bmp
->width
- startx
;
210 src
= (WORD
*)((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 2 * startx
);
211 for(; width
; width
--)
215 *dwBuf
++ =((( b
& bmp
->blueMask
) >> bmp
->blueShift
) << ( 8 - bmp
->blueLen
)) |
216 (((b
& bmp
->greenMask
) >> bmp
->greenShift
) << (16 - bmp
->greenLen
)) |
217 (((b
& bmp
->redMask
) >> bmp
->redShift
) << (24 - bmp
->redLen
));
222 BOOL
_DIBDRV_GetLine8(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
224 DWORD
*dwBuf
= (DWORD
*)buf
;
227 #ifdef DIBDRV_CHECK_RANGES
229 if(line
< 0 || line
>= bmp
->height
)
237 if(startx
+ width
> bmp
->width
)
238 width
= bmp
->width
- startx
;
243 src
= ((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ startx
);
244 for(; width
; width
--)
245 *dwBuf
++ = *((DWORD
*)bmp
->colorTable
+ *src
++);
249 BOOL
_DIBDRV_GetLine4(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
251 DWORD
*dwBuf
= (DWORD
*)buf
;
254 #ifdef DIBDRV_CHECK_RANGES
256 if(line
< 0 || line
>= bmp
->height
)
264 if(startx
+ width
> bmp
->width
)
265 width
= bmp
->width
- startx
;
270 ERR("Called with uninitialized color table\n");
275 src
= ((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ (startx
>> 1));
276 /* if startx is odd, get first nibble */
279 *dwBuf
++ = *((DWORD
*)bmp
->colorTable
+ (*src
++ & 0x0f));
283 /* then gets all full image bytes */
284 for( ; width
> 1 ; width
-= 2)
286 *dwBuf
++ = *((DWORD
*)bmp
->colorTable
+ ((*src
>> 4) & 0x0f));
287 *dwBuf
++ = *((DWORD
*)bmp
->colorTable
+ (*src
++ & 0x0f));
290 /* last nibble, if any */
292 *dwBuf
++ = *((DWORD
*)bmp
->colorTable
+ ((*src
>> 4) & 0x0f));
296 BOOL
_DIBDRV_GetLine1(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
298 DWORD
*dwBuf
= (DWORD
*)buf
;
302 DWORD pixOn
= *((DWORD
*)bmp
->colorTable
+ 1);
303 DWORD pixOff
= *(DWORD
*)bmp
->colorTable
;
305 #ifdef DIBDRV_CHECK_RANGES
307 if(line
< 0 || line
>= bmp
->height
)
315 if(startx
+ width
> bmp
->width
)
316 width
= bmp
->width
- startx
;
321 src
= ((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ (startx
>> 3));
322 /* get first partial byte, if any */
323 startx
= (8 - (startx
& 0x07)) & 0x07;
327 b
= *src
++ << (8 - startx
);
338 /* then gets full next bytes */
339 for( ; width
> 7 ; width
-= 8)
342 for(i
= 0 ; i
< 8 ; i
++)
352 /* last partial byte, if any */
368 BOOL
_DIBDRV_PutLine32_RGB(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
370 DWORD
*dwBuf
= (DWORD
*)buf
;
371 DWORD
*dst
= (DWORD
*)((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 4 * startx
);
372 for(; width
; width
--)
377 BOOL
_DIBDRV_PutLine32_BITFIELDS(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
379 DWORD
*dwBuf
= (DWORD
*)buf
;
380 DWORD
*dst
= (DWORD
*)((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 4 * startx
);
382 for(; width
; width
--)
384 c
= (RGBQUAD
*)dwBuf
++;
386 PlaceField32(c
->rgbRed
, bmp
->redShift
, bmp
->redLen
) |
387 PlaceField32(c
->rgbGreen
, bmp
->greenShift
, bmp
->greenLen
) |
388 PlaceField32(c
->rgbBlue
, bmp
->blueShift
, bmp
->blueLen
);
393 BOOL
_DIBDRV_PutLine24(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
395 DWORD
*dwBuf
= (DWORD
*)buf
;
396 BYTE
*dst
= ((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 3 * startx
);
398 for(; width
; width
--)
401 *dst
++ = c
& 0x000000ff;
402 *dst
++ = (c
& 0x0000ff00) >> 8;
403 *dst
++ = (c
& 0x00ff0000) >> 16;
408 BOOL
_DIBDRV_PutLine16_RGB(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
410 DWORD
*dwBuf
= (DWORD
*)buf
;
411 WORD
*dst
= (WORD
*)((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 2 * startx
);
413 for(; width
; width
--)
417 /* 0RRR|RRGG|GGGB|BBBB */
418 ((c
& 0x000000f8) >> 3) |
419 ((c
& 0x0000f800) >> 6) |
420 ((c
& 0x00f80000) >> 9);
425 BOOL
_DIBDRV_PutLine16_BITFIELDS(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
427 DWORD
*dwBuf
= (DWORD
*)buf
;
428 WORD
*dst
= (WORD
*)((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ 2 * startx
);
431 BYTE bShift
= 8 - bmp
->blueLen
;
432 BYTE gShift
= 16 - bmp
->greenLen
;
433 BYTE rShift
= 24 - bmp
->redLen
;
434 for(; width
; width
--)
438 ((((c
& 0x000000ff) >> bShift
) << bmp
->blueShift
) & bmp
->blueMask
) |
439 ((((c
& 0x0000ff00) >> gShift
) << bmp
->greenShift
) & bmp
->greenMask
) |
440 ((((c
& 0x00ff0000) >> rShift
) << bmp
->redShift
) & bmp
->redMask
);
445 BOOL
_DIBDRV_PutLine8(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
447 DWORD
*dwBuf
= (DWORD
*)buf
;
448 BYTE
*dst
= ((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ startx
);
450 DWORD last_color
= 0xffffffff;
453 for(; width
; width
--)
457 /* slight optimization, as images often have many
458 consecutive pixels with same color */
459 if(last_index
== -1 || c
!= last_color
)
461 last_index
= bmp
->funcs
->ColorToPixel(bmp
, SwapColors(c
));
469 BOOL
_DIBDRV_PutLine4(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
471 DWORD
*dwBuf
= (DWORD
*)buf
;
472 BYTE
*dst
= ((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ (startx
>> 1));
474 DWORD last_color
= 0xffffffff;
477 /* if startx is odd, put first nibble */
482 last_index
= bmp
->funcs
->ColorToPixel(bmp
, SwapColors(c
));
484 *dst
= (*dst
& 0xf0) | last_index
;
489 /* then gets all full image bytes */
490 for( ; width
> 1 ; width
-= 2)
494 /* slight optimization, as images often have many
495 consecutive pixels with same color */
496 if(last_index
== -1 || c
!= last_color
)
498 last_index
= bmp
->funcs
->ColorToPixel(bmp
, SwapColors(c
));
501 *dst
= last_index
<< 4;
505 /* slight optimization, as images often have many
506 consecutive pixels with same color */
507 if(last_index
== -1 || c
!= last_color
)
509 last_index
= bmp
->funcs
->ColorToPixel(bmp
, SwapColors(c
));
512 *dst
++ |= last_index
;
515 /* last nibble, if any */
520 /* slight optimization, as images often have many
521 consecutive pixels with same color */
522 if(last_index
== -1 || c
!= last_color
)
523 last_index
= bmp
->funcs
->ColorToPixel(bmp
, SwapColors(c
));
524 *dst
= (*dst
& 0x0f) | (last_index
<< 4);
529 BOOL
_DIBDRV_PutLine1(const DIBDRVBITMAP
*bmp
, INT line
, INT startx
, int width
, void *buf
)
531 DWORD
*dwBuf
= (DWORD
*)buf
;
532 BYTE
*dst
= ((BYTE
*)bmp
->bits
+ line
* bmp
->stride
+ (startx
>> 3));
537 /* get foreground color */
538 DWORD back
= *(DWORD
*)bmp
->colorTable
& 0x00ffffff;
539 DWORD fore
= *((DWORD
*)bmp
->colorTable
+ 1) & 0x00ffffff;
541 /* put first partial byte, if any */
543 mask
= 0x80 >> startx
;
544 startx
= (8 - startx
) & 0x07;
551 c
= *dwBuf
++ & 0x00ffffff;
556 else if(c
== 0x00ffffff)
565 /* then puts full next bytes */
566 for( ; width
> 7 ; width
-= 8)
570 for(i
= 0 ; i
< 8 ; i
++)
572 c
= *dwBuf
++ & 0x00ffffff;
573 if(c
== fore
|| (c
== 0x00ffffff && c
!= back
))
580 /* last partial byte, if any */
587 c
= *dwBuf
++ & 0x00ffffff;
592 else if(c
== 0x00ffffff)