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
72 #define WIN32_NO_STATUS
77 #include "ddk/d3dkmthk.h"
79 #include "ntgdi_private.h"
80 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
85 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
86 static BOOL
DIB_DeleteObject( HGDIOBJ handle
);
88 static const struct gdi_obj_funcs dib_funcs
=
90 DIB_GetObject
, /* pGetObjectW */
91 NULL
, /* pUnrealizeObject */
92 DIB_DeleteObject
/* pDeleteObject */
95 /***********************************************************************
98 * Return the size of the bitmap info structure including color table.
100 static int bitmap_info_size( const BITMAPINFO
*info
, WORD coloruse
)
102 unsigned int colors
, size
, masks
= 0;
104 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
106 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
107 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
108 return sizeof(BITMAPCOREHEADER
) + colors
*
109 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
111 else /* assume BITMAPINFOHEADER */
113 if (info
->bmiHeader
.biClrUsed
) colors
= min( info
->bmiHeader
.biClrUsed
, 256 );
114 else colors
= info
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << info
->bmiHeader
.biBitCount
;
115 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
116 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
117 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
121 /*******************************************************************************************
122 * Verify that the DIB parameters are valid.
124 static BOOL
is_valid_dib_format( const BITMAPINFOHEADER
*info
, BOOL allow_compression
)
126 if (info
->biWidth
<= 0) return FALSE
;
127 if (info
->biHeight
== 0) return FALSE
;
129 if (allow_compression
&& (info
->biCompression
== BI_RLE4
|| info
->biCompression
== BI_RLE8
))
131 if (info
->biHeight
< 0) return FALSE
;
132 if (!info
->biSizeImage
) return FALSE
;
133 return info
->biBitCount
== (info
->biCompression
== BI_RLE4
? 4 : 8);
136 if (!info
->biPlanes
) return FALSE
;
138 /* check for size overflow */
139 if (!info
->biBitCount
) return FALSE
;
140 if (UINT_MAX
/ info
->biBitCount
< info
->biWidth
) return FALSE
;
141 if (UINT_MAX
/ get_dib_stride( info
->biWidth
, info
->biBitCount
) < abs( info
->biHeight
)) return FALSE
;
143 switch (info
->biBitCount
)
149 return (info
->biCompression
== BI_RGB
);
152 return (info
->biCompression
== BI_BITFIELDS
|| info
->biCompression
== BI_RGB
);
158 /*******************************************************************************************
159 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
161 static BOOL
bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER
*dst
, const BITMAPINFOHEADER
*info
)
163 if (!info
) return FALSE
;
165 if (info
->biSize
== sizeof(BITMAPCOREHEADER
))
167 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
168 dst
->biWidth
= core
->bcWidth
;
169 dst
->biHeight
= core
->bcHeight
;
170 dst
->biPlanes
= core
->bcPlanes
;
171 dst
->biBitCount
= core
->bcBitCount
;
172 dst
->biCompression
= BI_RGB
;
173 dst
->biXPelsPerMeter
= 0;
174 dst
->biYPelsPerMeter
= 0;
176 dst
->biClrImportant
= 0;
178 else if (info
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
184 WARN( "(%u): unknown/wrong size for header\n", info
->biSize
);
188 dst
->biSize
= sizeof(*dst
);
189 if (dst
->biCompression
== BI_RGB
|| dst
->biCompression
== BI_BITFIELDS
)
190 dst
->biSizeImage
= get_dib_image_size( (BITMAPINFO
*)dst
);
194 /*******************************************************************************************
195 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
197 * The resulting sanitized BITMAPINFO is guaranteed to have:
198 * - biSize set to sizeof(BITMAPINFOHEADER)
199 * - biSizeImage set to the actual image size even for non-compressed DIB
200 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
201 * - color table present only for <= 8 bpp, always starts at info->bmiColors
203 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
,
204 UINT coloruse
, BOOL allow_compression
)
208 if (coloruse
> DIB_PAL_COLORS
+ 1) return FALSE
; /* FIXME: handle DIB_PAL_COLORS+1 format */
209 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
210 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
212 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
214 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
216 /* bitfields are always at bmiColors even in larger structures */
217 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
218 dst
->bmiHeader
.biClrUsed
= 0;
220 else if (dst
->bmiHeader
.biBitCount
<= 8)
222 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
223 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
225 if (!colors
) colors
= max_colors
;
226 else colors
= min( colors
, max_colors
);
228 if (coloruse
== DIB_PAL_COLORS
)
230 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
233 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
235 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
240 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
241 for (i
= 0; i
< colors
; i
++)
243 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
244 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
245 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
246 dst
->bmiColors
[i
].rgbReserved
= 0;
249 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
250 dst
->bmiHeader
.biClrUsed
= max_colors
;
252 else dst
->bmiHeader
.biClrUsed
= 0;
257 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
259 PALETTEENTRY palEntry
[256];
260 HPALETTE palette
= NtGdiGetDCObject( hdc
, NTGDI_OBJ_PAL
);
261 int i
, colors
= 1 << info
->bmiHeader
.biBitCount
;
263 info
->bmiHeader
.biClrUsed
= colors
;
265 if (!palette
) return 0;
267 memset( palEntry
, 0, sizeof(palEntry
) );
268 if (!get_palette_entries( palette
, 0, colors
, palEntry
))
271 for (i
= 0; i
< colors
; i
++)
273 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
274 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
275 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
276 info
->bmiColors
[i
].rgbReserved
= 0;
282 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
284 PALETTEENTRY entries
[256];
287 const WORD
*index
= (const WORD
*)info
->bmiColors
;
288 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
290 if (!colors
) return TRUE
;
291 if (!(palette
= NtGdiGetDCObject( hdc
, NTGDI_OBJ_PAL
)))
293 if (!(count
= get_palette_entries( 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
= calloc( 1, get_dib_image_size( info
) );
333 if (!out_bits
) goto fail
;
337 *clip
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
338 run
= NtGdiCreateRectRgn( 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 NtGdiSetRectRgn( run
, left
, y
, right
, y
+ 1 );
383 NtGdiCombineRgn( *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
) NtGdiDeleteObjectApp( 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
) NtGdiDeleteObjectApp( run
);
458 if (clip
&& *clip
) NtGdiDeleteObjectApp( *clip
);
465 INT CDECL
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
->attr
->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
) NtGdiOffsetRgn( 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
->attr
->stretch_blt_mode
);
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
) NtGdiDeleteObjectApp( clip
);
611 /***********************************************************************
612 * NtGdiStretchDIBitsInternal (win32u.@)
614 INT WINAPI
NtGdiStretchDIBitsInternal( 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
,
617 DWORD rop
, UINT max_info
, UINT max_bits
, HANDLE xform
)
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
, NTGDI_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 OffsetRect( &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 OffsetRect( &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
) NtGdiDeleteObjectApp( clip
);
764 GDI_ReleaseObj( hbitmap
);
769 INT CDECL
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
? -min( lines
, height
) : 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
->attr
->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 OffsetRect( &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 OffsetRect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
866 if (IsRectEmpty( &dst
.visrect
)) goto done
;
867 if (clip
) NtGdiOffsetRgn( 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
) NtGdiDeleteObjectApp( clip
);
885 /***********************************************************************
886 * NtGdiSetDIBitsToDeviceInternal (win32u.@)
888 INT WINAPI
NtGdiSetDIBitsToDeviceInternal( HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
889 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
890 UINT lines
, const void *bits
, const BITMAPINFO
*bmi
,
891 UINT coloruse
, UINT max_bits
, UINT max_info
,
892 BOOL xform_coords
, HANDLE xform
)
894 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
895 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
901 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
903 SetLastError( ERROR_INVALID_PARAMETER
);
907 if ((dc
= get_dc_ptr( hdc
)))
910 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
911 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
912 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
913 release_dc_ptr( dc
);
918 UINT
set_dib_dc_color_table( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
924 if (!(dc
= get_dc_ptr( hdc
))) return 0;
926 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, NTGDI_OBJ_BITMAP
)))
928 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
930 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
931 for (i
= 0; i
< result
; i
++)
933 bitmap
->color_table
[startpos
+ i
].rgbBlue
= colors
[i
].rgbBlue
;
934 bitmap
->color_table
[startpos
+ i
].rgbGreen
= colors
[i
].rgbGreen
;
935 bitmap
->color_table
[startpos
+ i
].rgbRed
= colors
[i
].rgbRed
;
936 bitmap
->color_table
[startpos
+ i
].rgbReserved
= 0;
939 GDI_ReleaseObj( dc
->hBitmap
);
941 if (result
) /* update colors of selected objects */
943 NtGdiGetAndSetDCDword( hdc
, NtGdiSetTextColor
, dc
->attr
->text_color
, NULL
);
944 NtGdiGetAndSetDCDword( hdc
, NtGdiSetBkColor
, dc
->attr
->background_color
, NULL
);
945 NtGdiSelectPen( hdc
, dc
->hPen
);
946 NtGdiSelectBrush( hdc
, dc
->hBrush
);
949 release_dc_ptr( dc
);
954 UINT
get_dib_dc_color_table( 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
= malloc( 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 * NtGdiGetDIBitsInternal (win32u.@)
1200 * Retrieves bits of bitmap and copies to buffer.
1202 INT WINAPI
NtGdiGetDIBitsInternal( HDC hdc
, HBITMAP hbitmap
, UINT startscan
, UINT lines
,
1203 void *bits
, BITMAPINFO
*info
, UINT coloruse
,
1204 UINT max_bits
, UINT max_info
)
1208 int i
, dst_to_src_offset
, ret
= 0;
1210 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1211 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1212 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1213 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1214 struct gdi_image_bits src_bits
;
1215 struct bitblt_coords src
, dst
;
1216 BOOL empty_rect
= FALSE
;
1218 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1219 own copy and transfer the colour info back at the end */
1220 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1221 if (coloruse
> DIB_PAL_COLORS
) return 0;
1223 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1225 dst_info
->bmiHeader
.biClrUsed
= 0;
1226 dst_info
->bmiHeader
.biClrImportant
= 0;
1228 if (!(dc
= get_dc_ptr( hdc
)))
1230 SetLastError( ERROR_INVALID_PARAMETER
);
1234 if (!(bmp
= GDI_GetObjPtr( hbitmap
, NTGDI_OBJ_BITMAP
)))
1236 release_dc_ptr( dc
);
1240 src
.visrect
.left
= 0;
1241 src
.visrect
.top
= 0;
1242 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1243 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1245 dst
.visrect
.left
= 0;
1246 dst
.visrect
.top
= 0;
1247 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1248 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1250 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1253 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1255 ret
= fill_query_info( info
, bmp
);
1259 /* validate parameters */
1261 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1262 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1264 switch (dst_info
->bmiHeader
.biCompression
)
1267 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1268 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1269 if (bits
) goto done
; /* can't retrieve compressed bits */
1272 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1273 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1274 if (bits
) goto done
; /* can't retrieve compressed bits */
1277 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1280 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1281 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1282 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1283 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1284 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1285 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1286 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1294 if (dst_info
->bmiHeader
.biHeight
> 0)
1296 dst_to_src_offset
= -startscan
;
1297 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1298 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1302 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1303 if (dst_to_src_offset
< 0)
1305 dst_to_src_offset
= 0;
1306 lines
= dst
.visrect
.bottom
- startscan
;
1308 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1311 OffsetRect( &dst
.visrect
, 0, dst_to_src_offset
);
1312 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1313 dst
.visrect
= src
.visrect
;
1314 OffsetRect( &dst
.visrect
, 0, -dst_to_src_offset
);
1316 if (dst_info
->bmiHeader
.biHeight
> 0)
1318 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1320 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1321 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1322 memset( bits
, 0, pad_bytes
);
1323 bits
= (char *)bits
+ pad_bytes
;
1328 if (dst
.visrect
.bottom
< lines
)
1330 int pad_lines
= lines
- dst
.visrect
.bottom
;
1331 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1332 int pad_bytes
= pad_lines
* stride
;
1333 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1337 if (empty_rect
) bits
= NULL
;
1339 src
.x
= src
.visrect
.left
;
1340 src
.y
= src
.visrect
.top
;
1341 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1342 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1347 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1351 /* fill out the src colour table, if it needs one */
1352 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1353 fill_default_color_table( src_info
);
1355 /* if the src and dst are the same depth, copy the colour info across */
1356 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1358 switch (src_info
->bmiHeader
.biBitCount
)
1361 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1363 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1364 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1368 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1370 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1371 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1375 copy_color_info( dst_info
, src_info
, coloruse
);
1377 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1379 if( coloruse
== DIB_PAL_COLORS
)
1381 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1385 fill_default_color_table( dst_info
);
1391 if(dst_info
->bmiHeader
.biHeight
> 0)
1392 dst_info
->bmiHeader
.biHeight
= src
.height
;
1394 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1395 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1397 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1398 if (src_bits
.free
) src_bits
.free( &src_bits
);
1404 if (coloruse
== DIB_PAL_COLORS
)
1406 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1407 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1411 copy_color_info( info
, dst_info
, coloruse
);
1412 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
1414 info
->bmiHeader
.biClrUsed
= 0;
1415 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
1419 release_dc_ptr( dc
);
1420 GDI_ReleaseObj( hbitmap
);
1425 /***********************************************************************
1426 * NtGdiCreateDIBitmapInternal (win32u.@)
1428 * Creates a DDB (device dependent bitmap) from a DIB.
1429 * The DDB will have the same color depth as the reference DC.
1431 HBITMAP WINAPI
NtGdiCreateDIBitmapInternal( HDC hdc
, INT width
, INT height
, DWORD init
,
1432 const void *bits
, const BITMAPINFO
*data
,
1433 UINT coloruse
, UINT max_info
, UINT max_bits
,
1434 ULONG flags
, HANDLE xform
)
1438 if (coloruse
> DIB_PAL_COLORS
+ 1 || width
< 0) return 0;
1440 /* Top-down DIBs have a negative height */
1441 height
= abs( height
);
1443 TRACE( "hdc=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d)\n",
1444 hdc
, init
, bits
, data
, coloruse
, width
, height
);
1447 handle
= NtGdiCreateBitmap( width
, height
, 1, 1, NULL
);
1449 handle
= NtGdiCreateCompatibleBitmap( hdc
, width
, height
);
1453 if (init
& CBM_INIT
)
1455 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1457 NtGdiDeleteObjectApp( handle
);
1467 /***********************************************************************
1468 * NtGdiCreateDIBSection (win32u.@)
1470 HBITMAP WINAPI
NtGdiCreateDIBSection( HDC hdc
, HANDLE section
, DWORD offset
, const BITMAPINFO
*bmi
,
1471 UINT usage
, UINT header_size
, ULONG flags
,
1472 ULONG_PTR color_space
, void **bits
)
1474 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1475 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1478 void *mapBits
= NULL
;
1480 if (bits
) *bits
= NULL
;
1481 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1482 if (usage
> DIB_PAL_COLORS
) return 0;
1483 if (info
->bmiHeader
.biPlanes
!= 1)
1485 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1486 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1489 if (!(bmp
= calloc( 1, sizeof(*bmp
) ))) return 0;
1491 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1492 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1493 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1494 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1495 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1497 bmp
->dib
.dsBm
.bmType
= 0;
1498 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1499 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1500 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1501 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1502 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1503 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1505 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1507 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1509 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1510 if (!(bmp
->color_table
= malloc( bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1512 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1515 /* set dsBitfields values */
1516 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1518 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1519 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1520 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1521 bmp
->dib
.dsBitfields
[2] = 0x001f;
1523 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1525 if (usage
== DIB_PAL_COLORS
) goto error
;
1526 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1527 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1528 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1529 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1531 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1533 /* get storage location for DIB bits */
1537 LARGE_INTEGER map_offset
;
1540 map_offset
.QuadPart
= offset
- (offset
% system_info
.AllocationGranularity
);
1541 map_size
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- map_offset
.QuadPart
);
1542 if (NtMapViewOfSection( section
, GetCurrentProcess(), &mapBits
, 0, 0, &map_offset
,
1543 &map_size
, ViewShare
, 0, PAGE_READWRITE
))
1545 bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- map_offset
.QuadPart
);
1549 SIZE_T size
= bmp
->dib
.dsBmih
.biSizeImage
;
1551 if (NtAllocateVirtualMemory( GetCurrentProcess(), &bmp
->dib
.dsBm
.bmBits
, zero_bits(),
1552 &size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
))
1555 bmp
->dib
.dshSection
= section
;
1556 bmp
->dib
.dsOffset
= offset
;
1558 if ((ret
= alloc_gdi_handle( &bmp
->obj
, NTGDI_OBJ_BITMAP
, &dib_funcs
)))
1560 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1564 if (section
) NtUnmapViewOfSection( GetCurrentProcess(), mapBits
);
1568 NtFreeVirtualMemory( GetCurrentProcess(), &bmp
->dib
.dsBm
.bmBits
, &size
, MEM_RELEASE
);
1571 free( bmp
->color_table
);
1577 static BOOL
memory_dib_DeleteObject( HGDIOBJ handle
)
1581 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1583 free( bmp
->color_table
);
1589 static const struct gdi_obj_funcs memory_dib_funcs
=
1591 .pGetObjectW
= DIB_GetObject
,
1592 .pDeleteObject
= memory_dib_DeleteObject
,
1595 /***********************************************************************
1596 * NtGdiDdDDICreateDCFromMemory (win32u.@)
1598 NTSTATUS WINAPI
NtGdiDdDDICreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY
*desc
)
1600 const struct d3dddi_format_info
1602 D3DDDIFORMAT format
;
1603 unsigned int bit_count
;
1605 unsigned int palette_size
;
1606 DWORD mask_r
, mask_g
, mask_b
;
1608 BITMAPOBJ
*bmp
= NULL
;
1613 static const struct d3dddi_format_info format_info
[] =
1615 { D3DDDIFMT_R8G8B8
, 24, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1616 { D3DDDIFMT_A8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1617 { D3DDDIFMT_X8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1618 { D3DDDIFMT_R5G6B5
, 16, BI_BITFIELDS
, 0, 0x0000f800, 0x000007e0, 0x0000001f },
1619 { D3DDDIFMT_X1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1620 { D3DDDIFMT_A1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1621 { D3DDDIFMT_A4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1622 { D3DDDIFMT_X4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1623 { D3DDDIFMT_P8
, 8, BI_RGB
, 256, 0x00000000, 0x00000000, 0x00000000 },
1626 if (!desc
) return STATUS_INVALID_PARAMETER
;
1628 TRACE("memory %p, format %#x, width %u, height %u, pitch %u, device dc %p, color table %p.\n",
1629 desc
->pMemory
, desc
->Format
, desc
->Width
, desc
->Height
,
1630 desc
->Pitch
, desc
->hDeviceDc
, desc
->pColorTable
);
1632 if (!desc
->pMemory
) return STATUS_INVALID_PARAMETER
;
1634 for (i
= 0; i
< ARRAY_SIZE( format_info
); ++i
)
1636 if (format_info
[i
].format
== desc
->Format
)
1638 format
= &format_info
[i
];
1642 if (!format
) return STATUS_INVALID_PARAMETER
;
1644 if (desc
->Width
> (UINT_MAX
& ~3) / (format
->bit_count
/ 8) ||
1645 !desc
->Pitch
|| desc
->Pitch
< get_dib_stride( desc
->Width
, format
->bit_count
) ||
1646 !desc
->Height
|| desc
->Height
> UINT_MAX
/ desc
->Pitch
) return STATUS_INVALID_PARAMETER
;
1648 if (!desc
->hDeviceDc
|| !(dc
= NtGdiCreateCompatibleDC( desc
->hDeviceDc
)))
1649 return STATUS_INVALID_PARAMETER
;
1651 if (!(bmp
= calloc( 1, sizeof(*bmp
) ))) goto error
;
1653 bmp
->dib
.dsBm
.bmWidth
= desc
->Width
;
1654 bmp
->dib
.dsBm
.bmHeight
= desc
->Height
;
1655 bmp
->dib
.dsBm
.bmWidthBytes
= desc
->Pitch
;
1656 bmp
->dib
.dsBm
.bmPlanes
= 1;
1657 bmp
->dib
.dsBm
.bmBitsPixel
= format
->bit_count
;
1658 bmp
->dib
.dsBm
.bmBits
= desc
->pMemory
;
1660 bmp
->dib
.dsBmih
.biSize
= sizeof(bmp
->dib
.dsBmih
);
1661 bmp
->dib
.dsBmih
.biWidth
= desc
->Width
;
1662 bmp
->dib
.dsBmih
.biHeight
= -(LONG
)desc
->Height
;
1663 bmp
->dib
.dsBmih
.biPlanes
= 1;
1664 bmp
->dib
.dsBmih
.biBitCount
= format
->bit_count
;
1665 bmp
->dib
.dsBmih
.biCompression
= format
->compression
;
1666 bmp
->dib
.dsBmih
.biClrUsed
= format
->palette_size
;
1667 bmp
->dib
.dsBmih
.biClrImportant
= format
->palette_size
;
1669 bmp
->dib
.dsBitfields
[0] = format
->mask_r
;
1670 bmp
->dib
.dsBitfields
[1] = format
->mask_g
;
1671 bmp
->dib
.dsBitfields
[2] = format
->mask_b
;
1673 if (format
->palette_size
)
1675 if (!(bmp
->color_table
= malloc( format
->palette_size
* sizeof(*bmp
->color_table
) )))
1677 if (desc
->pColorTable
)
1679 for (i
= 0; i
< format
->palette_size
; ++i
)
1681 bmp
->color_table
[i
].rgbRed
= desc
->pColorTable
[i
].peRed
;
1682 bmp
->color_table
[i
].rgbGreen
= desc
->pColorTable
[i
].peGreen
;
1683 bmp
->color_table
[i
].rgbBlue
= desc
->pColorTable
[i
].peBlue
;
1684 bmp
->color_table
[i
].rgbReserved
= 0;
1689 memcpy( bmp
->color_table
, get_default_color_table( format
->bit_count
),
1690 format
->palette_size
* sizeof(*bmp
->color_table
) );
1694 if (!(bitmap
= alloc_gdi_handle( &bmp
->obj
, NTGDI_OBJ_BITMAP
, &memory_dib_funcs
))) goto error
;
1697 desc
->hBitmap
= bitmap
;
1698 NtGdiSelectBitmap( dc
, bitmap
);
1699 return STATUS_SUCCESS
;
1702 if (bmp
) free( bmp
->color_table
);
1704 NtGdiDeleteObjectApp( dc
);
1705 return STATUS_INVALID_PARAMETER
;
1709 /***********************************************************************
1710 * NtGdiDdDDIDestroyDCFromMemory (win32u.@)
1712 NTSTATUS WINAPI
NtGdiDdDDIDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY
*desc
)
1714 if (!desc
) return STATUS_INVALID_PARAMETER
;
1716 TRACE("dc %p, bitmap %p.\n", desc
->hDc
, desc
->hBitmap
);
1718 if (get_gdi_object_type( desc
->hDc
) != NTGDI_OBJ_MEMDC
||
1719 get_gdi_object_type( desc
->hBitmap
) != NTGDI_OBJ_BITMAP
) return STATUS_INVALID_PARAMETER
;
1720 NtGdiDeleteObjectApp( desc
->hBitmap
);
1721 NtGdiDeleteObjectApp( desc
->hDc
);
1723 return STATUS_SUCCESS
;
1727 /***********************************************************************
1730 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1733 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, NTGDI_OBJ_BITMAP
);
1737 if (!buffer
) ret
= sizeof(BITMAP
);
1738 else if (count
>= sizeof(DIBSECTION
))
1740 DIBSECTION
*dib
= buffer
;
1742 dib
->dsBm
.bmWidthBytes
= get_dib_stride( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmBitsPixel
);
1743 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1744 ret
= sizeof(DIBSECTION
);
1746 else if (count
>= sizeof(BITMAP
))
1748 BITMAP
*bitmap
= buffer
;
1749 *bitmap
= bmp
->dib
.dsBm
;
1750 bitmap
->bmWidthBytes
= get_dib_stride( bitmap
->bmWidth
, bitmap
->bmBitsPixel
);
1751 ret
= sizeof(BITMAP
);
1754 GDI_ReleaseObj( handle
);
1759 /***********************************************************************
1762 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1766 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1768 if (bmp
->dib
.dshSection
)
1770 NtUnmapViewOfSection( GetCurrentProcess(), (char *)bmp
->dib
.dsBm
.bmBits
-
1771 (bmp
->dib
.dsOffset
% system_info
.AllocationGranularity
) );
1776 NtFreeVirtualMemory( GetCurrentProcess(), &bmp
->dib
.dsBm
.bmBits
, &size
, MEM_RELEASE
);
1779 free( bmp
->color_table
);