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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize),
32 or use the internal function DIB_GetBitmapInfo.
35 * The palettes are stored in different formats:
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
46 If biCompression is BI_BITFIELDS, the color masks are at the same position
47 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48 the new headers have structure members for the masks.
51 * You should never access the color table using the bmiColors member,
52 because the passed structure may have one of the extended headers
53 mentioned above. Use this to calculate the location:
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
60 Search for "Bitmap Structures" in MSDN
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
76 /***********************************************************************
79 * Return the size of the bitmap info structure including color table.
81 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
83 unsigned int colors
, size
, masks
= 0;
85 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
87 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
88 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
89 return sizeof(BITMAPCOREHEADER
) + colors
*
90 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
92 else /* assume BITMAPINFOHEADER */
94 colors
= info
->bmiHeader
.biClrUsed
;
95 if (colors
> 256) colors
= 256;
96 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
97 colors
= 1 << info
->bmiHeader
.biBitCount
;
98 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
99 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
100 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
105 /***********************************************************************
108 * Get the info from a bitmap header.
109 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
111 int DIB_GetBitmapInfo( const BITMAPINFOHEADER
*header
, LONG
*width
,
112 LONG
*height
, WORD
*planes
, WORD
*bpp
, DWORD
*compr
, DWORD
*size
)
114 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
116 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)header
;
117 *width
= core
->bcWidth
;
118 *height
= core
->bcHeight
;
119 *planes
= core
->bcPlanes
;
120 *bpp
= core
->bcBitCount
;
125 if (header
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
127 *width
= header
->biWidth
;
128 *height
= header
->biHeight
;
129 *planes
= header
->biPlanes
;
130 *bpp
= header
->biBitCount
;
131 *compr
= header
->biCompression
;
132 *size
= header
->biSizeImage
;
135 ERR("(%d): unknown/wrong size for header\n", header
->biSize
);
139 /*******************************************************************************************
140 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
142 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
, UINT coloruse
)
147 void *src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
149 int bitmap_type
= DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
, &planes
, &bpp
, &compr
, &size
);
151 if (bitmap_type
== -1) return FALSE
;
153 colors
= (bpp
> 8) ? 0 : 1 << bpp
;
155 if (bitmap_type
== 1)
157 dst
->bmiHeader
= info
->bmiHeader
;
158 dst
->bmiHeader
.biSize
= sizeof(dst
->bmiHeader
);
160 if (info
->bmiHeader
.biClrUsed
) colors
= info
->bmiHeader
.biClrUsed
;
162 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
163 /* bitfields are always at bmiColors even in larger structures */
164 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
169 if (coloruse
== DIB_PAL_COLORS
)
170 size
= colors
* sizeof(WORD
);
172 size
= colors
* sizeof(RGBQUAD
);
173 memcpy( dst
->bmiColors
, src_colors
, size
);
178 dst
->bmiHeader
.biSize
= sizeof(dst
->bmiHeader
);
179 dst
->bmiHeader
.biWidth
= width
;
180 dst
->bmiHeader
.biHeight
= height
;
181 dst
->bmiHeader
.biPlanes
= planes
;
182 dst
->bmiHeader
.biBitCount
= bpp
;
183 dst
->bmiHeader
.biCompression
= compr
;
184 dst
->bmiHeader
.biSizeImage
= size
;
185 dst
->bmiHeader
.biXPelsPerMeter
= 0;
186 dst
->bmiHeader
.biYPelsPerMeter
= 0;
187 dst
->bmiHeader
.biClrUsed
= 0;
188 dst
->bmiHeader
.biClrImportant
= 0;
192 if (coloruse
== DIB_PAL_COLORS
)
193 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
197 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
198 for (i
= 0; i
< colors
; i
++)
200 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
201 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
202 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
203 dst
->bmiColors
[i
].rgbReserved
= 0;
212 static int fill_color_table_from_palette( BITMAPINFO
*info
, DC
*dc
)
214 PALETTEENTRY palEntry
[256];
215 int i
, colors
= (info
->bmiHeader
.biBitCount
> 8) ? 0 : 1 << info
->bmiHeader
.biBitCount
;
217 if (info
->bmiHeader
.biClrUsed
) colors
= info
->bmiHeader
.biClrUsed
;
219 if (!colors
) return 0;
221 memset( palEntry
, 0, sizeof(palEntry
) );
222 if (!GetPaletteEntries( dc
->hPalette
, 0, colors
, palEntry
))
225 for (i
= 0; i
< colors
; i
++)
227 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
228 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
229 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
230 info
->bmiColors
[i
].rgbReserved
= 0;
236 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
237 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
238 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
239 const BITMAPINFO
*info
, UINT coloruse
, DWORD rop
)
241 DC
*dc
= get_nulldrv_dc( dev
);
249 /* make sure we have a real implementation for StretchBlt and SetDIBits */
250 if (GET_DC_PHYSDEV( dc
, pStretchBlt
) == dev
|| GET_DC_PHYSDEV( dc
, pSetDIBits
) == dev
)
253 if (DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
, &planes
, &bpp
, &compr
, &size
) == -1)
256 if (width
< 0) return 0;
258 if (xSrc
== 0 && ySrc
== 0 && widthDst
== widthSrc
&& heightDst
== heightSrc
&&
259 info
->bmiHeader
.biCompression
== BI_RGB
)
261 /* Windows appears to have a fast case optimization
262 * that uses the wrong origin for top-down DIBs */
263 if (height
< 0 && heightSrc
< abs(height
)) ySrc
= abs(height
) - heightSrc
;
265 if (xDst
== 0 && yDst
== 0 && info
->bmiHeader
.biCompression
== BI_RGB
&& rop
== SRCCOPY
)
268 hBitmap
= GetCurrentObject( dev
->hdc
, OBJ_BITMAP
);
269 if (GetObjectW( hBitmap
, sizeof(bm
), &bm
) &&
270 bm
.bmWidth
== widthSrc
&& bm
.bmHeight
== heightSrc
&&
271 bm
.bmBitsPixel
== bpp
&& bm
.bmPlanes
== planes
)
274 return SetDIBits( dev
->hdc
, hBitmap
, 0, abs( height
), bits
, info
, coloruse
);
279 hdcMem
= CreateCompatibleDC( dev
->hdc
);
280 hBitmap
= CreateCompatibleBitmap( dev
->hdc
, width
, height
);
281 SelectObject( hdcMem
, hBitmap
);
282 if (coloruse
== DIB_PAL_COLORS
)
283 SelectPalette( hdcMem
, GetCurrentObject( dev
->hdc
, OBJ_PAL
), FALSE
);
285 if (info
->bmiHeader
.biCompression
== BI_RLE4
|| info
->bmiHeader
.biCompression
== BI_RLE8
)
287 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
288 * contain all the rectangle described in bmiHeader, but only part of it.
289 * This mean that those undescribed pixels must be left untouched.
290 * So, we first copy on a memory bitmap the current content of the
291 * destination rectangle, blit the DIB bits on top of it - hence leaving
292 * the gaps untouched -, and blitting the rectangle back.
293 * This insure that gaps are untouched on the destination rectangle
295 StretchBlt( hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
, widthSrc
, heightSrc
,
296 dev
->hdc
, xDst
, yDst
, widthDst
, heightDst
, rop
);
298 ret
= SetDIBits( hdcMem
, hBitmap
, 0, abs( height
), bits
, info
, coloruse
);
299 if (ret
) StretchBlt( dev
->hdc
, xDst
, yDst
, widthDst
, heightDst
,
300 hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
, widthSrc
, heightSrc
, rop
);
302 DeleteObject( hBitmap
);
306 /***********************************************************************
307 * StretchDIBits (GDI32.@)
309 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
310 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
311 const BITMAPINFO
*info
, UINT coloruse
, DWORD rop
)
316 if (!bits
|| !info
) return 0;
318 if ((dc
= get_dc_ptr( hdc
)))
320 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
322 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
323 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
324 release_dc_ptr( dc
);
330 /******************************************************************************
331 * SetDIBits [GDI32.@]
333 * Sets pixels in a bitmap using colors from DIB.
336 * hdc [I] Handle to device context
337 * hbitmap [I] Handle to bitmap
338 * startscan [I] Starting scan line
339 * lines [I] Number of scan lines
340 * bits [I] Array of bitmap bits
341 * info [I] Address of structure with data
342 * coloruse [I] Type of color indexes to use
345 * Success: Number of scan lines copied
348 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
349 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
352 DC
*dc
= get_dc_ptr( hdc
);
353 BOOL delete_hdc
= FALSE
;
356 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
357 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
360 if (coloruse
== DIB_RGB_COLORS
&& !dc
)
362 hdc
= CreateCompatibleDC(0);
363 dc
= get_dc_ptr( hdc
);
371 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
373 release_dc_ptr( dc
);
374 if (delete_hdc
) DeleteDC(hdc
);
378 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
)) goto done
;
380 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBits
);
381 if (!BITMAP_SetOwnerDC( hbitmap
, physdev
)) goto done
;
383 result
= physdev
->funcs
->pSetDIBits( physdev
, hbitmap
, startscan
, lines
, bits
, src_info
, coloruse
);
386 GDI_ReleaseObj( hbitmap
);
387 release_dc_ptr( dc
);
388 if (delete_hdc
) DeleteDC(hdc
);
393 /***********************************************************************
394 * SetDIBitsToDevice (GDI32.@)
396 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
397 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
398 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
406 if ((dc
= get_dc_ptr( hdc
)))
408 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
410 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
411 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
412 release_dc_ptr( dc
);
417 /***********************************************************************
418 * SetDIBColorTable (GDI32.@)
420 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, CONST RGBQUAD
*colors
)
426 if (!(dc
= get_dc_ptr( hdc
))) return 0;
428 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
430 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBColorTable
);
432 /* Check if currently selected bitmap is a DIB */
433 if (bitmap
->color_table
)
435 if (startpos
< bitmap
->nb_colors
)
437 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
438 memcpy(bitmap
->color_table
+ startpos
, colors
, entries
* sizeof(RGBQUAD
));
442 GDI_ReleaseObj( dc
->hBitmap
);
443 physdev
->funcs
->pSetDIBColorTable( physdev
, startpos
, entries
, colors
);
445 release_dc_ptr( dc
);
450 /***********************************************************************
451 * GetDIBColorTable (GDI32.@)
453 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
459 if (!(dc
= get_dc_ptr( hdc
))) return 0;
461 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
463 /* Check if currently selected bitmap is a DIB */
464 if (bitmap
->color_table
)
466 if (startpos
< bitmap
->nb_colors
)
468 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
469 memcpy(colors
, bitmap
->color_table
+ startpos
, entries
* sizeof(RGBQUAD
));
473 GDI_ReleaseObj( dc
->hBitmap
);
475 release_dc_ptr( dc
);
479 static const RGBQUAD DefLogPaletteQuads
[20] = { /* Copy of Default Logical Palette */
480 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
481 { 0x00, 0x00, 0x00, 0x00 },
482 { 0x00, 0x00, 0x80, 0x00 },
483 { 0x00, 0x80, 0x00, 0x00 },
484 { 0x00, 0x80, 0x80, 0x00 },
485 { 0x80, 0x00, 0x00, 0x00 },
486 { 0x80, 0x00, 0x80, 0x00 },
487 { 0x80, 0x80, 0x00, 0x00 },
488 { 0xc0, 0xc0, 0xc0, 0x00 },
489 { 0xc0, 0xdc, 0xc0, 0x00 },
490 { 0xf0, 0xca, 0xa6, 0x00 },
491 { 0xf0, 0xfb, 0xff, 0x00 },
492 { 0xa4, 0xa0, 0xa0, 0x00 },
493 { 0x80, 0x80, 0x80, 0x00 },
494 { 0x00, 0x00, 0xff, 0x00 },
495 { 0x00, 0xff, 0x00, 0x00 },
496 { 0x00, 0xff, 0xff, 0x00 },
497 { 0xff, 0x00, 0x00, 0x00 },
498 { 0xff, 0x00, 0xff, 0x00 },
499 { 0xff, 0xff, 0x00, 0x00 },
500 { 0xff, 0xff, 0xff, 0x00 }
503 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
504 static const DWORD bit_fields_565
[3] = {0xf800, 0x07e0, 0x001f};
505 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
507 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
509 BITMAPINFOHEADER header
;
511 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
512 header
.biWidth
= bmp
->bitmap
.bmWidth
;
513 header
.biHeight
= bmp
->bitmap
.bmHeight
;
518 header
.biBitCount
= bmp
->dib
->dsBm
.bmBitsPixel
;
519 switch (bmp
->dib
->dsBm
.bmBitsPixel
)
523 header
.biCompression
= BI_BITFIELDS
;
526 header
.biCompression
= BI_RGB
;
532 header
.biCompression
= (bmp
->bitmap
.bmBitsPixel
> 8) ? BI_BITFIELDS
: BI_RGB
;
533 header
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
536 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
537 header
.biXPelsPerMeter
= 0;
538 header
.biYPelsPerMeter
= 0;
539 header
.biClrUsed
= 0;
540 header
.biClrImportant
= 0;
542 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
544 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
546 coreheader
->bcWidth
= header
.biWidth
;
547 coreheader
->bcHeight
= header
.biHeight
;
548 coreheader
->bcPlanes
= header
.biPlanes
;
549 coreheader
->bcBitCount
= header
.biBitCount
;
552 info
->bmiHeader
= header
;
554 return abs(bmp
->bitmap
.bmHeight
);
557 /************************************************************************
560 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
562 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
564 unsigned int colors
= src
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << src
->bmiHeader
.biBitCount
;
565 RGBQUAD
*src_colors
= (RGBQUAD
*)((char *)src
+ src
->bmiHeader
.biSize
);
567 assert( src
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) );
569 if (src
->bmiHeader
.biClrUsed
) colors
= src
->bmiHeader
.biClrUsed
;
571 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
573 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
574 if (coloruse
== DIB_PAL_COLORS
)
575 memcpy( core
->bmciColors
, src_colors
, colors
* sizeof(WORD
) );
579 for (i
= 0; i
< colors
; i
++)
581 core
->bmciColors
[i
].rgbtRed
= src_colors
[i
].rgbRed
;
582 core
->bmciColors
[i
].rgbtGreen
= src_colors
[i
].rgbGreen
;
583 core
->bmciColors
[i
].rgbtBlue
= src_colors
[i
].rgbBlue
;
589 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
590 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
592 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
593 /* bitfields are always at bmiColors even in larger structures */
594 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
597 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
600 if (coloruse
== DIB_PAL_COLORS
)
601 size
= colors
* sizeof(WORD
);
603 size
= colors
* sizeof(RGBQUAD
);
604 memcpy( colorptr
, src_colors
, size
);
609 static void fill_default_color_table( BITMAPINFO
*info
)
613 switch (info
->bmiHeader
.biBitCount
)
616 info
->bmiColors
[0].rgbRed
= info
->bmiColors
[0].rgbGreen
= info
->bmiColors
[0].rgbBlue
= 0;
617 info
->bmiColors
[0].rgbReserved
= 0;
618 info
->bmiColors
[1].rgbRed
= info
->bmiColors
[1].rgbGreen
= info
->bmiColors
[1].rgbBlue
= 0xff;
619 info
->bmiColors
[1].rgbReserved
= 0;
623 /* The EGA palette is the first and last 8 colours of the default palette
624 with the innermost pair swapped */
625 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 7 * sizeof(RGBQUAD
));
626 memcpy(info
->bmiColors
+ 7, DefLogPaletteQuads
+ 12, 1 * sizeof(RGBQUAD
));
627 memcpy(info
->bmiColors
+ 8, DefLogPaletteQuads
+ 7, 1 * sizeof(RGBQUAD
));
628 memcpy(info
->bmiColors
+ 9, DefLogPaletteQuads
+ 13, 7 * sizeof(RGBQUAD
));
632 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 10 * sizeof(RGBQUAD
));
633 memcpy(info
->bmiColors
+ 246, DefLogPaletteQuads
+ 10, 10 * sizeof(RGBQUAD
));
634 for (i
= 10; i
< 246; i
++)
636 info
->bmiColors
[i
].rgbRed
= (i
& 0x07) << 5;
637 info
->bmiColors
[i
].rgbGreen
= (i
& 0x38) << 2;
638 info
->bmiColors
[i
].rgbBlue
= i
& 0xc0;
639 info
->bmiColors
[i
].rgbReserved
= 0;
644 ERR("called with bitcount %d\n", info
->bmiHeader
.biBitCount
);
648 /******************************************************************************
649 * GetDIBits [GDI32.@]
651 * Retrieves bits of bitmap and copies to buffer.
654 * Success: Number of scan lines copied from bitmap
657 INT WINAPI
GetDIBits(
658 HDC hdc
, /* [in] Handle to device context */
659 HBITMAP hbitmap
, /* [in] Handle to bitmap */
660 UINT startscan
, /* [in] First scan line to set in dest bitmap */
661 UINT lines
, /* [in] Number of scan lines to copy */
662 LPVOID bits
, /* [out] Address of array for bitmap bits */
663 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
664 UINT coloruse
) /* [in] RGB or palette index */
674 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
675 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
676 unsigned int colors
= 0;
680 bitmap_type
= DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
, &planes
, &bpp
, &compr
, &size
);
681 if (bitmap_type
== -1)
683 ERR("Invalid bitmap format\n");
686 if (!(dc
= get_dc_ptr( hdc
)))
688 SetLastError( ERROR_INVALID_PARAMETER
);
692 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
694 release_dc_ptr( dc
);
699 if (bpp
== 0) /* query bitmap info only */
701 lines
= fill_query_info( info
, bmp
);
705 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
706 own copy and transfer the colour info back at the end */
708 dst_info
->bmiHeader
.biSize
= sizeof(dst_info
->bmiHeader
);
709 dst_info
->bmiHeader
.biWidth
= width
;
710 dst_info
->bmiHeader
.biHeight
= height
;
711 dst_info
->bmiHeader
.biPlanes
= planes
;
712 dst_info
->bmiHeader
.biBitCount
= bpp
;
713 dst_info
->bmiHeader
.biCompression
= compr
;
714 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
715 dst_info
->bmiHeader
.biXPelsPerMeter
= 0;
716 dst_info
->bmiHeader
.biYPelsPerMeter
= 0;
717 dst_info
->bmiHeader
.biClrUsed
= 0;
718 dst_info
->bmiHeader
.biClrImportant
= 0;
728 /* If the bitmap object is a dib section at the
729 same color depth then get the color map from it */
730 if (bmp
->dib
&& bpp
== bmp
->dib
->dsBm
.bmBitsPixel
&& coloruse
== DIB_RGB_COLORS
)
732 colors
= min( colors
, bmp
->nb_colors
);
733 if (colors
!= 1 << bpp
) dst_info
->bmiHeader
.biClrUsed
= colors
;
734 memcpy( dst_info
->bmiColors
, bmp
->color_table
, colors
* sizeof(RGBQUAD
) );
737 /* For color DDBs in native depth (mono DDBs always have a black/white palette):
738 Generate the color map from the selected palette. In the DIB_PAL_COLORS
739 case we'll fix up the indices after the format conversion. */
740 else if ( (bpp
> 1 && bpp
== bmp
->bitmap
.bmBitsPixel
) || coloruse
== DIB_PAL_COLORS
)
742 if (!fill_color_table_from_palette( dst_info
, dc
))
749 fill_default_color_table( dst_info
);
754 if (dst_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
755 memcpy( dst_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
759 if (dst_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
763 if (bmp
->dib
->dsBmih
.biCompression
== BI_BITFIELDS
&& bmp
->dib
->dsBmih
.biBitCount
== bpp
)
764 memcpy( dst_info
->bmiColors
, bmp
->dib
->dsBitfields
, 3 * sizeof(DWORD
) );
766 memcpy( dst_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
769 memcpy( dst_info
->bmiColors
, bit_fields_565
, sizeof(bit_fields_565
) );
775 if (dst_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
777 if (bmp
->dib
&& bmp
->dib
->dsBmih
.biCompression
== BI_BITFIELDS
&& bmp
->dib
->dsBmih
.biBitCount
== bpp
)
778 memcpy( dst_info
->bmiColors
, bmp
->dib
->dsBitfields
, 3 * sizeof(DWORD
) );
780 memcpy( dst_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
788 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
789 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
790 struct gdi_image_bits src_bits
;
791 struct bitblt_coords src
;
794 /* FIXME: will need updating once the dib driver has pGetImage. */
795 physdev
= GET_DC_PHYSDEV( dc
, pGetImage
);
797 if (!BITMAP_SetOwnerDC( hbitmap
, physdev
)) lines
= 0;
799 src
.visrect
.left
= 0;
800 src
.visrect
.right
= min( width
, bmp
->bitmap
.bmWidth
);
802 if (startscan
>= bmp
->bitmap
.bmHeight
) /* constrain lines to within src bitmap */
805 lines
= min( lines
, bmp
->bitmap
.bmHeight
- startscan
);
806 lines
= min( lines
, abs(height
) ); /* and constrain to within dest bitmap */
808 if (lines
== 0) goto done
;
810 src
.visrect
.bottom
= bmp
->bitmap
.bmHeight
- startscan
;
811 src
.visrect
.top
= src
.visrect
.bottom
- lines
;
812 src
.x
= src
.visrect
.left
;
813 src
.y
= src
.visrect
.top
;
814 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
815 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
817 err
= physdev
->funcs
->pGetImage( physdev
, hbitmap
, src_info
, &src_bits
, &src
);
825 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
828 memcpy( src_info
->bmiColors
, bmp
->color_table
, bmp
->nb_colors
* sizeof(RGBQUAD
) );
830 fill_default_color_table( src_info
);
833 if(dst_info
->bmiHeader
.biHeight
> 0)
834 dst_info
->bmiHeader
.biHeight
= lines
;
836 dst_info
->bmiHeader
.biHeight
= -lines
;
838 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
.visrect
, dst_info
, bits
);
839 if (src_bits
.free
) src_bits
.free( &src_bits
);
841 else lines
= abs(height
);
843 if (coloruse
== DIB_PAL_COLORS
)
845 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
846 for (i
= 0; i
< colors
; i
++, index
++)
850 copy_color_info( info
, dst_info
, coloruse
);
853 release_dc_ptr( dc
);
854 GDI_ReleaseObj( hbitmap
);
859 /***********************************************************************
860 * CreateDIBitmap (GDI32.@)
862 * Creates a DDB (device dependent bitmap) from a DIB.
863 * The DDB will have the same color depth as the reference DC.
865 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
866 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
875 if (!header
) return 0;
877 if (DIB_GetBitmapInfo( header
, &width
, &height
, &planes
, &bpp
, &compr
, &size
) == -1) return 0;
881 TRACE("Bitmap has a negative width\n");
885 /* Top-down DIBs have a negative height */
886 if (height
< 0) height
= -height
;
888 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
889 hdc
, header
, init
, bits
, data
, coloruse
, width
, height
, bpp
, compr
);
892 handle
= CreateBitmap( width
, height
, 1, 1, NULL
);
894 handle
= CreateCompatibleBitmap( hdc
, width
, height
);
900 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
902 DeleteObject( handle
);
911 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
912 static void DIB_CopyColorTable( DC
*dc
, BITMAPOBJ
*bmp
, WORD coloruse
, const BITMAPINFO
*info
)
915 unsigned int colors
, i
;
916 BOOL core_info
= info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
);
920 colors
= 1 << ((const BITMAPCOREINFO
*) info
)->bmciHeader
.bcBitCount
;
924 colors
= info
->bmiHeader
.biClrUsed
;
925 if (!colors
) colors
= 1 << info
->bmiHeader
.biBitCount
;
929 ERR("called with >256 colors!\n");
933 if (!(colorTable
= HeapAlloc(GetProcessHeap(), 0, colors
* sizeof(RGBQUAD
) ))) return;
935 if(coloruse
== DIB_RGB_COLORS
)
939 /* Convert RGBTRIPLEs to RGBQUADs */
940 for (i
=0; i
< colors
; i
++)
942 colorTable
[i
].rgbRed
= ((const BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtRed
;
943 colorTable
[i
].rgbGreen
= ((const BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtGreen
;
944 colorTable
[i
].rgbBlue
= ((const BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtBlue
;
945 colorTable
[i
].rgbReserved
= 0;
950 memcpy(colorTable
, (const BYTE
*) info
+ (WORD
) info
->bmiHeader
.biSize
, colors
* sizeof(RGBQUAD
));
955 PALETTEENTRY entries
[256];
956 const WORD
*index
= (const WORD
*) ((const BYTE
*) info
+ (WORD
) info
->bmiHeader
.biSize
);
957 UINT count
= GetPaletteEntries( dc
->hPalette
, 0, colors
, entries
);
959 for (i
= 0; i
< colors
; i
++, index
++)
961 PALETTEENTRY
*entry
= &entries
[*index
% count
];
962 colorTable
[i
].rgbRed
= entry
->peRed
;
963 colorTable
[i
].rgbGreen
= entry
->peGreen
;
964 colorTable
[i
].rgbBlue
= entry
->peBlue
;
965 colorTable
[i
].rgbReserved
= 0;
968 bmp
->color_table
= colorTable
;
969 bmp
->nb_colors
= colors
;
972 /***********************************************************************
973 * CreateDIBSection (GDI32.@)
975 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, CONST BITMAPINFO
*bmi
, UINT usage
,
976 VOID
**bits
, HANDLE section
, DWORD offset
)
980 BOOL bDesktopDC
= FALSE
;
986 DWORD compression
, sizeImage
;
987 void *mapBits
= NULL
;
990 if(bits
) *bits
= NULL
;
994 if (((bitmap_type
= DIB_GetBitmapInfo( &bmi
->bmiHeader
, &width
, &height
,
995 &planes
, &bpp
, &compression
, &sizeImage
)) == -1))
1002 if (compression
== BI_BITFIELDS
) break;
1008 if (compression
== BI_RGB
) break;
1011 WARN( "invalid %u bpp compression %u\n", bpp
, compression
);
1015 if (!(dib
= HeapAlloc( GetProcessHeap(), 0, sizeof(*dib
) ))) return 0;
1017 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1018 width
, height
, planes
, bpp
, compression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1019 sizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1021 dib
->dsBm
.bmType
= 0;
1022 dib
->dsBm
.bmWidth
= width
;
1023 dib
->dsBm
.bmHeight
= height
>= 0 ? height
: -height
;
1024 dib
->dsBm
.bmWidthBytes
= get_dib_stride( width
, bpp
);
1025 dib
->dsBm
.bmPlanes
= planes
;
1026 dib
->dsBm
.bmBitsPixel
= bpp
;
1027 dib
->dsBm
.bmBits
= NULL
;
1029 if (!bitmap_type
) /* core header */
1031 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1032 dib
->dsBmih
.biSize
= sizeof(BITMAPINFOHEADER
);
1033 dib
->dsBmih
.biWidth
= width
;
1034 dib
->dsBmih
.biHeight
= height
;
1035 dib
->dsBmih
.biPlanes
= planes
;
1036 dib
->dsBmih
.biBitCount
= bpp
;
1037 dib
->dsBmih
.biCompression
= compression
;
1038 dib
->dsBmih
.biXPelsPerMeter
= 0;
1039 dib
->dsBmih
.biYPelsPerMeter
= 0;
1040 dib
->dsBmih
.biClrUsed
= 0;
1041 dib
->dsBmih
.biClrImportant
= 0;
1045 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1046 dib
->dsBmih
= bmi
->bmiHeader
;
1047 dib
->dsBmih
.biSize
= sizeof(BITMAPINFOHEADER
);
1050 /* set number of entries in bmi.bmiColors table */
1052 dib
->dsBmih
.biClrUsed
= 1 << bpp
;
1054 dib
->dsBmih
.biSizeImage
= dib
->dsBm
.bmWidthBytes
* dib
->dsBm
.bmHeight
;
1056 /* set dsBitfields values */
1057 dib
->dsBitfields
[0] = dib
->dsBitfields
[1] = dib
->dsBitfields
[2] = 0;
1059 if((bpp
== 15 || bpp
== 16) && compression
== BI_RGB
)
1061 /* In this case Windows changes biCompression to BI_BITFIELDS,
1062 however for now we won't do this, as there are a lot
1063 of places where BI_BITFIELDS is currently unsupported. */
1065 /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
1066 dib
->dsBitfields
[0] = 0x7c00;
1067 dib
->dsBitfields
[1] = 0x03e0;
1068 dib
->dsBitfields
[2] = 0x001f;
1070 else if(compression
== BI_BITFIELDS
)
1072 dib
->dsBitfields
[0] = *(const DWORD
*)bmi
->bmiColors
;
1073 dib
->dsBitfields
[1] = *((const DWORD
*)bmi
->bmiColors
+ 1);
1074 dib
->dsBitfields
[2] = *((const DWORD
*)bmi
->bmiColors
+ 2);
1077 /* get storage location for DIB bits */
1081 SYSTEM_INFO SystemInfo
;
1085 GetSystemInfo( &SystemInfo
);
1086 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1087 mapSize
= dib
->dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1088 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1089 if (mapBits
) dib
->dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1094 dib
->dsBm
.bmBits
= VirtualAlloc( NULL
, dib
->dsBmih
.biSizeImage
,
1095 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1097 dib
->dshSection
= section
;
1098 dib
->dsOffset
= offset
;
1100 if (!dib
->dsBm
.bmBits
)
1102 HeapFree( GetProcessHeap(), 0, dib
);
1106 /* If the reference hdc is null, take the desktop dc */
1109 hdc
= CreateCompatibleDC(0);
1113 if (!(dc
= get_dc_ptr( hdc
))) goto error
;
1115 /* create Device Dependent Bitmap and add DIB pointer */
1116 ret
= CreateBitmap( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmHeight
, 1,
1117 (bpp
== 1) ? 1 : GetDeviceCaps(hdc
, BITSPIXEL
), NULL
);
1119 if (ret
&& ((bmp
= GDI_GetObjPtr(ret
, OBJ_BITMAP
))))
1121 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pCreateDIBSection
);
1123 bmp
->funcs
= physdev
->funcs
;
1124 /* create local copy of DIB palette */
1125 if (bpp
<= 8) DIB_CopyColorTable( dc
, bmp
, usage
, bmi
);
1126 GDI_ReleaseObj( ret
);
1128 if (!physdev
->funcs
->pCreateDIBSection( physdev
, ret
, bmi
, usage
))
1130 DeleteObject( ret
);
1135 release_dc_ptr( dc
);
1136 if (bDesktopDC
) DeleteDC( hdc
);
1137 if (ret
&& bits
) *bits
= dib
->dsBm
.bmBits
;
1141 if (bDesktopDC
) DeleteDC( hdc
);
1142 if (section
) UnmapViewOfFile( mapBits
);
1143 else if (!offset
) VirtualFree( dib
->dsBm
.bmBits
, 0, MEM_RELEASE
);
1144 HeapFree( GetProcessHeap(), 0, dib
);