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
68 #define WIN32_NO_STATUS
73 #include "ddk/d3dkmthk.h"
75 #include "ntgdi_private.h"
76 #include "wine/debug.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
81 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
82 static BOOL
DIB_DeleteObject( HGDIOBJ handle
);
84 static const struct gdi_obj_funcs dib_funcs
=
86 DIB_GetObject
, /* pGetObjectW */
87 NULL
, /* pUnrealizeObject */
88 DIB_DeleteObject
/* pDeleteObject */
91 /***********************************************************************
94 * Return the size of the bitmap info structure including color table.
96 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
98 unsigned int colors
, size
, masks
= 0;
100 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
102 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
103 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
104 return sizeof(BITMAPCOREHEADER
) + colors
*
105 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
107 else /* assume BITMAPINFOHEADER */
109 if (info
->bmiHeader
.biClrUsed
) colors
= min( info
->bmiHeader
.biClrUsed
, 256 );
110 else colors
= info
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << info
->bmiHeader
.biBitCount
;
111 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
112 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
113 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
117 /*******************************************************************************************
118 * Verify that the DIB parameters are valid.
120 static BOOL
is_valid_dib_format( const BITMAPINFOHEADER
*info
, BOOL allow_compression
)
122 if (info
->biWidth
<= 0) return FALSE
;
123 if (info
->biHeight
== 0) return FALSE
;
125 if (allow_compression
&& (info
->biCompression
== BI_RLE4
|| info
->biCompression
== BI_RLE8
))
127 if (info
->biHeight
< 0) return FALSE
;
128 if (!info
->biSizeImage
) return FALSE
;
129 return info
->biBitCount
== (info
->biCompression
== BI_RLE4
? 4 : 8);
132 if (!info
->biPlanes
) return FALSE
;
134 /* check for size overflow */
135 if (!info
->biBitCount
) return FALSE
;
136 if (UINT_MAX
/ info
->biBitCount
< info
->biWidth
) return FALSE
;
137 if (UINT_MAX
/ get_dib_stride( info
->biWidth
, info
->biBitCount
) < abs( info
->biHeight
)) return FALSE
;
139 switch (info
->biBitCount
)
145 return (info
->biCompression
== BI_RGB
);
148 return (info
->biCompression
== BI_BITFIELDS
|| info
->biCompression
== BI_RGB
);
154 /*******************************************************************************************
155 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
157 static BOOL
bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER
*dst
, const BITMAPINFOHEADER
*info
)
159 if (!info
) return FALSE
;
161 if (info
->biSize
== sizeof(BITMAPCOREHEADER
))
163 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
164 dst
->biWidth
= core
->bcWidth
;
165 dst
->biHeight
= core
->bcHeight
;
166 dst
->biPlanes
= core
->bcPlanes
;
167 dst
->biBitCount
= core
->bcBitCount
;
168 dst
->biCompression
= BI_RGB
;
169 dst
->biXPelsPerMeter
= 0;
170 dst
->biYPelsPerMeter
= 0;
172 dst
->biClrImportant
= 0;
174 else if (info
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
180 WARN( "(%u): unknown/wrong size for header\n", info
->biSize
);
184 dst
->biSize
= sizeof(*dst
);
185 if (dst
->biCompression
== BI_RGB
|| dst
->biCompression
== BI_BITFIELDS
)
186 dst
->biSizeImage
= get_dib_image_size( (BITMAPINFO
*)dst
);
190 /*******************************************************************************************
191 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
193 * The resulting sanitized BITMAPINFO is guaranteed to have:
194 * - biSize set to sizeof(BITMAPINFOHEADER)
195 * - biSizeImage set to the actual image size even for non-compressed DIB
196 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
197 * - color table present only for <= 8 bpp, always starts at info->bmiColors
199 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
,
200 UINT coloruse
, BOOL allow_compression
)
204 if (coloruse
> DIB_PAL_COLORS
+ 1) return FALSE
; /* FIXME: handle DIB_PAL_COLORS+1 format */
205 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
206 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
208 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
210 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
212 /* bitfields are always at bmiColors even in larger structures */
213 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
214 dst
->bmiHeader
.biClrUsed
= 0;
216 else if (dst
->bmiHeader
.biBitCount
<= 8)
218 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
219 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
221 if (!colors
) colors
= max_colors
;
222 else colors
= min( colors
, max_colors
);
224 if (coloruse
== DIB_PAL_COLORS
)
226 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
229 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
231 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
236 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
237 for (i
= 0; i
< colors
; i
++)
239 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
240 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
241 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
242 dst
->bmiColors
[i
].rgbReserved
= 0;
245 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
246 dst
->bmiHeader
.biClrUsed
= max_colors
;
248 else dst
->bmiHeader
.biClrUsed
= 0;
253 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
255 PALETTEENTRY palEntry
[256];
256 HPALETTE palette
= GetCurrentObject( hdc
, OBJ_PAL
);
257 int i
, colors
= 1 << info
->bmiHeader
.biBitCount
;
259 info
->bmiHeader
.biClrUsed
= colors
;
261 if (!palette
) return 0;
263 memset( palEntry
, 0, sizeof(palEntry
) );
264 if (!GetPaletteEntries( palette
, 0, colors
, palEntry
))
267 for (i
= 0; i
< colors
; i
++)
269 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
270 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
271 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
272 info
->bmiColors
[i
].rgbReserved
= 0;
278 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
280 PALETTEENTRY entries
[256];
283 const WORD
*index
= (const WORD
*)info
->bmiColors
;
284 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
286 if (!colors
) return TRUE
;
287 if (!(palette
= GetCurrentObject( hdc
, OBJ_PAL
))) return FALSE
;
288 if (!(count
= GetPaletteEntries( palette
, 0, colors
, entries
))) return FALSE
;
290 for (i
= 0; i
< colors
; i
++, index
++)
292 table
[i
].rgbRed
= entries
[*index
% count
].peRed
;
293 table
[i
].rgbGreen
= entries
[*index
% count
].peGreen
;
294 table
[i
].rgbBlue
= entries
[*index
% count
].peBlue
;
295 table
[i
].rgbReserved
= 0;
297 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
298 memcpy( info
->bmiColors
, table
, colors
* sizeof(RGBQUAD
) );
299 memset( info
->bmiColors
+ colors
, 0, (info
->bmiHeader
.biClrUsed
- colors
) * sizeof(RGBQUAD
) );
303 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
305 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
306 const int bpp
= info
->bmiHeader
.biBitCount
;
309 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
311 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
314 static BOOL
build_rle_bitmap( BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
318 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
320 BYTE skip
, num
, data
;
321 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
323 if (clip
) *clip
= NULL
;
325 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
327 out_bits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, get_dib_image_size( info
) );
328 if (!out_bits
) goto fail
;
332 *clip
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
333 run
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
334 if (!*clip
|| !run
) goto fail
;
337 x
= left
= right
= 0;
340 while (i
< info
->bmiHeader
.biSizeImage
- 1)
343 data
= in_bits
[i
+ 1];
348 if (x
+ num
> width
) num
= width
- x
;
351 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
352 if (info
->bmiHeader
.biBitCount
== 8)
353 memset( out_ptr
, s
, num
);
358 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
359 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
364 /* this will write one too many if num is odd, but that doesn't matter */
365 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
375 if(left
!= right
&& clip
)
377 NtGdiSetRectRgn( run
, left
, y
, right
, y
+ 1 );
378 NtGdiCombineRgn( *clip
, run
, *clip
, RGN_OR
);
383 left
= right
= x
= 0;
392 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
394 if (x
> width
) x
= width
;
401 else /* data bytes of data */
404 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
405 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
406 skip
= (skip
+ 1) & ~1;
407 if (x
+ num
> width
) num
= width
- x
;
410 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
411 if (info
->bmiHeader
.biBitCount
== 8)
412 memcpy( out_ptr
, in_bits
+ i
, num
);
417 const BYTE
*in_ptr
= in_bits
+ i
;
418 for ( ; num
; num
--, x
++)
422 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
426 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
430 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
441 if (run
) DeleteObject( run
);
442 if (bits
->free
) bits
->free( bits
);
444 bits
->ptr
= out_bits
;
445 bits
->is_copy
= TRUE
;
446 bits
->free
= free_heap_bits
;
447 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
452 if (run
) DeleteObject( run
);
453 if (clip
&& *clip
) DeleteObject( *clip
);
454 HeapFree( GetProcessHeap(), 0, out_bits
);
460 INT CDECL
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
461 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
462 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
464 DC
*dc
= get_nulldrv_dc( dev
);
465 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
466 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
467 struct bitblt_coords src
, dst
;
468 struct gdi_image_bits src_bits
;
472 INT height
= abs( src_info
->bmiHeader
.biHeight
);
473 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
476 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
477 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
479 src_bits
.ptr
= (void*)bits
;
480 src_bits
.is_copy
= FALSE
;
481 src_bits
.free
= NULL
;
483 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
487 rect
.right
= xDst
+ widthDst
;
488 rect
.bottom
= yDst
+ heightDst
;
489 lp_to_dp( dc
, (POINT
*)&rect
, 2 );
492 dst
.width
= rect
.right
- rect
.left
;
493 dst
.height
= rect
.bottom
- rect
.top
;
495 if (dc
->attr
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
498 dst
.width
= -dst
.width
;
500 rop
&= ~NOMIRRORBITMAP
;
503 src
.width
= widthSrc
;
505 src
.height
= heightSrc
;
507 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
508 non_stretch_from_origin
= TRUE
;
510 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
512 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
513 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
516 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
518 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
519 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
524 if (dst
.width
< 0 && dst
.width
== src
.width
)
526 /* This is off-by-one, but that's what Windows does */
529 dst
.width
= -dst
.width
;
530 src
.width
= -src
.width
;
532 if (dst
.height
< 0 && dst
.height
== src
.height
)
536 dst
.height
= -dst
.height
;
537 src
.height
= -src
.height
;
541 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
543 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
545 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
546 src
.y
= -src
.height
- 1;
548 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
550 src
.visrect
.left
= 0;
551 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
553 src
.visrect
.bottom
= height
;
554 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
556 if (rop
== SRCCOPY
) ret
= height
;
557 else ret
= src_info
->bmiHeader
.biHeight
;
559 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
561 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
563 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
565 if (clip
) NtGdiOffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
567 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
568 copy_bitmapinfo( dst_info
, src_info
);
569 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
570 if (err
== ERROR_BAD_FORMAT
)
572 DWORD dst_colors
= dst_info
->bmiHeader
.biClrUsed
;
574 /* 1-bpp destination without a color table requires a fake 1-entry table
575 * that contains only the background color. There is no source DC to get
576 * it from, so the background is hardcoded to the default color. */
577 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_colors
)
579 static const RGBQUAD default_bg
= { 255, 255, 255 };
580 dst_info
->bmiColors
[0] = default_bg
;
581 dst_info
->bmiHeader
.biClrUsed
= 1;
584 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
)))
586 /* get rid of the fake 1-bpp table */
587 dst_info
->bmiHeader
.biClrUsed
= dst_colors
;
588 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
592 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
594 copy_bitmapinfo( src_info
, dst_info
);
595 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, dc
->attr
->stretch_blt_mode
);
596 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
601 if (src_bits
.free
) src_bits
.free( &src_bits
);
602 if (clip
) DeleteObject( clip
);
606 /***********************************************************************
607 * StretchDIBits (GDI32.@)
609 INT WINAPI DECLSPEC_HOTPATCH
StretchDIBits( HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
610 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
611 const void *bits
, const BITMAPINFO
*bmi
, UINT coloruse
,
614 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
615 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
621 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
623 SetLastError( ERROR_INVALID_PARAMETER
);
627 if ((dc
= get_dc_ptr( hdc
)))
630 physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
631 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
632 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
633 release_dc_ptr( dc
);
639 /******************************************************************************
640 * SetDIBits [GDI32.@]
642 * Sets pixels in a bitmap using colors from DIB.
645 * hdc [I] Handle to device context
646 * hbitmap [I] Handle to bitmap
647 * startscan [I] Starting scan line
648 * lines [I] Number of scan lines
649 * bits [I] Array of bitmap bits
650 * info [I] Address of structure with data
651 * coloruse [I] Type of color indexes to use
654 * Success: Number of scan lines copied
657 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
658 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
662 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
663 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
664 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
665 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
668 struct gdi_image_bits src_bits
;
669 struct bitblt_coords src
, dst
;
670 INT src_to_dst_offset
;
673 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
) || coloruse
> DIB_PAL_COLORS
)
675 SetLastError( ERROR_INVALID_PARAMETER
);
678 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
680 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
681 if (!masks
[0] || !masks
[1] || !masks
[2])
683 SetLastError( ERROR_INVALID_PARAMETER
);
688 src_bits
.ptr
= (void *)bits
;
689 src_bits
.is_copy
= FALSE
;
690 src_bits
.free
= NULL
;
691 src_bits
.param
= NULL
;
693 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
695 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, NTGDI_OBJ_BITMAP
))) return 0;
697 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
699 if (lines
== 0) goto done
;
700 else lines
= src_info
->bmiHeader
.biHeight
;
703 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
706 dst
.visrect
.left
= 0;
708 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
709 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
711 src
.visrect
.left
= 0;
713 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
714 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
716 if (src_info
->bmiHeader
.biHeight
> 0)
718 src_to_dst_offset
= -startscan
;
719 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
720 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
724 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
725 /* Unlike the bottom-up case, Windows doesn't limit lines. */
726 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
731 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
732 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
733 src
.visrect
= dst
.visrect
;
734 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
736 src
.x
= src
.visrect
.left
;
737 src
.y
= src
.visrect
.top
;
738 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
739 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
741 dst
.x
= dst
.visrect
.left
;
742 dst
.y
= dst
.visrect
.top
;
743 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
744 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
746 copy_bitmapinfo( dst_info
, src_info
);
748 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
749 if (err
== ERROR_BAD_FORMAT
)
751 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
752 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
757 if (src_bits
.free
) src_bits
.free( &src_bits
);
758 if (clip
) DeleteObject( clip
);
759 GDI_ReleaseObj( hbitmap
);
764 INT CDECL
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
765 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
766 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
768 DC
*dc
= get_nulldrv_dc( dev
);
769 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
770 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
771 struct bitblt_coords src
, dst
;
772 struct gdi_image_bits src_bits
;
780 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
781 height
= abs( src_info
->bmiHeader
.biHeight
);
783 src_bits
.ptr
= (void *)bits
;
784 src_bits
.is_copy
= FALSE
;
785 src_bits
.free
= NULL
;
787 if (!lines
) return 0;
788 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
790 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
794 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
795 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
796 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
801 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
805 if (startscan
>= height
) return 0;
806 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
808 /* map src to top-down coordinates with startscan as origin */
810 src
.y
= startscan
+ lines
- (y_src
+ cy
);
817 /* get rid of unnecessary lines */
818 if (src
.y
>= lines
) return 0;
822 else if (src
.y
>= lines
) return lines
;
824 src_info
->bmiHeader
.biHeight
= top_down
? -min( lines
, height
) : lines
;
825 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( src_info
);
828 src
.visrect
.left
= src
.x
;
829 src
.visrect
.top
= src
.y
;
830 src
.visrect
.right
= src
.x
+ cx
;
831 src
.visrect
.bottom
= src
.y
+ cy
;
834 rect
.right
= src_info
->bmiHeader
.biWidth
;
835 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
836 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
844 lp_to_dp( dc
, &pt
, 1 );
849 if (dc
->attr
->layout
& LAYOUT_RTL
) dst
.x
-= cx
- 1;
853 rect
.right
= dst
.x
+ cx
;
854 rect
.bottom
= dst
.y
+ cy
;
855 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
857 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
858 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
859 src
.visrect
= dst
.visrect
= rect
;
860 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
861 if (is_rect_empty( &dst
.visrect
)) goto done
;
862 if (clip
) NtGdiOffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
864 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
865 copy_bitmapinfo( dst_info
, src_info
);
866 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
867 if (err
== ERROR_BAD_FORMAT
)
869 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
870 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
875 if (src_bits
.free
) src_bits
.free( &src_bits
);
876 if (clip
) DeleteObject( clip
);
880 /***********************************************************************
881 * SetDIBitsToDevice (GDI32.@)
883 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
884 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
885 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
888 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
889 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
895 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
897 SetLastError( ERROR_INVALID_PARAMETER
);
901 if ((dc
= get_dc_ptr( hdc
)))
904 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
905 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
906 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
907 release_dc_ptr( dc
);
912 /***********************************************************************
913 * SetDIBColorTable (GDI32.@)
915 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
921 if (!(dc
= get_dc_ptr( hdc
))) return 0;
923 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, NTGDI_OBJ_BITMAP
)))
925 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
927 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
928 for (i
= 0; i
< result
; i
++)
930 bitmap
->color_table
[startpos
+ i
].rgbBlue
= colors
[i
].rgbBlue
;
931 bitmap
->color_table
[startpos
+ i
].rgbGreen
= colors
[i
].rgbGreen
;
932 bitmap
->color_table
[startpos
+ i
].rgbRed
= colors
[i
].rgbRed
;
933 bitmap
->color_table
[startpos
+ i
].rgbReserved
= 0;
936 GDI_ReleaseObj( dc
->hBitmap
);
938 if (result
) /* update colors of selected objects */
940 SetTextColor( hdc
, dc
->attr
->text_color
);
941 SetBkColor( hdc
, dc
->attr
->background_color
);
942 NtGdiSelectPen( hdc
, dc
->hPen
);
943 NtGdiSelectBrush( hdc
, dc
->hBrush
);
946 release_dc_ptr( dc
);
951 /***********************************************************************
952 * GetDIBColorTable (GDI32.@)
954 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
960 if (!(dc
= get_dc_ptr( hdc
))) return 0;
962 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, NTGDI_OBJ_BITMAP
)))
964 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
966 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
967 memcpy(colors
, bitmap
->color_table
+ startpos
, result
* sizeof(RGBQUAD
));
969 GDI_ReleaseObj( dc
->hBitmap
);
971 release_dc_ptr( dc
);
975 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
976 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
978 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
980 BITMAPINFOHEADER header
;
982 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
983 header
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
984 header
.biHeight
= bmp
->dib
.dsBm
.bmHeight
;
986 header
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
988 switch (header
.biBitCount
)
992 header
.biCompression
= BI_BITFIELDS
;
995 header
.biCompression
= BI_RGB
;
999 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
1000 header
.biXPelsPerMeter
= 0;
1001 header
.biYPelsPerMeter
= 0;
1002 header
.biClrUsed
= 0;
1003 header
.biClrImportant
= 0;
1005 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
1007 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
1009 coreheader
->bcWidth
= header
.biWidth
;
1010 coreheader
->bcHeight
= header
.biHeight
;
1011 coreheader
->bcPlanes
= header
.biPlanes
;
1012 coreheader
->bcBitCount
= header
.biBitCount
;
1015 info
->bmiHeader
= header
;
1017 return bmp
->dib
.dsBm
.bmHeight
;
1020 /************************************************************************
1023 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1025 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1027 assert( src
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
) );
1029 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1031 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1032 if (coloruse
== DIB_PAL_COLORS
)
1033 memcpy( core
->bmciColors
, src
->bmiColors
, src
->bmiHeader
.biClrUsed
* sizeof(WORD
) );
1037 for (i
= 0; i
< src
->bmiHeader
.biClrUsed
; i
++)
1039 core
->bmciColors
[i
].rgbtRed
= src
->bmiColors
[i
].rgbRed
;
1040 core
->bmciColors
[i
].rgbtGreen
= src
->bmiColors
[i
].rgbGreen
;
1041 core
->bmciColors
[i
].rgbtBlue
= src
->bmiColors
[i
].rgbBlue
;
1047 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1049 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1050 /* bitfields are always at bmiColors even in larger structures */
1051 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1052 else if (src
->bmiHeader
.biClrUsed
)
1054 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1057 if (coloruse
== DIB_PAL_COLORS
)
1058 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1060 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1061 memcpy( colorptr
, src
->bmiColors
, size
);
1066 const RGBQUAD
*get_default_color_table( int bpp
)
1068 static const RGBQUAD table_1
[2] =
1070 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1072 static const RGBQUAD table_4
[16] =
1074 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1075 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1076 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1077 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1079 static const RGBQUAD table_8
[256] =
1081 /* first and last 10 entries are the default system palette entries */
1082 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1083 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1084 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1085 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1086 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1087 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1088 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1089 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1090 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1091 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1092 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1093 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1094 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1095 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1096 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1097 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1098 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1099 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1100 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1101 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1102 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1103 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1104 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1105 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1106 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1107 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1108 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1109 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1110 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1111 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1112 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1113 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1114 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1115 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1116 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1117 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1118 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1119 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1120 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1121 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1122 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1123 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1124 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1125 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1126 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1127 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1128 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1129 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1130 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1131 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1132 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1133 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1134 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1135 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1136 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1137 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1138 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1139 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1140 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1141 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1142 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1143 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1144 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1145 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1150 case 1: return table_1
;
1151 case 4: return table_4
;
1152 case 8: return table_8
;
1153 default: return NULL
;
1157 void fill_default_color_table( BITMAPINFO
*info
)
1159 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1160 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1161 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1164 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1166 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1167 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1168 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1169 info
->bmiHeader
.biPlanes
= 1;
1170 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1171 info
->bmiHeader
.biCompression
= BI_RGB
;
1172 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
1173 info
->bmiHeader
.biXPelsPerMeter
= 0;
1174 info
->bmiHeader
.biYPelsPerMeter
= 0;
1175 info
->bmiHeader
.biClrUsed
= 0;
1176 info
->bmiHeader
.biClrImportant
= 0;
1179 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1181 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1182 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1183 unsigned int info_size
;
1185 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1187 info_size
= get_dib_info_size( info
, usage
);
1188 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ info
->bmiHeader
.biSizeImage
)))
1190 memcpy( ret
, info
, info_size
);
1191 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size( src_info
, usage
),
1192 info
->bmiHeader
.biSizeImage
);
1197 /******************************************************************************
1198 * GetDIBits [GDI32.@]
1200 * Retrieves bits of bitmap and copies to buffer.
1203 * Success: Number of scan lines copied from bitmap
1206 INT WINAPI DECLSPEC_HOTPATCH
GetDIBits(
1207 HDC hdc
, /* [in] Handle to device context */
1208 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1209 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1210 UINT lines
, /* [in] Number of scan lines to copy */
1211 LPVOID bits
, /* [out] Address of array for bitmap bits */
1212 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1213 UINT coloruse
) /* [in] RGB or palette index */
1217 int i
, dst_to_src_offset
, ret
= 0;
1219 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1220 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1221 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1222 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1223 struct gdi_image_bits src_bits
;
1224 struct bitblt_coords src
, dst
;
1225 BOOL empty_rect
= FALSE
;
1227 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1228 own copy and transfer the colour info back at the end */
1229 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1230 if (coloruse
> DIB_PAL_COLORS
) return 0;
1232 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1234 dst_info
->bmiHeader
.biClrUsed
= 0;
1235 dst_info
->bmiHeader
.biClrImportant
= 0;
1237 if (!(dc
= get_dc_ptr( hdc
)))
1239 SetLastError( ERROR_INVALID_PARAMETER
);
1243 if (!(bmp
= GDI_GetObjPtr( hbitmap
, NTGDI_OBJ_BITMAP
)))
1245 release_dc_ptr( dc
);
1249 src
.visrect
.left
= 0;
1250 src
.visrect
.top
= 0;
1251 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1252 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1254 dst
.visrect
.left
= 0;
1255 dst
.visrect
.top
= 0;
1256 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1257 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1259 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1262 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1264 ret
= fill_query_info( info
, bmp
);
1268 /* validate parameters */
1270 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1271 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1273 switch (dst_info
->bmiHeader
.biCompression
)
1276 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1277 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1278 if (bits
) goto done
; /* can't retrieve compressed bits */
1281 if (dst_info
->bmiHeader
.biBitCount
!= 8) 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
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1289 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1290 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1291 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1292 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1293 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1294 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1295 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1303 if (dst_info
->bmiHeader
.biHeight
> 0)
1305 dst_to_src_offset
= -startscan
;
1306 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1307 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1311 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1312 if (dst_to_src_offset
< 0)
1314 dst_to_src_offset
= 0;
1315 lines
= dst
.visrect
.bottom
- startscan
;
1317 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1320 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1321 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1322 dst
.visrect
= src
.visrect
;
1323 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1325 if (dst_info
->bmiHeader
.biHeight
> 0)
1327 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1329 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1330 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1331 memset( bits
, 0, pad_bytes
);
1332 bits
= (char *)bits
+ pad_bytes
;
1337 if (dst
.visrect
.bottom
< lines
)
1339 int pad_lines
= lines
- dst
.visrect
.bottom
;
1340 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1341 int pad_bytes
= pad_lines
* stride
;
1342 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1346 if (empty_rect
) bits
= NULL
;
1348 src
.x
= src
.visrect
.left
;
1349 src
.y
= src
.visrect
.top
;
1350 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1351 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1356 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1360 /* fill out the src colour table, if it needs one */
1361 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1362 fill_default_color_table( src_info
);
1364 /* if the src and dst are the same depth, copy the colour info across */
1365 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1367 switch (src_info
->bmiHeader
.biBitCount
)
1370 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1372 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1373 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1377 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1379 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1380 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1384 copy_color_info( dst_info
, src_info
, coloruse
);
1386 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1388 if( coloruse
== DIB_PAL_COLORS
)
1390 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1394 fill_default_color_table( dst_info
);
1400 if(dst_info
->bmiHeader
.biHeight
> 0)
1401 dst_info
->bmiHeader
.biHeight
= src
.height
;
1403 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1404 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1406 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1407 if (src_bits
.free
) src_bits
.free( &src_bits
);
1413 if (coloruse
== DIB_PAL_COLORS
)
1415 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1416 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1420 copy_color_info( info
, dst_info
, coloruse
);
1421 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
1423 info
->bmiHeader
.biClrUsed
= 0;
1424 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
1428 release_dc_ptr( dc
);
1429 GDI_ReleaseObj( hbitmap
);
1434 /***********************************************************************
1435 * CreateDIBitmap (GDI32.@)
1437 * Creates a DDB (device dependent bitmap) from a DIB.
1438 * The DDB will have the same color depth as the reference DC.
1440 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1441 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1444 BITMAPINFOHEADER info
;
1448 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1449 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1450 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1451 if (info
.biWidth
< 0) return 0;
1453 /* Top-down DIBs have a negative height */
1454 height
= abs( info
.biHeight
);
1456 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1457 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1458 info
.biBitCount
, info
.biCompression
);
1461 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1463 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1467 if (init
& CBM_INIT
)
1469 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1471 DeleteObject( handle
);
1481 /***********************************************************************
1482 * CreateDIBSection (GDI32.@)
1484 HBITMAP WINAPI DECLSPEC_HOTPATCH
CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
1485 void **bits
, HANDLE section
, DWORD offset
)
1487 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1488 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1491 void *mapBits
= NULL
;
1493 if (bits
) *bits
= NULL
;
1494 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1495 if (usage
> DIB_PAL_COLORS
) return 0;
1496 if (info
->bmiHeader
.biPlanes
!= 1)
1498 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1499 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1502 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1504 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1505 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1506 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1507 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1508 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1510 bmp
->dib
.dsBm
.bmType
= 0;
1511 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1512 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1513 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1514 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1515 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1516 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1518 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1520 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1522 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1523 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1524 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1526 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1529 /* set dsBitfields values */
1530 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1532 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1533 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1534 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1535 bmp
->dib
.dsBitfields
[2] = 0x001f;
1537 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1539 if (usage
== DIB_PAL_COLORS
) goto error
;
1540 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1541 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1542 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1543 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1545 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1547 /* get storage location for DIB bits */
1551 SYSTEM_INFO SystemInfo
;
1555 GetSystemInfo( &SystemInfo
);
1556 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1557 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1558 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1559 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1564 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1565 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1567 bmp
->dib
.dshSection
= section
;
1568 bmp
->dib
.dsOffset
= offset
;
1570 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1572 if (!(ret
= alloc_gdi_handle( &bmp
->obj
, NTGDI_OBJ_BITMAP
, &dib_funcs
))) goto error
;
1574 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1578 if (section
) UnmapViewOfFile( mapBits
);
1579 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1580 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1581 HeapFree( GetProcessHeap(), 0, bmp
);
1586 /***********************************************************************
1587 * D3DKMTCreateDCFromMemory (GDI32.@)
1589 NTSTATUS WINAPI
D3DKMTCreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY
*desc
)
1591 const struct d3dddi_format_info
1593 D3DDDIFORMAT format
;
1594 unsigned int bit_count
;
1596 unsigned int palette_size
;
1597 DWORD mask_r
, mask_g
, mask_b
;
1599 BITMAPOBJ
*bmp
= NULL
;
1604 static const struct d3dddi_format_info format_info
[] =
1606 { D3DDDIFMT_R8G8B8
, 24, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1607 { D3DDDIFMT_A8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1608 { D3DDDIFMT_X8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1609 { D3DDDIFMT_R5G6B5
, 16, BI_BITFIELDS
, 0, 0x0000f800, 0x000007e0, 0x0000001f },
1610 { D3DDDIFMT_X1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1611 { D3DDDIFMT_A1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1612 { D3DDDIFMT_A4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1613 { D3DDDIFMT_X4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1614 { D3DDDIFMT_P8
, 8, BI_RGB
, 256, 0x00000000, 0x00000000, 0x00000000 },
1617 if (!desc
) return STATUS_INVALID_PARAMETER
;
1619 TRACE("memory %p, format %#x, width %u, height %u, pitch %u, device dc %p, color table %p.\n",
1620 desc
->pMemory
, desc
->Format
, desc
->Width
, desc
->Height
,
1621 desc
->Pitch
, desc
->hDeviceDc
, desc
->pColorTable
);
1623 if (!desc
->pMemory
) return STATUS_INVALID_PARAMETER
;
1625 for (i
= 0; i
< ARRAY_SIZE( format_info
); ++i
)
1627 if (format_info
[i
].format
== desc
->Format
)
1629 format
= &format_info
[i
];
1633 if (!format
) return STATUS_INVALID_PARAMETER
;
1635 if (desc
->Width
> (UINT_MAX
& ~3) / (format
->bit_count
/ 8) ||
1636 !desc
->Pitch
|| desc
->Pitch
< get_dib_stride( desc
->Width
, format
->bit_count
) ||
1637 !desc
->Height
|| desc
->Height
> UINT_MAX
/ desc
->Pitch
) return STATUS_INVALID_PARAMETER
;
1639 if (!desc
->hDeviceDc
|| !(dc
= NtGdiCreateCompatibleDC( desc
->hDeviceDc
)))
1640 return STATUS_INVALID_PARAMETER
;
1642 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) goto error
;
1644 bmp
->dib
.dsBm
.bmWidth
= desc
->Width
;
1645 bmp
->dib
.dsBm
.bmHeight
= desc
->Height
;
1646 bmp
->dib
.dsBm
.bmWidthBytes
= desc
->Pitch
;
1647 bmp
->dib
.dsBm
.bmPlanes
= 1;
1648 bmp
->dib
.dsBm
.bmBitsPixel
= format
->bit_count
;
1649 bmp
->dib
.dsBm
.bmBits
= desc
->pMemory
;
1651 bmp
->dib
.dsBmih
.biSize
= sizeof(bmp
->dib
.dsBmih
);
1652 bmp
->dib
.dsBmih
.biWidth
= desc
->Width
;
1653 bmp
->dib
.dsBmih
.biHeight
= -(LONG
)desc
->Height
;
1654 bmp
->dib
.dsBmih
.biPlanes
= 1;
1655 bmp
->dib
.dsBmih
.biBitCount
= format
->bit_count
;
1656 bmp
->dib
.dsBmih
.biCompression
= format
->compression
;
1657 bmp
->dib
.dsBmih
.biClrUsed
= format
->palette_size
;
1658 bmp
->dib
.dsBmih
.biClrImportant
= format
->palette_size
;
1660 bmp
->dib
.dsBitfields
[0] = format
->mask_r
;
1661 bmp
->dib
.dsBitfields
[1] = format
->mask_g
;
1662 bmp
->dib
.dsBitfields
[2] = format
->mask_b
;
1664 if (format
->palette_size
)
1666 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0, format
->palette_size
* sizeof(*bmp
->color_table
) )))
1668 if (desc
->pColorTable
)
1670 for (i
= 0; i
< format
->palette_size
; ++i
)
1672 bmp
->color_table
[i
].rgbRed
= desc
->pColorTable
[i
].peRed
;
1673 bmp
->color_table
[i
].rgbGreen
= desc
->pColorTable
[i
].peGreen
;
1674 bmp
->color_table
[i
].rgbBlue
= desc
->pColorTable
[i
].peBlue
;
1675 bmp
->color_table
[i
].rgbReserved
= 0;
1680 memcpy( bmp
->color_table
, get_default_color_table( format
->bit_count
),
1681 format
->palette_size
* sizeof(*bmp
->color_table
) );
1685 if (!(bitmap
= alloc_gdi_handle( &bmp
->obj
, NTGDI_OBJ_BITMAP
, &dib_funcs
))) goto error
;
1688 desc
->hBitmap
= bitmap
;
1689 NtGdiSelectBitmap( dc
, bitmap
);
1690 return STATUS_SUCCESS
;
1693 if (bmp
) HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1694 HeapFree( GetProcessHeap(), 0, bmp
);
1696 return STATUS_INVALID_PARAMETER
;
1700 /***********************************************************************
1701 * D3DKMTDestroyDCFromMemory (GDI32.@)
1703 NTSTATUS WINAPI
D3DKMTDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY
*desc
)
1705 if (!desc
) return STATUS_INVALID_PARAMETER
;
1707 TRACE("dc %p, bitmap %p.\n", desc
->hDc
, desc
->hBitmap
);
1709 if (GetObjectType( desc
->hDc
) != OBJ_MEMDC
||
1710 GetObjectType( desc
->hBitmap
) != OBJ_BITMAP
) return STATUS_INVALID_PARAMETER
;
1711 DeleteObject( desc
->hBitmap
);
1712 DeleteDC( desc
->hDc
);
1714 return STATUS_SUCCESS
;
1718 /***********************************************************************
1721 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1724 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, NTGDI_OBJ_BITMAP
);
1728 if (!buffer
) ret
= sizeof(BITMAP
);
1729 else if (count
>= sizeof(DIBSECTION
))
1731 DIBSECTION
*dib
= buffer
;
1733 dib
->dsBm
.bmWidthBytes
= get_dib_stride( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmBitsPixel
);
1734 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1735 ret
= sizeof(DIBSECTION
);
1737 else if (count
>= sizeof(BITMAP
))
1739 BITMAP
*bitmap
= buffer
;
1740 *bitmap
= bmp
->dib
.dsBm
;
1741 bitmap
->bmWidthBytes
= get_dib_stride( bitmap
->bmWidth
, bitmap
->bmBitsPixel
);
1742 ret
= sizeof(BITMAP
);
1745 GDI_ReleaseObj( handle
);
1750 /***********************************************************************
1753 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1757 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1759 if (bmp
->dib
.dshSection
)
1761 SYSTEM_INFO SystemInfo
;
1762 GetSystemInfo( &SystemInfo
);
1763 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1764 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1766 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1768 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1769 HeapFree( GetProcessHeap(), 0, bmp
);