2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "gdi_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
34 /***********************************************************************
35 * DIB_GetDIBWidthBytes
37 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
38 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
40 int DIB_GetDIBWidthBytes( int width
, int depth
)
46 case 1: words
= (width
+ 31) / 32; break;
47 case 4: words
= (width
+ 7) / 8; break;
48 case 8: words
= (width
+ 3) / 4; break;
50 case 16: words
= (width
+ 1) / 2; break;
51 case 24: words
= (width
* 3 + 3)/4; break;
54 WARN("(%d): Unsupported depth\n", depth
);
62 /***********************************************************************
63 * DIB_GetDIBImageBytes
65 * Return the number of bytes used to hold the image in a DIB bitmap.
67 int DIB_GetDIBImageBytes( int width
, int height
, int depth
)
69 return DIB_GetDIBWidthBytes( width
, depth
) * abs( height
);
73 /***********************************************************************
76 * Return the size of the bitmap info structure including color table.
78 int DIB_BitmapInfoSize( const BITMAPINFO
* info
, WORD coloruse
)
82 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
84 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)info
;
85 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
86 return sizeof(BITMAPCOREHEADER
) + colors
*
87 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
89 else /* assume BITMAPINFOHEADER */
91 colors
= info
->bmiHeader
.biClrUsed
;
92 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
93 colors
= 1 << info
->bmiHeader
.biBitCount
;
94 return sizeof(BITMAPINFOHEADER
) + colors
*
95 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
100 /***********************************************************************
103 * Get the info from a bitmap header.
104 * Return 1 for INFOHEADER, 0 for COREHEADER,
105 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
107 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER
*header
, DWORD
*width
,
108 int *height
, WORD
*bpp
, WORD
*compr
)
110 if (header
->biSize
== sizeof(BITMAPINFOHEADER
))
112 *width
= header
->biWidth
;
113 *height
= header
->biHeight
;
114 *bpp
= header
->biBitCount
;
115 *compr
= header
->biCompression
;
118 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
120 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)header
;
121 *width
= core
->bcWidth
;
122 *height
= core
->bcHeight
;
123 *bpp
= core
->bcBitCount
;
127 if (header
->biSize
== sizeof(BITMAPV4HEADER
))
129 BITMAPV4HEADER
*v4hdr
= (BITMAPV4HEADER
*)header
;
130 *width
= v4hdr
->bV4Width
;
131 *height
= v4hdr
->bV4Height
;
132 *bpp
= v4hdr
->bV4BitCount
;
133 *compr
= v4hdr
->bV4V4Compression
;
136 if (header
->biSize
== sizeof(BITMAPV5HEADER
))
138 BITMAPV5HEADER
*v5hdr
= (BITMAPV5HEADER
*)header
;
139 *width
= v5hdr
->bV5Width
;
140 *height
= v5hdr
->bV5Height
;
141 *bpp
= v5hdr
->bV5BitCount
;
142 *compr
= v5hdr
->bV5Compression
;
145 ERR("(%ld): unknown/wrong size for header\n", header
->biSize
);
150 /***********************************************************************
151 * StretchDIBits (GDI32.@)
153 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
,
154 INT heightDst
, INT xSrc
, INT ySrc
, INT widthSrc
,
155 INT heightSrc
, const void *bits
,
156 const BITMAPINFO
*info
, UINT wUsage
, DWORD dwRop
)
163 dc
= DC_GetDCUpdate( hdc
);
164 if(!dc
) return FALSE
;
166 if(dc
->funcs
->pStretchDIBits
)
168 heightSrc
= dc
->funcs
->pStretchDIBits(dc
->physDev
, xDst
, yDst
, widthDst
,
169 heightDst
, xSrc
, ySrc
, widthSrc
,
170 heightSrc
, bits
, info
, wUsage
, dwRop
);
171 GDI_ReleaseObj( hdc
);
173 else /* use StretchBlt */
175 HBITMAP hBitmap
, hOldBitmap
;
176 HPALETTE hpal
= NULL
;
179 GDI_ReleaseObj( hdc
);
180 hdcMem
= CreateCompatibleDC( hdc
);
181 hBitmap
= CreateCompatibleBitmap(hdc
, info
->bmiHeader
.biWidth
,
182 info
->bmiHeader
.biHeight
);
183 hOldBitmap
= SelectObject( hdcMem
, hBitmap
);
184 if(wUsage
== DIB_PAL_COLORS
)
186 hpal
= GetCurrentObject(hdc
, OBJ_PAL
);
187 hpal
= SelectPalette(hdcMem
, hpal
, FALSE
);
190 if (info
->bmiHeader
.biCompression
== BI_RLE4
||
191 info
->bmiHeader
.biCompression
== BI_RLE8
) {
193 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
194 * contain all the rectangle described in bmiHeader, but only part of it.
195 * This mean that those undescribed pixels must be left untouched.
196 * So, we first copy on a memory bitmap the current content of the
197 * destination rectangle, blit the DIB bits on top of it - hence leaving
198 * the gaps untouched -, and blitting the rectangle back.
199 * This insure that gaps are untouched on the destination rectangle
200 * Not doing so leads to trashed images (the gaps contain what was on the
201 * memory bitmap => generally black or garbage)
202 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
203 * another speed vs correctness issue. Anyway, if speed is needed, then the
204 * pStretchDIBits function shall be implemented.
208 /* copy existing bitmap from destination dc */
209 StretchBlt( hdcMem
, xSrc
, abs(info
->bmiHeader
.biHeight
) - heightSrc
- ySrc
,
210 widthSrc
, heightSrc
, hdc
, xDst
, yDst
, widthDst
, heightDst
,
214 SetDIBits(hdcMem
, hBitmap
, 0, info
->bmiHeader
.biHeight
, bits
,
217 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
218 left (negative biHeight) */
219 StretchBlt( hdc
, xDst
, yDst
, widthDst
, heightDst
,
220 hdcMem
, xSrc
, abs(info
->bmiHeader
.biHeight
) - heightSrc
- ySrc
,
221 widthSrc
, heightSrc
, dwRop
);
223 SelectPalette(hdcMem
, hpal
, FALSE
);
224 SelectObject( hdcMem
, hOldBitmap
);
226 DeleteObject( hBitmap
);
232 /******************************************************************************
233 * SetDIBits [GDI32.@]
235 * Sets pixels in a bitmap using colors from DIB.
238 * hdc [I] Handle to device context
239 * hbitmap [I] Handle to bitmap
240 * startscan [I] Starting scan line
241 * lines [I] Number of scan lines
242 * bits [I] Array of bitmap bits
243 * info [I] Address of structure with data
244 * coloruse [I] Type of color indexes to use
247 * Success: Number of scan lines copied
250 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
251 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
258 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
))) return 0;
260 if (!(dc
= DC_GetDCUpdate( hdc
)))
262 if (coloruse
== DIB_RGB_COLORS
) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
263 GDI_ReleaseObj( hbitmap
);
267 if (!bitmap
->funcs
&& !BITMAP_SetOwnerDC( hbitmap
, dc
)) goto done
;
269 if (bitmap
->funcs
&& bitmap
->funcs
->pSetDIBits
)
270 result
= bitmap
->funcs
->pSetDIBits( dc
->physDev
, hbitmap
, startscan
, lines
,
271 bits
, info
, coloruse
);
276 GDI_ReleaseObj( hdc
);
277 GDI_ReleaseObj( hbitmap
);
282 /***********************************************************************
283 * SetDIBitsToDevice (GDI32.@)
285 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
286 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
287 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
293 if (!(dc
= DC_GetDCUpdate( hdc
))) return 0;
295 if(dc
->funcs
->pSetDIBitsToDevice
)
296 ret
= dc
->funcs
->pSetDIBitsToDevice( dc
->physDev
, xDest
, yDest
, cx
, cy
, xSrc
,
297 ySrc
, startscan
, lines
, bits
,
300 FIXME("unimplemented on hdc %p\n", hdc
);
304 GDI_ReleaseObj( hdc
);
308 /***********************************************************************
309 * SetDIBColorTable (GDI32.@)
311 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
316 if (!(dc
= DC_GetDCUpdate( hdc
))) return 0;
318 if (dc
->funcs
->pSetDIBColorTable
)
319 result
= dc
->funcs
->pSetDIBColorTable(dc
->physDev
, startpos
, entries
, colors
);
321 GDI_ReleaseObj( hdc
);
326 /***********************************************************************
327 * GetDIBColorTable (GDI32.@)
329 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
334 if (!(dc
= DC_GetDCUpdate( hdc
))) return 0;
336 if (dc
->funcs
->pGetDIBColorTable
)
337 result
= dc
->funcs
->pGetDIBColorTable(dc
->physDev
, startpos
, entries
, colors
);
339 GDI_ReleaseObj( hdc
);
343 /* FIXME the following two structs should be combined with __sysPalTemplate in
344 objects/color.c - this should happen after de-X11-ing both of these
346 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
349 static RGBQUAD EGAColors
[16] = {
350 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
351 { 0x00, 0x00, 0x00, 0x00 },
352 { 0x00, 0x00, 0x80, 0x00 },
353 { 0x00, 0x80, 0x00, 0x00 },
354 { 0x00, 0x80, 0x80, 0x00 },
355 { 0x80, 0x00, 0x00, 0x00 },
356 { 0x80, 0x00, 0x80, 0x00 },
357 { 0x80, 0x80, 0x00, 0x00 },
358 { 0x80, 0x80, 0x80, 0x00 },
359 { 0xc0, 0xc0, 0xc0, 0x00 },
360 { 0x00, 0x00, 0xff, 0x00 },
361 { 0x00, 0xff, 0x00, 0x00 },
362 { 0x00, 0xff, 0xff, 0x00 },
363 { 0xff, 0x00, 0x00, 0x00 },
364 { 0xff, 0x00, 0xff, 0x00 },
365 { 0xff, 0xff, 0x00, 0x00 },
366 { 0xff, 0xff, 0xff, 0x00 }
370 static RGBQUAD DefLogPalette
[20] = { /* Copy of Default Logical Palette */
371 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
372 { 0x00, 0x00, 0x00, 0x00 },
373 { 0x00, 0x00, 0x80, 0x00 },
374 { 0x00, 0x80, 0x00, 0x00 },
375 { 0x00, 0x80, 0x80, 0x00 },
376 { 0x80, 0x00, 0x00, 0x00 },
377 { 0x80, 0x00, 0x80, 0x00 },
378 { 0x80, 0x80, 0x00, 0x00 },
379 { 0xc0, 0xc0, 0xc0, 0x00 },
380 { 0xc0, 0xdc, 0xc0, 0x00 },
381 { 0xf0, 0xca, 0xa6, 0x00 },
382 { 0xf0, 0xfb, 0xff, 0x00 },
383 { 0xa4, 0xa0, 0xa0, 0x00 },
384 { 0x80, 0x80, 0x80, 0x00 },
385 { 0x00, 0x00, 0xf0, 0x00 },
386 { 0x00, 0xff, 0x00, 0x00 },
387 { 0x00, 0xff, 0xff, 0x00 },
388 { 0xff, 0x00, 0x00, 0x00 },
389 { 0xff, 0x00, 0xff, 0x00 },
390 { 0xff, 0xff, 0x00, 0x00 },
391 { 0xff, 0xff, 0xff, 0x00 }
395 /******************************************************************************
396 * GetDIBits [GDI32.@]
398 * Retrieves bits of bitmap and copies to buffer.
401 * Success: Number of scan lines copied from bitmap
404 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
406 INT WINAPI
GetDIBits(
407 HDC hdc
, /* [in] Handle to device context */
408 HBITMAP hbitmap
, /* [in] Handle to bitmap */
409 UINT startscan
, /* [in] First scan line to set in dest bitmap */
410 UINT lines
, /* [in] Number of scan lines to copy */
411 LPVOID bits
, /* [out] Address of array for bitmap bits */
412 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
413 UINT coloruse
) /* [in] RGB or palette index */
421 memdc
= CreateCompatibleDC(hdc
);
422 if (!(dc
= DC_GetDCUpdate( hdc
)))
427 if (!(bmp
= (BITMAPOBJ
*)GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
429 GDI_ReleaseObj( hdc
);
434 /* Transfer color info */
436 if (info
->bmiHeader
.biBitCount
<= 8 && info
->bmiHeader
.biBitCount
> 0 ) {
438 info
->bmiHeader
.biClrUsed
= 0;
440 /* If the bitmap object already has a dib section at the
441 same color depth then get the color map from it */
442 if (bmp
->dib
&& bmp
->dib
->dsBm
.bmBitsPixel
== info
->bmiHeader
.biBitCount
) {
443 if(coloruse
== DIB_RGB_COLORS
) {
445 oldbm
= SelectObject(memdc
, hbitmap
);
446 GetDIBColorTable(memdc
, 0, 1 << info
->bmiHeader
.biBitCount
, info
->bmiColors
);
447 SelectObject(memdc
, oldbm
);
450 WORD
*index
= (WORD
*)info
->bmiColors
;
452 for(i
= 0; i
< 1 << info
->bmiHeader
.biBitCount
; i
++, index
++)
457 if(info
->bmiHeader
.biBitCount
>= bmp
->bitmap
.bmBitsPixel
) {
458 /* Generate the color map from the selected palette */
459 PALETTEENTRY
* palEntry
;
460 PALETTEOBJ
* palette
;
461 if (!(palette
= (PALETTEOBJ
*)GDI_GetObjPtr( dc
->hPalette
, PALETTE_MAGIC
))) {
462 GDI_ReleaseObj( hdc
);
463 GDI_ReleaseObj( hbitmap
);
467 palEntry
= palette
->logpalette
.palPalEntry
;
468 for (i
= 0; i
< (1 << bmp
->bitmap
.bmBitsPixel
); i
++, palEntry
++) {
469 if (coloruse
== DIB_RGB_COLORS
) {
470 info
->bmiColors
[i
].rgbRed
= palEntry
->peRed
;
471 info
->bmiColors
[i
].rgbGreen
= palEntry
->peGreen
;
472 info
->bmiColors
[i
].rgbBlue
= palEntry
->peBlue
;
473 info
->bmiColors
[i
].rgbReserved
= 0;
475 else ((WORD
*)info
->bmiColors
)[i
] = (WORD
)i
;
477 GDI_ReleaseObj( dc
->hPalette
);
479 switch (info
->bmiHeader
.biBitCount
) {
481 info
->bmiColors
[0].rgbRed
= info
->bmiColors
[0].rgbGreen
=
482 info
->bmiColors
[0].rgbBlue
= 0;
483 info
->bmiColors
[0].rgbReserved
= 0;
484 info
->bmiColors
[1].rgbRed
= info
->bmiColors
[1].rgbGreen
=
485 info
->bmiColors
[1].rgbBlue
= 0xff;
486 info
->bmiColors
[1].rgbReserved
= 0;
490 memcpy(info
->bmiColors
, EGAColors
, sizeof(EGAColors
));
498 memcpy(info
->bmiColors
, DefLogPalette
,
499 10 * sizeof(RGBQUAD
));
500 memcpy(info
->bmiColors
+ 246, DefLogPalette
+ 10,
501 10 * sizeof(RGBQUAD
));
502 color
= info
->bmiColors
+ 10;
503 for(r
= 0; r
<= 5; r
++) /* FIXME */
504 for(g
= 0; g
<= 5; g
++)
505 for(b
= 0; b
<= 5; b
++) {
506 color
->rgbRed
= (r
* 0xff) / 5;
507 color
->rgbGreen
= (g
* 0xff) / 5;
508 color
->rgbBlue
= (b
* 0xff) / 5;
509 color
->rgbReserved
= 0;
520 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
521 if(bmp
->dib
&& bmp
->dib
->dsBm
.bmBitsPixel
>= 15 && info
->bmiHeader
.biBitCount
>= 15)
523 /*FIXME: Only RGB dibs supported for now */
524 unsigned int srcwidth
= bmp
->dib
->dsBm
.bmWidth
, srcwidthb
= bmp
->dib
->dsBm
.bmWidthBytes
;
525 int dstwidthb
= DIB_GetDIBWidthBytes( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
526 LPBYTE dbits
= bits
, sbits
= (LPBYTE
) bmp
->dib
->dsBm
.bmBits
+ (startscan
* srcwidthb
);
529 if ((info
->bmiHeader
.biHeight
< 0) ^ (bmp
->dib
->dsBmih
.biHeight
< 0))
531 dbits
= (LPBYTE
)bits
+ (dstwidthb
* (lines
-1));
532 dstwidthb
= -dstwidthb
;
535 switch( info
->bmiHeader
.biBitCount
) {
538 case 16: /* 16 bpp dstDIB */
540 LPWORD dstbits
= (LPWORD
)dbits
;
541 WORD rmask
= 0x7c00, gmask
= 0x03e0, bmask
= 0x001f;
543 /* FIXME: BI_BITFIELDS not supported yet */
545 switch(bmp
->dib
->dsBm
.bmBitsPixel
) {
547 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
549 /* FIXME: BI_BITFIELDS not supported yet */
550 for (y
= 0; y
< lines
; y
++, dbits
+=dstwidthb
, sbits
+=srcwidthb
)
551 memcpy(dbits
, sbits
, srcwidthb
);
555 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
557 LPBYTE srcbits
= sbits
;
559 for( y
= 0; y
< lines
; y
++) {
560 for( x
= 0; x
< srcwidth
; x
++, srcbits
+= 3)
561 *dstbits
++ = ((srcbits
[0] >> 3) & bmask
) |
562 (((WORD
)srcbits
[1] << 2) & gmask
) |
563 (((WORD
)srcbits
[2] << 7) & rmask
);
565 dstbits
= (LPWORD
)(dbits
+=dstwidthb
);
566 srcbits
= (sbits
+= srcwidthb
);
571 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
573 LPDWORD srcbits
= (LPDWORD
)sbits
;
576 for( y
= 0; y
< lines
; y
++) {
577 for( x
= 0; x
< srcwidth
; x
++ ) {
579 *dstbits
++ = (WORD
)(((val
>> 3) & bmask
) | ((val
>> 6) & gmask
) |
580 ((val
>> 9) & rmask
));
582 dstbits
= (LPWORD
)(dbits
+=dstwidthb
);
583 srcbits
= (LPDWORD
)(sbits
+=srcwidthb
);
588 default: /* ? bit bmp -> 16 bit DIB */
589 FIXME("15/16 bit DIB %d bit bitmap\n",
590 bmp
->bitmap
.bmBitsPixel
);
596 case 24: /* 24 bpp dstDIB */
598 LPBYTE dstbits
= dbits
;
600 switch(bmp
->dib
->dsBm
.bmBitsPixel
) {
602 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
604 LPWORD srcbits
= (LPWORD
)sbits
;
607 /* FIXME: BI_BITFIELDS not supported yet */
608 for( y
= 0; y
< lines
; y
++) {
609 for( x
= 0; x
< srcwidth
; x
++ ) {
611 *dstbits
++ = (BYTE
)(((val
<< 3) & 0xf8) | ((val
>> 2) & 0x07));
612 *dstbits
++ = (BYTE
)(((val
>> 2) & 0xf8) | ((val
>> 7) & 0x07));
613 *dstbits
++ = (BYTE
)(((val
>> 7) & 0xf8) | ((val
>> 12) & 0x07));
615 dstbits
= (LPBYTE
)(dbits
+=dstwidthb
);
616 srcbits
= (LPWORD
)(sbits
+=srcwidthb
);
621 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
623 for (y
= 0; y
< lines
; y
++, dbits
+=dstwidthb
, sbits
+=srcwidthb
)
624 memcpy(dbits
, sbits
, srcwidthb
);
628 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
630 LPBYTE srcbits
= (LPBYTE
)sbits
;
632 for( y
= 0; y
< lines
; y
++) {
633 for( x
= 0; x
< srcwidth
; x
++, srcbits
++ ) {
634 *dstbits
++ = *srcbits
++;
635 *dstbits
++ = *srcbits
++;
636 *dstbits
++ = *srcbits
++;
638 dstbits
=(LPBYTE
)(dbits
+=dstwidthb
);
639 srcbits
= (LPBYTE
)(sbits
+=srcwidthb
);
644 default: /* ? bit bmp -> 24 bit DIB */
645 FIXME("24 bit DIB %d bit bitmap\n",
646 bmp
->bitmap
.bmBitsPixel
);
652 case 32: /* 32 bpp dstDIB */
654 LPDWORD dstbits
= (LPDWORD
)dbits
;
656 /* FIXME: BI_BITFIELDS not supported yet */
658 switch(bmp
->dib
->dsBm
.bmBitsPixel
) {
659 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
661 LPWORD srcbits
= (LPWORD
)sbits
;
664 /* FIXME: BI_BITFIELDS not supported yet */
665 for( y
= 0; y
< lines
; y
++) {
666 for( x
= 0; x
< srcwidth
; x
++ ) {
667 val
= (DWORD
)*srcbits
++;
668 *dstbits
++ = ((val
<< 3) & 0xf8) | ((val
>> 2) & 0x07) |
669 ((val
<< 6) & 0xf800) | ((val
<< 1) & 0x0700) |
670 ((val
<< 9) & 0xf80000) | ((val
<< 4) & 0x070000);
672 dstbits
=(LPDWORD
)(dbits
+=dstwidthb
);
673 srcbits
=(LPWORD
)(sbits
+=srcwidthb
);
678 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
680 LPBYTE srcbits
= sbits
;
682 for( y
= 0; y
< lines
; y
++) {
683 for( x
= 0; x
< srcwidth
; x
++, srcbits
+=3 )
684 *dstbits
++ = ((DWORD
)*srcbits
) & 0x00ffffff;
685 dstbits
=(LPDWORD
)(dbits
+=dstwidthb
);
686 srcbits
=(sbits
+=srcwidthb
);
691 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
693 /* FIXME: BI_BITFIELDS not supported yet */
694 for (y
= 0; y
< lines
; y
++, dbits
+=dstwidthb
, sbits
+=srcwidthb
)
695 memcpy(dbits
, sbits
, srcwidthb
);
699 default: /* ? bit bmp -> 32 bit DIB */
700 FIXME("32 bit DIB %d bit bitmap\n",
701 bmp
->bitmap
.bmBitsPixel
);
707 default: /* ? bit DIB */
708 FIXME("Unsupported DIB depth %d\n", info
->bmiHeader
.biBitCount
);
712 /* Otherwise, get bits from the XImage */
715 if (!bmp
->funcs
&& !BITMAP_SetOwnerDC( hbitmap
, dc
)) lines
= 0;
718 if (bmp
->funcs
&& bmp
->funcs
->pGetDIBits
)
719 lines
= bmp
->funcs
->pGetDIBits( dc
->physDev
, hbitmap
, startscan
,
720 lines
, bits
, info
, coloruse
);
722 lines
= 0; /* FIXME: should copy from bmp->bitmap.bmBits */
726 else if( info
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) )
728 /* fill in struct members */
730 if( info
->bmiHeader
.biBitCount
== 0)
732 info
->bmiHeader
.biWidth
= bmp
->bitmap
.bmWidth
;
733 info
->bmiHeader
.biHeight
= bmp
->bitmap
.bmHeight
;
734 info
->bmiHeader
.biPlanes
= 1;
735 info
->bmiHeader
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
736 info
->bmiHeader
.biSizeImage
=
737 DIB_GetDIBImageBytes( bmp
->bitmap
.bmWidth
,
738 bmp
->bitmap
.bmHeight
,
739 bmp
->bitmap
.bmBitsPixel
);
740 info
->bmiHeader
.biCompression
= 0;
744 info
->bmiHeader
.biSizeImage
= DIB_GetDIBImageBytes(
745 info
->bmiHeader
.biWidth
,
746 info
->bmiHeader
.biHeight
,
747 info
->bmiHeader
.biBitCount
);
749 lines
= info
->bmiHeader
.biHeight
;
752 TRACE("biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
753 info
->bmiHeader
.biSizeImage
, info
->bmiHeader
.biWidth
,
754 info
->bmiHeader
.biHeight
);
756 GDI_ReleaseObj( hdc
);
757 GDI_ReleaseObj( hbitmap
);
763 /***********************************************************************
764 * CreateDIBitmap (GDI32.@)
766 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
767 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
778 if (DIB_GetBitmapInfo( header
, &width
, &height
, &bpp
, &compr
) == -1) return 0;
779 if (height
< 0) height
= -height
;
781 /* Check if we should create a monochrome or color bitmap. */
782 /* We create a monochrome bitmap only if it has exactly 2 */
783 /* colors, which are black followed by white, nothing else. */
784 /* In all other cases, we create a color bitmap. */
786 if (bpp
!= 1) fColor
= TRUE
;
787 else if ((coloruse
!= DIB_RGB_COLORS
) || !data
) fColor
= FALSE
;
790 if (data
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
792 RGBQUAD
*rgb
= data
->bmiColors
;
793 DWORD col
= RGB( rgb
->rgbRed
, rgb
->rgbGreen
, rgb
->rgbBlue
);
795 /* Check if the first color of the colormap is black */
796 if ((col
== RGB(0,0,0)))
799 col
= RGB( rgb
->rgbRed
, rgb
->rgbGreen
, rgb
->rgbBlue
);
800 /* If the second color is white, create a monochrome bitmap */
801 fColor
= (col
!= RGB(0xff,0xff,0xff));
803 /* Note : If the first color of the colormap is white
804 followed by black, we have to create a color bitmap.
805 If we don't the white will be displayed in black later on!*/
808 else if (data
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
810 RGBTRIPLE
*rgb
= ((BITMAPCOREINFO
*)data
)->bmciColors
;
811 DWORD col
= RGB( rgb
->rgbtRed
, rgb
->rgbtGreen
, rgb
->rgbtBlue
);
812 if ((col
== RGB(0,0,0)))
815 col
= RGB( rgb
->rgbtRed
, rgb
->rgbtGreen
, rgb
->rgbtBlue
);
816 fColor
= (col
!= RGB(0xff,0xff,0xff));
820 else if (data
->bmiHeader
.biSize
== sizeof(BITMAPV4HEADER
))
821 { /* FIXME: correct ? */
822 RGBQUAD
*rgb
= data
->bmiColors
;
823 DWORD col
= RGB( rgb
->rgbRed
, rgb
->rgbGreen
, rgb
->rgbBlue
);
825 /* Check if the first color of the colormap is black */
826 if ((col
== RGB(0,0,0)))
829 col
= RGB( rgb
->rgbRed
, rgb
->rgbGreen
, rgb
->rgbBlue
);
830 /* If the second color is white, create a monochrome bitmap */
831 fColor
= (col
!= RGB(0xff,0xff,0xff));
833 /* Note : If the first color of the colormap is white
834 followed by black, we have to create a color bitmap.
835 If we don't the white will be displayed in black later on!*/
840 ERR("(%ld): wrong/unknown size for data\n",
841 data
->bmiHeader
.biSize
);
846 /* Now create the bitmap */
848 if (!(dc
= DC_GetDCPtr( hdc
))) return 0;
851 handle
= CreateBitmap( width
, height
, GetDeviceCaps( hdc
, PLANES
),
852 GetDeviceCaps( hdc
, BITSPIXEL
), NULL
);
853 else handle
= CreateBitmap( width
, height
, 1, 1, NULL
);
857 if (init
== CBM_INIT
) SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
);
858 else if (!BITMAP_SetOwnerDC( handle
, dc
))
860 DeleteObject( handle
);
865 GDI_ReleaseObj( hdc
);
869 /***********************************************************************
870 * CreateDIBSection (GDI.489)
872 HBITMAP16 WINAPI
CreateDIBSection16 (HDC16 hdc
, const BITMAPINFO
*bmi
, UINT16 usage
,
873 SEGPTR
*bits16
, HANDLE section
, DWORD offset
)
878 hbitmap
= CreateDIBSection( HDC_32(hdc
), bmi
, usage
, &bits32
, section
, offset
);
881 BITMAPOBJ
*bmp
= (BITMAPOBJ
*) GDI_GetObjPtr(hbitmap
, BITMAP_MAGIC
);
882 if (bmp
&& bmp
->dib
&& bits32
)
884 const BITMAPINFOHEADER
*bi
= &bmi
->bmiHeader
;
885 INT height
= bi
->biHeight
>= 0 ? bi
->biHeight
: -bi
->biHeight
;
886 INT width_bytes
= DIB_GetDIBWidthBytes(bi
->biWidth
, bi
->biBitCount
);
887 INT size
= (bi
->biSizeImage
&& bi
->biCompression
!= BI_RGB
) ?
888 bi
->biSizeImage
: width_bytes
* height
;
890 /* calculate number of sel's needed for size with 64K steps */
891 WORD count
= (size
+ 0xffff) / 0x10000;
892 WORD sel
= AllocSelectorArray16(count
);
895 for (i
= 0; i
< count
; i
++)
897 SetSelectorBase(sel
+ (i
<< __AHSHIFT
), (DWORD
)bits32
+ i
* 0x10000);
898 SetSelectorLimit16(sel
+ (i
<< __AHSHIFT
), size
- 1); /* yep, limit is correct */
901 bmp
->segptr_bits
= MAKESEGPTR( sel
, 0 );
902 if (bits16
) *bits16
= bmp
->segptr_bits
;
904 if (bmp
) GDI_ReleaseObj( hbitmap
);
906 return HBITMAP_16(hbitmap
);
909 /***********************************************************************
910 * DIB_CreateDIBSection
912 HBITMAP
DIB_CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
913 VOID
**bits
, HANDLE section
,
914 DWORD offset
, DWORD ovr_pitch
)
918 BOOL bDesktopDC
= FALSE
;
920 /* If the reference hdc is null, take the desktop dc */
923 hdc
= CreateCompatibleDC(0);
927 if ((dc
= DC_GetDCPtr( hdc
)))
929 if(dc
->funcs
->pCreateDIBSection
)
930 hbitmap
= dc
->funcs
->pCreateDIBSection(dc
->physDev
, bmi
, usage
, bits
, section
, offset
, ovr_pitch
);
940 /***********************************************************************
941 * CreateDIBSection (GDI32.@)
943 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, CONST BITMAPINFO
*bmi
, UINT usage
,
944 VOID
**bits
, HANDLE section
,
947 return DIB_CreateDIBSection(hdc
, bmi
, usage
, bits
, section
, offset
, 0);