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).
34 * The palettes are stored in different formats:
36 - BITMAPCOREINFO: Array of RGBTRIPLE
37 - BITMAPINFO: Array of RGBQUAD
40 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
43 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45 If biCompression is BI_BITFIELDS, the color masks are at the same position
46 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
47 the new headers have structure members for the masks.
50 * You should never access the color table using the bmiColors member,
51 because the passed structure may have one of the extended headers
52 mentioned above. Use this to calculate the location:
55 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 Search for "Bitmap Structures" in MSDN
70 #define WIN32_NO_STATUS
75 #include "ddk/d3dkmthk.h"
77 #include "gdi_private.h"
78 #include "wine/debug.h"
80 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
83 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
);
84 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
85 static BOOL
DIB_DeleteObject( HGDIOBJ handle
);
87 static const struct gdi_obj_funcs dib_funcs
=
89 DIB_SelectObject
, /* pSelectObject */
90 DIB_GetObject
, /* pGetObjectA */
91 DIB_GetObject
, /* pGetObjectW */
92 NULL
, /* pUnrealizeObject */
93 DIB_DeleteObject
/* pDeleteObject */
96 /***********************************************************************
99 * Return the size of the bitmap info structure including color table.
101 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
103 unsigned int colors
, size
, masks
= 0;
105 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
107 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
108 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
109 return sizeof(BITMAPCOREHEADER
) + colors
*
110 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
112 else /* assume BITMAPINFOHEADER */
114 if (info
->bmiHeader
.biClrUsed
) colors
= min( info
->bmiHeader
.biClrUsed
, 256 );
115 else colors
= info
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << info
->bmiHeader
.biBitCount
;
116 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
117 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
118 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
122 /*******************************************************************************************
123 * Verify that the DIB parameters are valid.
125 static BOOL
is_valid_dib_format( const BITMAPINFOHEADER
*info
, BOOL allow_compression
)
127 if (info
->biWidth
<= 0) return FALSE
;
128 if (info
->biHeight
== 0) return FALSE
;
130 if (allow_compression
&& (info
->biCompression
== BI_RLE4
|| info
->biCompression
== BI_RLE8
))
132 if (info
->biHeight
< 0) return FALSE
;
133 if (!info
->biSizeImage
) return FALSE
;
134 return info
->biBitCount
== (info
->biCompression
== BI_RLE4
? 4 : 8);
137 if (!info
->biPlanes
) return FALSE
;
139 /* check for size overflow */
140 if (!info
->biBitCount
) return FALSE
;
141 if (UINT_MAX
/ info
->biBitCount
< info
->biWidth
) return FALSE
;
142 if (UINT_MAX
/ get_dib_stride( info
->biWidth
, info
->biBitCount
) < abs( info
->biHeight
)) return FALSE
;
144 switch (info
->biBitCount
)
150 return (info
->biCompression
== BI_RGB
);
153 return (info
->biCompression
== BI_BITFIELDS
|| info
->biCompression
== BI_RGB
);
159 /*******************************************************************************************
160 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
162 static BOOL
bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER
*dst
, const BITMAPINFOHEADER
*info
)
164 if (!info
) return FALSE
;
166 if (info
->biSize
== sizeof(BITMAPCOREHEADER
))
168 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
169 dst
->biWidth
= core
->bcWidth
;
170 dst
->biHeight
= core
->bcHeight
;
171 dst
->biPlanes
= core
->bcPlanes
;
172 dst
->biBitCount
= core
->bcBitCount
;
173 dst
->biCompression
= BI_RGB
;
174 dst
->biXPelsPerMeter
= 0;
175 dst
->biYPelsPerMeter
= 0;
177 dst
->biClrImportant
= 0;
179 else if (info
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
185 WARN( "(%u): unknown/wrong size for header\n", info
->biSize
);
189 dst
->biSize
= sizeof(*dst
);
190 if (dst
->biCompression
== BI_RGB
|| dst
->biCompression
== BI_BITFIELDS
)
191 dst
->biSizeImage
= get_dib_image_size( (BITMAPINFO
*)dst
);
195 /*******************************************************************************************
196 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
198 * The resulting sanitized BITMAPINFO is guaranteed to have:
199 * - biSize set to sizeof(BITMAPINFOHEADER)
200 * - biSizeImage set to the actual image size even for non-compressed DIB
201 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
202 * - color table present only for <= 8 bpp, always starts at info->bmiColors
204 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
,
205 UINT coloruse
, BOOL allow_compression
)
209 if (coloruse
> DIB_PAL_COLORS
+ 1) return FALSE
; /* FIXME: handle DIB_PAL_COLORS+1 format */
210 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
211 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
213 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
215 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
217 /* bitfields are always at bmiColors even in larger structures */
218 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
219 dst
->bmiHeader
.biClrUsed
= 0;
221 else if (dst
->bmiHeader
.biBitCount
<= 8)
223 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
224 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
226 if (!colors
) colors
= max_colors
;
227 else colors
= min( colors
, max_colors
);
229 if (coloruse
== DIB_PAL_COLORS
)
231 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
234 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
236 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
241 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
242 for (i
= 0; i
< colors
; i
++)
244 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
245 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
246 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
247 dst
->bmiColors
[i
].rgbReserved
= 0;
250 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
251 dst
->bmiHeader
.biClrUsed
= max_colors
;
253 else dst
->bmiHeader
.biClrUsed
= 0;
258 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
260 PALETTEENTRY palEntry
[256];
261 HPALETTE palette
= GetCurrentObject( hdc
, OBJ_PAL
);
262 int i
, colors
= 1 << info
->bmiHeader
.biBitCount
;
264 info
->bmiHeader
.biClrUsed
= colors
;
266 if (!palette
) return 0;
268 memset( palEntry
, 0, sizeof(palEntry
) );
269 if (!GetPaletteEntries( palette
, 0, colors
, palEntry
))
272 for (i
= 0; i
< colors
; i
++)
274 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
275 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
276 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
277 info
->bmiColors
[i
].rgbReserved
= 0;
283 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
285 PALETTEENTRY entries
[256];
288 const WORD
*index
= (const WORD
*)info
->bmiColors
;
289 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
291 if (!colors
) return TRUE
;
292 if (!(palette
= GetCurrentObject( hdc
, OBJ_PAL
))) return FALSE
;
293 if (!(count
= GetPaletteEntries( palette
, 0, colors
, entries
))) return FALSE
;
295 for (i
= 0; i
< colors
; i
++, index
++)
297 table
[i
].rgbRed
= entries
[*index
% count
].peRed
;
298 table
[i
].rgbGreen
= entries
[*index
% count
].peGreen
;
299 table
[i
].rgbBlue
= entries
[*index
% count
].peBlue
;
300 table
[i
].rgbReserved
= 0;
302 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
303 memcpy( info
->bmiColors
, table
, colors
* sizeof(RGBQUAD
) );
304 memset( info
->bmiColors
+ colors
, 0, (info
->bmiHeader
.biClrUsed
- colors
) * sizeof(RGBQUAD
) );
308 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
310 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
311 const int bpp
= info
->bmiHeader
.biBitCount
;
314 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
316 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
319 static BOOL
build_rle_bitmap( BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
323 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
325 BYTE skip
, num
, data
;
326 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
328 if (clip
) *clip
= NULL
;
330 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
332 out_bits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, get_dib_image_size( info
) );
333 if (!out_bits
) goto fail
;
337 *clip
= CreateRectRgn( 0, 0, 0, 0 );
338 run
= CreateRectRgn( 0, 0, 0, 0 );
339 if (!*clip
|| !run
) goto fail
;
342 x
= left
= right
= 0;
345 while (i
< info
->bmiHeader
.biSizeImage
- 1)
348 data
= in_bits
[i
+ 1];
353 if (x
+ num
> width
) num
= width
- x
;
356 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
357 if (info
->bmiHeader
.biBitCount
== 8)
358 memset( out_ptr
, s
, num
);
363 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
364 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
369 /* this will write one too many if num is odd, but that doesn't matter */
370 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
380 if(left
!= right
&& clip
)
382 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
383 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
388 left
= right
= x
= 0;
397 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
399 if (x
> width
) x
= width
;
406 else /* data bytes of data */
409 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
410 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
411 skip
= (skip
+ 1) & ~1;
412 if (x
+ num
> width
) num
= width
- x
;
415 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
416 if (info
->bmiHeader
.biBitCount
== 8)
417 memcpy( out_ptr
, in_bits
+ i
, num
);
422 const BYTE
*in_ptr
= in_bits
+ i
;
423 for ( ; num
; num
--, x
++)
427 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
431 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
435 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
446 if (run
) DeleteObject( run
);
447 if (bits
->free
) bits
->free( bits
);
449 bits
->ptr
= out_bits
;
450 bits
->is_copy
= TRUE
;
451 bits
->free
= free_heap_bits
;
452 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
457 if (run
) DeleteObject( run
);
458 if (clip
&& *clip
) DeleteObject( *clip
);
459 HeapFree( GetProcessHeap(), 0, out_bits
);
465 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
466 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
467 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
469 DC
*dc
= get_nulldrv_dc( dev
);
470 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
471 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
472 struct bitblt_coords src
, dst
;
473 struct gdi_image_bits src_bits
;
477 INT height
= abs( src_info
->bmiHeader
.biHeight
);
478 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
481 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
482 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
484 src_bits
.ptr
= (void*)bits
;
485 src_bits
.is_copy
= FALSE
;
486 src_bits
.free
= NULL
;
488 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
492 rect
.right
= xDst
+ widthDst
;
493 rect
.bottom
= yDst
+ heightDst
;
494 lp_to_dp( dc
, (POINT
*)&rect
, 2 );
497 dst
.width
= rect
.right
- rect
.left
;
498 dst
.height
= rect
.bottom
- rect
.top
;
500 if (dc
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
503 dst
.width
= -dst
.width
;
505 rop
&= ~NOMIRRORBITMAP
;
508 src
.width
= widthSrc
;
510 src
.height
= heightSrc
;
512 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
513 non_stretch_from_origin
= TRUE
;
515 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
517 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
518 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
521 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
523 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
524 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
529 if (dst
.width
< 0 && dst
.width
== src
.width
)
531 /* This is off-by-one, but that's what Windows does */
534 dst
.width
= -dst
.width
;
535 src
.width
= -src
.width
;
537 if (dst
.height
< 0 && dst
.height
== src
.height
)
541 dst
.height
= -dst
.height
;
542 src
.height
= -src
.height
;
546 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
548 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
550 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
551 src
.y
= -src
.height
- 1;
553 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
555 src
.visrect
.left
= 0;
556 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
558 src
.visrect
.bottom
= height
;
559 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
561 if (rop
== SRCCOPY
) ret
= height
;
562 else ret
= src_info
->bmiHeader
.biHeight
;
564 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
566 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
568 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
570 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
572 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
573 copy_bitmapinfo( dst_info
, src_info
);
574 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
575 if (err
== ERROR_BAD_FORMAT
)
577 DWORD dst_colors
= dst_info
->bmiHeader
.biClrUsed
;
579 /* 1-bpp destination without a color table requires a fake 1-entry table
580 * that contains only the background color. There is no source DC to get
581 * it from, so the background is hardcoded to the default color. */
582 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_colors
)
584 static const RGBQUAD default_bg
= { 255, 255, 255 };
585 dst_info
->bmiColors
[0] = default_bg
;
586 dst_info
->bmiHeader
.biClrUsed
= 1;
589 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
)))
591 /* get rid of the fake 1-bpp table */
592 dst_info
->bmiHeader
.biClrUsed
= dst_colors
;
593 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
597 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
599 copy_bitmapinfo( src_info
, dst_info
);
600 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, dc
->stretchBltMode
);
601 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
606 if (src_bits
.free
) src_bits
.free( &src_bits
);
607 if (clip
) DeleteObject( clip
);
611 /***********************************************************************
612 * StretchDIBits (GDI32.@)
614 INT WINAPI DECLSPEC_HOTPATCH
StretchDIBits( HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
615 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
616 const void *bits
, const BITMAPINFO
*bmi
, UINT coloruse
,
619 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
620 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
626 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
628 SetLastError( ERROR_INVALID_PARAMETER
);
632 if ((dc
= get_dc_ptr( hdc
)))
635 physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
636 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
637 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
638 release_dc_ptr( dc
);
644 /******************************************************************************
645 * SetDIBits [GDI32.@]
647 * Sets pixels in a bitmap using colors from DIB.
650 * hdc [I] Handle to device context
651 * hbitmap [I] Handle to bitmap
652 * startscan [I] Starting scan line
653 * lines [I] Number of scan lines
654 * bits [I] Array of bitmap bits
655 * info [I] Address of structure with data
656 * coloruse [I] Type of color indexes to use
659 * Success: Number of scan lines copied
662 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
663 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
667 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
668 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
669 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
670 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
673 struct gdi_image_bits src_bits
;
674 struct bitblt_coords src
, dst
;
675 INT src_to_dst_offset
;
678 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
) || coloruse
> DIB_PAL_COLORS
)
680 SetLastError( ERROR_INVALID_PARAMETER
);
683 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
685 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
686 if (!masks
[0] || !masks
[1] || !masks
[2])
688 SetLastError( ERROR_INVALID_PARAMETER
);
693 src_bits
.ptr
= (void *)bits
;
694 src_bits
.is_copy
= FALSE
;
695 src_bits
.free
= NULL
;
696 src_bits
.param
= NULL
;
698 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
700 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
702 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
704 if (lines
== 0) goto done
;
705 else lines
= src_info
->bmiHeader
.biHeight
;
708 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
711 dst
.visrect
.left
= 0;
713 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
714 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
716 src
.visrect
.left
= 0;
718 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
719 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
721 if (src_info
->bmiHeader
.biHeight
> 0)
723 src_to_dst_offset
= -startscan
;
724 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
725 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
729 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
730 /* Unlike the bottom-up case, Windows doesn't limit lines. */
731 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
736 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
737 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
738 src
.visrect
= dst
.visrect
;
739 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
741 src
.x
= src
.visrect
.left
;
742 src
.y
= src
.visrect
.top
;
743 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
744 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
746 dst
.x
= dst
.visrect
.left
;
747 dst
.y
= dst
.visrect
.top
;
748 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
749 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
751 copy_bitmapinfo( dst_info
, src_info
);
753 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
754 if (err
== ERROR_BAD_FORMAT
)
756 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
757 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
762 if (src_bits
.free
) src_bits
.free( &src_bits
);
763 if (clip
) DeleteObject( clip
);
764 GDI_ReleaseObj( hbitmap
);
769 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
770 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
771 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
773 DC
*dc
= get_nulldrv_dc( dev
);
774 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
775 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
776 struct bitblt_coords src
, dst
;
777 struct gdi_image_bits src_bits
;
785 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
786 height
= abs( src_info
->bmiHeader
.biHeight
);
788 src_bits
.ptr
= (void *)bits
;
789 src_bits
.is_copy
= FALSE
;
790 src_bits
.free
= NULL
;
792 if (!lines
) return 0;
793 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
795 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
799 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
800 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
801 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
806 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
810 if (startscan
>= height
) return 0;
811 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
813 /* map src to top-down coordinates with startscan as origin */
815 src
.y
= startscan
+ lines
- (y_src
+ cy
);
822 /* get rid of unnecessary lines */
823 if (src
.y
>= lines
) return 0;
827 else if (src
.y
>= lines
) return lines
;
829 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
830 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( src_info
);
833 src
.visrect
.left
= src
.x
;
834 src
.visrect
.top
= src
.y
;
835 src
.visrect
.right
= src
.x
+ cx
;
836 src
.visrect
.bottom
= src
.y
+ cy
;
839 rect
.right
= src_info
->bmiHeader
.biWidth
;
840 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
841 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
849 lp_to_dp( dc
, &pt
, 1 );
854 if (dc
->layout
& LAYOUT_RTL
) dst
.x
-= cx
- 1;
858 rect
.right
= dst
.x
+ cx
;
859 rect
.bottom
= dst
.y
+ cy
;
860 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
862 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
863 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
864 src
.visrect
= dst
.visrect
= rect
;
865 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
866 if (is_rect_empty( &dst
.visrect
)) goto done
;
867 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
869 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
870 copy_bitmapinfo( dst_info
, src_info
);
871 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
872 if (err
== ERROR_BAD_FORMAT
)
874 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
875 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
880 if (src_bits
.free
) src_bits
.free( &src_bits
);
881 if (clip
) DeleteObject( clip
);
885 /***********************************************************************
886 * SetDIBitsToDevice (GDI32.@)
888 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
889 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
890 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
893 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
894 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
900 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
902 SetLastError( ERROR_INVALID_PARAMETER
);
906 if ((dc
= get_dc_ptr( hdc
)))
909 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
910 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
911 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
912 release_dc_ptr( dc
);
917 /***********************************************************************
918 * SetDIBColorTable (GDI32.@)
920 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
926 if (!(dc
= get_dc_ptr( hdc
))) return 0;
928 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
930 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
932 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
933 for (i
= 0; i
< result
; i
++)
935 bitmap
->color_table
[startpos
+ i
].rgbBlue
= colors
[i
].rgbBlue
;
936 bitmap
->color_table
[startpos
+ i
].rgbGreen
= colors
[i
].rgbGreen
;
937 bitmap
->color_table
[startpos
+ i
].rgbRed
= colors
[i
].rgbRed
;
938 bitmap
->color_table
[startpos
+ i
].rgbReserved
= 0;
941 GDI_ReleaseObj( dc
->hBitmap
);
943 if (result
) /* update colors of selected objects */
945 SetTextColor( hdc
, dc
->textColor
);
946 SetBkColor( hdc
, dc
->backgroundColor
);
947 SelectObject( hdc
, dc
->hPen
);
948 SelectObject( hdc
, dc
->hBrush
);
951 release_dc_ptr( dc
);
956 /***********************************************************************
957 * GetDIBColorTable (GDI32.@)
959 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
965 if (!(dc
= get_dc_ptr( hdc
))) return 0;
967 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
969 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
971 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
972 memcpy(colors
, bitmap
->color_table
+ startpos
, result
* sizeof(RGBQUAD
));
974 GDI_ReleaseObj( dc
->hBitmap
);
976 release_dc_ptr( dc
);
980 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
981 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
983 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
985 BITMAPINFOHEADER header
;
987 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
988 header
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
989 header
.biHeight
= bmp
->dib
.dsBm
.bmHeight
;
991 header
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
993 switch (header
.biBitCount
)
997 header
.biCompression
= BI_BITFIELDS
;
1000 header
.biCompression
= BI_RGB
;
1004 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
1005 header
.biXPelsPerMeter
= 0;
1006 header
.biYPelsPerMeter
= 0;
1007 header
.biClrUsed
= 0;
1008 header
.biClrImportant
= 0;
1010 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
1012 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
1014 coreheader
->bcWidth
= header
.biWidth
;
1015 coreheader
->bcHeight
= header
.biHeight
;
1016 coreheader
->bcPlanes
= header
.biPlanes
;
1017 coreheader
->bcBitCount
= header
.biBitCount
;
1020 info
->bmiHeader
= header
;
1022 return bmp
->dib
.dsBm
.bmHeight
;
1025 /************************************************************************
1028 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1030 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1032 assert( src
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
) );
1034 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1036 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1037 if (coloruse
== DIB_PAL_COLORS
)
1038 memcpy( core
->bmciColors
, src
->bmiColors
, src
->bmiHeader
.biClrUsed
* sizeof(WORD
) );
1042 for (i
= 0; i
< src
->bmiHeader
.biClrUsed
; i
++)
1044 core
->bmciColors
[i
].rgbtRed
= src
->bmiColors
[i
].rgbRed
;
1045 core
->bmciColors
[i
].rgbtGreen
= src
->bmiColors
[i
].rgbGreen
;
1046 core
->bmciColors
[i
].rgbtBlue
= src
->bmiColors
[i
].rgbBlue
;
1052 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1054 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1055 /* bitfields are always at bmiColors even in larger structures */
1056 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1057 else if (src
->bmiHeader
.biClrUsed
)
1059 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1062 if (coloruse
== DIB_PAL_COLORS
)
1063 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1065 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1066 memcpy( colorptr
, src
->bmiColors
, size
);
1071 const RGBQUAD
*get_default_color_table( int bpp
)
1073 static const RGBQUAD table_1
[2] =
1075 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1077 static const RGBQUAD table_4
[16] =
1079 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1080 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1081 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1082 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1084 static const RGBQUAD table_8
[256] =
1086 /* first and last 10 entries are the default system palette entries */
1087 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1088 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1089 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1090 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1091 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1092 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1093 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1094 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1095 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1096 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1097 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1098 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1099 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1100 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1101 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1102 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1103 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1104 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1105 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1106 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1107 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1108 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1109 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1110 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1111 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1112 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1113 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1114 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1115 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1116 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1117 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1118 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1119 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1120 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1121 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1122 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1123 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1124 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1125 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1126 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1127 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1128 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1129 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1130 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1131 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1132 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1133 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1134 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1135 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1136 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1137 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1138 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1139 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1140 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1141 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1142 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1143 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1144 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1145 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1146 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1147 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1148 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1149 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1150 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1155 case 1: return table_1
;
1156 case 4: return table_4
;
1157 case 8: return table_8
;
1158 default: return NULL
;
1162 void fill_default_color_table( BITMAPINFO
*info
)
1164 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1165 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1166 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1169 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1171 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1172 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1173 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1174 info
->bmiHeader
.biPlanes
= 1;
1175 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1176 info
->bmiHeader
.biCompression
= BI_RGB
;
1177 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
1178 info
->bmiHeader
.biXPelsPerMeter
= 0;
1179 info
->bmiHeader
.biYPelsPerMeter
= 0;
1180 info
->bmiHeader
.biClrUsed
= 0;
1181 info
->bmiHeader
.biClrImportant
= 0;
1184 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1186 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1187 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1188 unsigned int info_size
;
1190 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1192 info_size
= get_dib_info_size( info
, usage
);
1193 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ info
->bmiHeader
.biSizeImage
)))
1195 memcpy( ret
, info
, info_size
);
1196 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size( src_info
, usage
),
1197 info
->bmiHeader
.biSizeImage
);
1202 /******************************************************************************
1203 * GetDIBits [GDI32.@]
1205 * Retrieves bits of bitmap and copies to buffer.
1208 * Success: Number of scan lines copied from bitmap
1211 INT WINAPI DECLSPEC_HOTPATCH
GetDIBits(
1212 HDC hdc
, /* [in] Handle to device context */
1213 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1214 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1215 UINT lines
, /* [in] Number of scan lines to copy */
1216 LPVOID bits
, /* [out] Address of array for bitmap bits */
1217 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1218 UINT coloruse
) /* [in] RGB or palette index */
1222 int i
, dst_to_src_offset
, ret
= 0;
1224 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1225 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1226 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1227 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1228 struct gdi_image_bits src_bits
;
1229 struct bitblt_coords src
, dst
;
1230 BOOL empty_rect
= FALSE
;
1232 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1233 own copy and transfer the colour info back at the end */
1234 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1235 if (coloruse
> DIB_PAL_COLORS
) return 0;
1237 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1239 dst_info
->bmiHeader
.biClrUsed
= 0;
1240 dst_info
->bmiHeader
.biClrImportant
= 0;
1242 if (!(dc
= get_dc_ptr( hdc
)))
1244 SetLastError( ERROR_INVALID_PARAMETER
);
1248 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1250 release_dc_ptr( dc
);
1254 src
.visrect
.left
= 0;
1255 src
.visrect
.top
= 0;
1256 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1257 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1259 dst
.visrect
.left
= 0;
1260 dst
.visrect
.top
= 0;
1261 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1262 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1264 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1267 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1269 ret
= fill_query_info( info
, bmp
);
1273 /* validate parameters */
1275 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1276 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1278 switch (dst_info
->bmiHeader
.biCompression
)
1281 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1282 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1283 if (bits
) goto done
; /* can't retrieve compressed bits */
1286 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1287 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1288 if (bits
) goto done
; /* can't retrieve compressed bits */
1291 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1294 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1295 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1296 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1297 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1298 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1299 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1300 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1308 if (dst_info
->bmiHeader
.biHeight
> 0)
1310 dst_to_src_offset
= -startscan
;
1311 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1312 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1316 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1317 if (dst_to_src_offset
< 0)
1319 dst_to_src_offset
= 0;
1320 lines
= dst
.visrect
.bottom
- startscan
;
1322 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1325 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1326 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1327 dst
.visrect
= src
.visrect
;
1328 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1330 if (dst_info
->bmiHeader
.biHeight
> 0)
1332 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1334 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1335 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1336 memset( bits
, 0, pad_bytes
);
1337 bits
= (char *)bits
+ pad_bytes
;
1342 if (dst
.visrect
.bottom
< lines
)
1344 int pad_lines
= lines
- dst
.visrect
.bottom
;
1345 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1346 int pad_bytes
= pad_lines
* stride
;
1347 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1351 if (empty_rect
) bits
= NULL
;
1353 src
.x
= src
.visrect
.left
;
1354 src
.y
= src
.visrect
.top
;
1355 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1356 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1361 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1365 /* fill out the src colour table, if it needs one */
1366 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1367 fill_default_color_table( src_info
);
1369 /* if the src and dst are the same depth, copy the colour info across */
1370 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1372 switch (src_info
->bmiHeader
.biBitCount
)
1375 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1377 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1378 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1382 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1384 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1385 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1389 copy_color_info( dst_info
, src_info
, coloruse
);
1391 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1393 if( coloruse
== DIB_PAL_COLORS
)
1395 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1399 fill_default_color_table( dst_info
);
1405 if(dst_info
->bmiHeader
.biHeight
> 0)
1406 dst_info
->bmiHeader
.biHeight
= src
.height
;
1408 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1409 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1411 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1412 if (src_bits
.free
) src_bits
.free( &src_bits
);
1418 if (coloruse
== DIB_PAL_COLORS
)
1420 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1421 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1425 copy_color_info( info
, dst_info
, coloruse
);
1426 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
1428 info
->bmiHeader
.biClrUsed
= 0;
1429 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
1433 release_dc_ptr( dc
);
1434 GDI_ReleaseObj( hbitmap
);
1439 /***********************************************************************
1440 * CreateDIBitmap (GDI32.@)
1442 * Creates a DDB (device dependent bitmap) from a DIB.
1443 * The DDB will have the same color depth as the reference DC.
1445 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1446 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1449 BITMAPINFOHEADER info
;
1453 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1454 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1455 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1456 if (info
.biWidth
< 0) return 0;
1458 /* Top-down DIBs have a negative height */
1459 height
= abs( info
.biHeight
);
1461 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1462 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1463 info
.biBitCount
, info
.biCompression
);
1466 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1468 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1472 if (init
& CBM_INIT
)
1474 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1476 DeleteObject( handle
);
1486 /***********************************************************************
1487 * CreateDIBSection (GDI32.@)
1489 HBITMAP WINAPI DECLSPEC_HOTPATCH
CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
1490 void **bits
, HANDLE section
, DWORD offset
)
1492 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1493 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1496 void *mapBits
= NULL
;
1498 if (bits
) *bits
= NULL
;
1499 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1500 if (usage
> DIB_PAL_COLORS
) return 0;
1501 if (info
->bmiHeader
.biPlanes
!= 1)
1503 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1504 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1507 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1509 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1510 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1511 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1512 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1513 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1515 bmp
->dib
.dsBm
.bmType
= 0;
1516 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1517 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1518 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1519 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1520 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1521 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1523 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1525 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1527 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1528 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1529 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1531 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1534 /* set dsBitfields values */
1535 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1537 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1538 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1539 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1540 bmp
->dib
.dsBitfields
[2] = 0x001f;
1542 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1544 if (usage
== DIB_PAL_COLORS
) goto error
;
1545 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1546 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1547 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1548 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1550 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1552 /* get storage location for DIB bits */
1556 SYSTEM_INFO SystemInfo
;
1560 GetSystemInfo( &SystemInfo
);
1561 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1562 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1563 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1564 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1569 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1570 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1572 bmp
->dib
.dshSection
= section
;
1573 bmp
->dib
.dsOffset
= offset
;
1575 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1577 if (!(ret
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1579 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1583 if (section
) UnmapViewOfFile( mapBits
);
1584 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1585 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1586 HeapFree( GetProcessHeap(), 0, bmp
);
1591 /***********************************************************************
1592 * D3DKMTCreateDCFromMemory (GDI32.@)
1594 NTSTATUS WINAPI
D3DKMTCreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY
*desc
)
1596 const struct d3dddi_format_info
1598 D3DDDIFORMAT format
;
1599 unsigned int bit_count
;
1601 unsigned int palette_size
;
1602 DWORD mask_r
, mask_g
, mask_b
;
1604 BITMAPOBJ
*bmp
= NULL
;
1609 static const struct d3dddi_format_info format_info
[] =
1611 { D3DDDIFMT_R8G8B8
, 24, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1612 { D3DDDIFMT_A8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1613 { D3DDDIFMT_X8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1614 { D3DDDIFMT_R5G6B5
, 16, BI_BITFIELDS
, 0, 0x0000f800, 0x000007e0, 0x0000001f },
1615 { D3DDDIFMT_X1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1616 { D3DDDIFMT_A1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1617 { D3DDDIFMT_A4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1618 { D3DDDIFMT_X4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1619 { D3DDDIFMT_P8
, 8, BI_RGB
, 256, 0x00000000, 0x00000000, 0x00000000 },
1622 if (!desc
) return STATUS_INVALID_PARAMETER
;
1624 TRACE("memory %p, format %#x, width %u, height %u, pitch %u, device dc %p, color table %p.\n",
1625 desc
->pMemory
, desc
->Format
, desc
->Width
, desc
->Height
,
1626 desc
->Pitch
, desc
->hDeviceDc
, desc
->pColorTable
);
1628 if (!desc
->pMemory
) return STATUS_INVALID_PARAMETER
;
1630 for (i
= 0; i
< sizeof(format_info
) / sizeof(*format_info
); ++i
)
1632 if (format_info
[i
].format
== desc
->Format
)
1634 format
= &format_info
[i
];
1638 if (!format
) return STATUS_INVALID_PARAMETER
;
1640 if (desc
->Width
> (UINT_MAX
& ~3) / (format
->bit_count
/ 8) ||
1641 !desc
->Pitch
|| desc
->Pitch
< get_dib_stride( desc
->Width
, format
->bit_count
) ||
1642 !desc
->Height
|| desc
->Height
> UINT_MAX
/ desc
->Pitch
) return STATUS_INVALID_PARAMETER
;
1644 if (!desc
->hDeviceDc
|| !(dc
= CreateCompatibleDC( desc
->hDeviceDc
))) return STATUS_INVALID_PARAMETER
;
1646 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) goto error
;
1648 bmp
->dib
.dsBm
.bmWidth
= desc
->Width
;
1649 bmp
->dib
.dsBm
.bmHeight
= desc
->Height
;
1650 bmp
->dib
.dsBm
.bmWidthBytes
= desc
->Pitch
;
1651 bmp
->dib
.dsBm
.bmPlanes
= 1;
1652 bmp
->dib
.dsBm
.bmBitsPixel
= format
->bit_count
;
1653 bmp
->dib
.dsBm
.bmBits
= desc
->pMemory
;
1655 bmp
->dib
.dsBmih
.biSize
= sizeof(bmp
->dib
.dsBmih
);
1656 bmp
->dib
.dsBmih
.biWidth
= desc
->Width
;
1657 bmp
->dib
.dsBmih
.biHeight
= -(LONG
)desc
->Height
;
1658 bmp
->dib
.dsBmih
.biPlanes
= 1;
1659 bmp
->dib
.dsBmih
.biBitCount
= format
->bit_count
;
1660 bmp
->dib
.dsBmih
.biCompression
= format
->compression
;
1661 bmp
->dib
.dsBmih
.biClrUsed
= format
->palette_size
;
1662 bmp
->dib
.dsBmih
.biClrImportant
= format
->palette_size
;
1664 bmp
->dib
.dsBitfields
[0] = format
->mask_r
;
1665 bmp
->dib
.dsBitfields
[1] = format
->mask_g
;
1666 bmp
->dib
.dsBitfields
[2] = format
->mask_b
;
1668 if (format
->palette_size
)
1670 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0, format
->palette_size
* sizeof(*bmp
->color_table
) )))
1672 if (desc
->pColorTable
)
1674 for (i
= 0; i
< format
->palette_size
; ++i
)
1676 bmp
->color_table
[i
].rgbRed
= desc
->pColorTable
[i
].peRed
;
1677 bmp
->color_table
[i
].rgbGreen
= desc
->pColorTable
[i
].peGreen
;
1678 bmp
->color_table
[i
].rgbBlue
= desc
->pColorTable
[i
].peBlue
;
1679 bmp
->color_table
[i
].rgbReserved
= 0;
1684 memcpy( bmp
->color_table
, get_default_color_table( format
->bit_count
),
1685 format
->palette_size
* sizeof(*bmp
->color_table
) );
1689 if (!(bitmap
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1692 desc
->hBitmap
= bitmap
;
1693 SelectObject( dc
, bitmap
);
1694 return STATUS_SUCCESS
;
1697 if (bmp
) HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1698 HeapFree( GetProcessHeap(), 0, bmp
);
1700 return STATUS_INVALID_PARAMETER
;
1704 /***********************************************************************
1705 * D3DKMTDestroyDCFromMemory (GDI32.@)
1707 NTSTATUS WINAPI
D3DKMTDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY
*desc
)
1709 if (!desc
) return STATUS_INVALID_PARAMETER
;
1711 TRACE("dc %p, bitmap %p.\n", desc
->hDc
, desc
->hBitmap
);
1713 if (GetObjectType( desc
->hDc
) != OBJ_MEMDC
||
1714 GetObjectType( desc
->hBitmap
) != OBJ_BITMAP
) return STATUS_INVALID_PARAMETER
;
1715 DeleteObject( desc
->hBitmap
);
1716 DeleteDC( desc
->hDc
);
1718 return STATUS_SUCCESS
;
1722 /***********************************************************************
1725 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
)
1732 if (!(dc
= get_dc_ptr( hdc
))) return 0;
1734 if (GetObjectType( hdc
) != OBJ_MEMDC
)
1740 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
1742 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
1748 if (GDI_get_ref_count( handle
))
1750 WARN( "Bitmap already selected in another DC\n" );
1751 GDI_ReleaseObj( handle
);
1756 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
1757 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
1759 GDI_ReleaseObj( handle
);
1764 dc
->hBitmap
= handle
;
1765 GDI_inc_ref_count( handle
);
1767 dc
->vis_rect
.left
= 0;
1768 dc
->vis_rect
.top
= 0;
1769 dc
->vis_rect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
1770 dc
->vis_rect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
1771 dc
->device_rect
= dc
->vis_rect
;
1772 GDI_ReleaseObj( handle
);
1774 GDI_dec_ref_count( ret
);
1778 release_dc_ptr( dc
);
1783 /***********************************************************************
1786 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1789 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
1793 if (!buffer
) ret
= sizeof(BITMAP
);
1794 else if (count
>= sizeof(DIBSECTION
))
1796 DIBSECTION
*dib
= buffer
;
1798 dib
->dsBm
.bmWidthBytes
= get_dib_stride( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmBitsPixel
);
1799 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1800 ret
= sizeof(DIBSECTION
);
1802 else if (count
>= sizeof(BITMAP
))
1804 BITMAP
*bitmap
= buffer
;
1805 *bitmap
= bmp
->dib
.dsBm
;
1806 bitmap
->bmWidthBytes
= get_dib_stride( bitmap
->bmWidth
, bitmap
->bmBitsPixel
);
1807 ret
= sizeof(BITMAP
);
1810 GDI_ReleaseObj( handle
);
1815 /***********************************************************************
1818 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1822 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1824 if (bmp
->dib
.dshSection
)
1826 SYSTEM_INFO SystemInfo
;
1827 GetSystemInfo( &SystemInfo
);
1828 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1829 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1831 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1833 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1834 HeapFree( GetProcessHeap(), 0, bmp
);