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", (int)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_INDICES
) return FALSE
;
209 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
210 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
211 if (coloruse
== DIB_PAL_INDICES
&& (dst
->bmiHeader
.biBitCount
!= 1 ||
212 dst
->bmiHeader
.biCompression
!= BI_RGB
)) return FALSE
;
214 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
216 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
218 /* bitfields are always at bmiColors even in larger structures */
219 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
220 dst
->bmiHeader
.biClrUsed
= 0;
222 else if (dst
->bmiHeader
.biBitCount
<= 8)
224 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
225 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
227 if (!colors
) colors
= max_colors
;
228 else colors
= min( colors
, max_colors
);
230 if (coloruse
== DIB_PAL_COLORS
)
232 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
235 else if (coloruse
== DIB_PAL_INDICES
)
237 dst
->bmiColors
[0].rgbRed
= 0;
238 dst
->bmiColors
[0].rgbGreen
= 0;
239 dst
->bmiColors
[0].rgbBlue
= 0;
240 dst
->bmiColors
[0].rgbReserved
= 0;
241 dst
->bmiColors
[1].rgbRed
= 0xff;
242 dst
->bmiColors
[1].rgbGreen
= 0xff;
243 dst
->bmiColors
[1].rgbBlue
= 0xff;
244 dst
->bmiColors
[1].rgbReserved
= 0;
247 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
249 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
254 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
255 for (i
= 0; i
< colors
; i
++)
257 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
258 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
259 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
260 dst
->bmiColors
[i
].rgbReserved
= 0;
263 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
264 dst
->bmiHeader
.biClrUsed
= max_colors
;
266 else dst
->bmiHeader
.biClrUsed
= 0;
271 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
273 PALETTEENTRY palEntry
[256];
274 HPALETTE palette
= NtGdiGetDCObject( hdc
, NTGDI_OBJ_PAL
);
275 int i
, colors
= 1 << info
->bmiHeader
.biBitCount
;
277 info
->bmiHeader
.biClrUsed
= colors
;
279 if (!palette
) return 0;
281 memset( palEntry
, 0, sizeof(palEntry
) );
282 if (!get_palette_entries( palette
, 0, colors
, palEntry
))
285 for (i
= 0; i
< colors
; i
++)
287 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
288 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
289 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
290 info
->bmiColors
[i
].rgbReserved
= 0;
296 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
298 PALETTEENTRY entries
[256];
301 const WORD
*index
= (const WORD
*)info
->bmiColors
;
302 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
304 if (!colors
) return TRUE
;
305 if (!(palette
= NtGdiGetDCObject( hdc
, NTGDI_OBJ_PAL
)))
307 if (!(count
= get_palette_entries( palette
, 0, colors
, entries
))) return FALSE
;
309 for (i
= 0; i
< colors
; i
++, index
++)
311 table
[i
].rgbRed
= entries
[*index
% count
].peRed
;
312 table
[i
].rgbGreen
= entries
[*index
% count
].peGreen
;
313 table
[i
].rgbBlue
= entries
[*index
% count
].peBlue
;
314 table
[i
].rgbReserved
= 0;
316 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
317 memcpy( info
->bmiColors
, table
, colors
* sizeof(RGBQUAD
) );
318 memset( info
->bmiColors
+ colors
, 0, (info
->bmiHeader
.biClrUsed
- colors
) * sizeof(RGBQUAD
) );
322 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
324 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
325 const int bpp
= info
->bmiHeader
.biBitCount
;
328 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
330 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
333 static BOOL
build_rle_bitmap( BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
337 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
339 BYTE skip
, num
, data
;
340 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
342 if (clip
) *clip
= NULL
;
344 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
346 out_bits
= calloc( 1, get_dib_image_size( info
) );
347 if (!out_bits
) goto fail
;
351 *clip
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
352 run
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
353 if (!*clip
|| !run
) goto fail
;
356 x
= left
= right
= 0;
359 while (i
< info
->bmiHeader
.biSizeImage
- 1)
362 data
= in_bits
[i
+ 1];
367 if (x
+ num
> width
) num
= width
- x
;
370 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
371 if (info
->bmiHeader
.biBitCount
== 8)
372 memset( out_ptr
, s
, num
);
377 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
378 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
383 /* this will write one too many if num is odd, but that doesn't matter */
384 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
394 if(left
!= right
&& clip
)
396 NtGdiSetRectRgn( run
, left
, y
, right
, y
+ 1 );
397 NtGdiCombineRgn( *clip
, run
, *clip
, RGN_OR
);
402 left
= right
= x
= 0;
411 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
413 if (x
> width
) x
= width
;
420 else /* data bytes of data */
423 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
424 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
425 skip
= (skip
+ 1) & ~1;
426 if (x
+ num
> width
) num
= width
- x
;
429 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
430 if (info
->bmiHeader
.biBitCount
== 8)
431 memcpy( out_ptr
, in_bits
+ i
, num
);
436 const BYTE
*in_ptr
= in_bits
+ i
;
437 for ( ; num
; num
--, x
++)
441 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
445 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
449 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
460 if (run
) NtGdiDeleteObjectApp( run
);
461 if (bits
->free
) bits
->free( bits
);
463 bits
->ptr
= out_bits
;
464 bits
->is_copy
= TRUE
;
465 bits
->free
= free_heap_bits
;
466 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
471 if (run
) NtGdiDeleteObjectApp( run
);
472 if (clip
&& *clip
) NtGdiDeleteObjectApp( *clip
);
479 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
480 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
481 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
483 DC
*dc
= get_nulldrv_dc( dev
);
484 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
485 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
486 struct bitblt_coords src
, dst
;
487 struct gdi_image_bits src_bits
;
491 INT height
= abs( src_info
->bmiHeader
.biHeight
);
492 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
495 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
496 xSrc
, ySrc
, widthSrc
, heightSrc
, (int)rop
);
498 src_bits
.ptr
= (void*)bits
;
499 src_bits
.is_copy
= FALSE
;
500 src_bits
.free
= NULL
;
502 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
506 rect
.right
= xDst
+ widthDst
;
507 rect
.bottom
= yDst
+ heightDst
;
508 lp_to_dp( dc
, (POINT
*)&rect
, 2 );
511 dst
.width
= rect
.right
- rect
.left
;
512 dst
.height
= rect
.bottom
- rect
.top
;
514 if (dc
->attr
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
517 dst
.width
= -dst
.width
;
519 rop
&= ~NOMIRRORBITMAP
;
522 src
.width
= widthSrc
;
524 src
.height
= heightSrc
;
526 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
527 non_stretch_from_origin
= TRUE
;
529 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
531 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
532 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
535 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
537 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
538 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
543 if (dst
.width
< 0 && dst
.width
== src
.width
)
545 /* This is off-by-one, but that's what Windows does */
548 dst
.width
= -dst
.width
;
549 src
.width
= -src
.width
;
551 if (dst
.height
< 0 && dst
.height
== src
.height
)
555 dst
.height
= -dst
.height
;
556 src
.height
= -src
.height
;
560 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
562 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
564 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
565 src
.y
= -src
.height
- 1;
567 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
569 src
.visrect
.left
= 0;
570 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
572 src
.visrect
.bottom
= height
;
573 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
575 if (rop
== SRCCOPY
) ret
= height
;
576 else ret
= src_info
->bmiHeader
.biHeight
;
578 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
580 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
582 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
584 if (clip
) NtGdiOffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
586 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
587 copy_bitmapinfo( dst_info
, src_info
);
588 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
589 if (err
== ERROR_BAD_FORMAT
)
591 DWORD dst_colors
= dst_info
->bmiHeader
.biClrUsed
;
593 /* 1-bpp destination without a color table requires a fake 1-entry table
594 * that contains only the background color. There is no source DC to get
595 * it from, so the background is hardcoded to the default color. */
596 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_colors
)
598 static const RGBQUAD default_bg
= { 255, 255, 255 };
599 dst_info
->bmiColors
[0] = default_bg
;
600 dst_info
->bmiHeader
.biClrUsed
= 1;
603 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
)))
605 /* get rid of the fake 1-bpp table */
606 dst_info
->bmiHeader
.biClrUsed
= dst_colors
;
607 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
611 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
613 copy_bitmapinfo( src_info
, dst_info
);
614 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, dc
->attr
->stretch_blt_mode
);
615 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
620 if (src_bits
.free
) src_bits
.free( &src_bits
);
621 if (clip
) NtGdiDeleteObjectApp( clip
);
625 /***********************************************************************
626 * NtGdiStretchDIBitsInternal (win32u.@)
628 INT WINAPI
NtGdiStretchDIBitsInternal( HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
629 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
630 const void *bits
, const BITMAPINFO
*bmi
, UINT coloruse
,
631 DWORD rop
, UINT max_info
, UINT max_bits
, HANDLE xform
)
633 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
634 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
640 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
642 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER
);
646 if ((dc
= get_dc_ptr( hdc
)))
649 physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
650 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
651 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
652 release_dc_ptr( dc
);
658 /* Sets pixels in a bitmap using colors from DIB, see SetDIBits */
659 static int set_di_bits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
660 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
664 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
665 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
666 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
667 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
670 struct gdi_image_bits src_bits
;
671 struct bitblt_coords src
, dst
;
672 INT src_to_dst_offset
;
675 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
))
677 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER
);
680 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
682 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
683 if (!masks
[0] || !masks
[1] || !masks
[2])
685 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER
);
690 src_bits
.ptr
= (void *)bits
;
691 src_bits
.is_copy
= FALSE
;
692 src_bits
.free
= NULL
;
693 src_bits
.param
= NULL
;
695 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
697 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, NTGDI_OBJ_BITMAP
))) return 0;
699 if (coloruse
== DIB_PAL_INDICES
&& bitmap
->dib
.dsBm
.bmBitsPixel
!= 1) return 0;
701 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
703 if (lines
== 0) goto done
;
704 else lines
= src_info
->bmiHeader
.biHeight
;
707 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
710 dst
.visrect
.left
= 0;
712 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
713 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
715 src
.visrect
.left
= 0;
717 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
718 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
720 if (src_info
->bmiHeader
.biHeight
> 0)
722 src_to_dst_offset
= -startscan
;
723 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
724 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
728 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
729 /* Unlike the bottom-up case, Windows doesn't limit lines. */
730 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
735 OffsetRect( &src
.visrect
, 0, src_to_dst_offset
);
736 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
737 src
.visrect
= dst
.visrect
;
738 OffsetRect( &src
.visrect
, 0, -src_to_dst_offset
);
740 src
.x
= src
.visrect
.left
;
741 src
.y
= src
.visrect
.top
;
742 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
743 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
745 dst
.x
= dst
.visrect
.left
;
746 dst
.y
= dst
.visrect
.top
;
747 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
748 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
750 copy_bitmapinfo( dst_info
, src_info
);
752 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
753 if (err
== ERROR_BAD_FORMAT
)
755 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
756 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
761 if (src_bits
.free
) src_bits
.free( &src_bits
);
762 if (clip
) NtGdiDeleteObjectApp( clip
);
763 GDI_ReleaseObj( hbitmap
);
768 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
769 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
770 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
772 DC
*dc
= get_nulldrv_dc( dev
);
773 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
774 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
775 struct bitblt_coords src
, dst
;
776 struct gdi_image_bits src_bits
;
784 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
785 height
= abs( src_info
->bmiHeader
.biHeight
);
787 src_bits
.ptr
= (void *)bits
;
788 src_bits
.is_copy
= FALSE
;
789 src_bits
.free
= NULL
;
791 if (!lines
) return 0;
792 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
794 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
798 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
799 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
800 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
805 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
809 if (startscan
>= height
) return 0;
810 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
812 /* map src to top-down coordinates with startscan as origin */
814 src
.y
= startscan
+ lines
- (y_src
+ cy
);
821 /* get rid of unnecessary lines */
822 if (src
.y
>= lines
) return 0;
826 else if (src
.y
>= lines
) return lines
;
828 src_info
->bmiHeader
.biHeight
= top_down
? -min( lines
, height
) : lines
;
829 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( src_info
);
832 src
.visrect
.left
= src
.x
;
833 src
.visrect
.top
= src
.y
;
834 src
.visrect
.right
= src
.x
+ cx
;
835 src
.visrect
.bottom
= src
.y
+ cy
;
838 rect
.right
= src_info
->bmiHeader
.biWidth
;
839 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
840 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
848 lp_to_dp( dc
, &pt
, 1 );
853 if (dc
->attr
->layout
& LAYOUT_RTL
) dst
.x
-= cx
- 1;
857 rect
.right
= dst
.x
+ cx
;
858 rect
.bottom
= dst
.y
+ cy
;
859 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
861 OffsetRect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
862 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
863 src
.visrect
= dst
.visrect
= rect
;
864 OffsetRect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
865 if (IsRectEmpty( &dst
.visrect
)) goto done
;
866 if (clip
) NtGdiOffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
868 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
869 copy_bitmapinfo( dst_info
, src_info
);
870 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
871 if (err
== ERROR_BAD_FORMAT
)
873 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
874 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
879 if (src_bits
.free
) src_bits
.free( &src_bits
);
880 if (clip
) NtGdiDeleteObjectApp( clip
);
884 /***********************************************************************
885 * NtGdiSetDIBitsToDeviceInternal (win32u.@)
887 INT WINAPI
NtGdiSetDIBitsToDeviceInternal( HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
888 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
889 UINT lines
, const void *bits
, const BITMAPINFO
*bmi
,
890 UINT coloruse
, UINT max_bits
, UINT max_info
,
891 BOOL xform_coords
, HANDLE xform
)
893 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
894 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
899 if (xform
) return set_di_bits( hdc
, xform
, startscan
, lines
, bits
, bmi
, coloruse
);
902 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
904 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER
);
908 if ((dc
= get_dc_ptr( hdc
)))
911 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
912 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
913 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
914 release_dc_ptr( dc
);
919 UINT
set_dib_dc_color_table( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
925 if (!(dc
= get_dc_ptr( hdc
))) return 0;
927 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, NTGDI_OBJ_BITMAP
)))
929 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
931 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
932 for (i
= 0; i
< result
; i
++)
934 bitmap
->color_table
[startpos
+ i
].rgbBlue
= colors
[i
].rgbBlue
;
935 bitmap
->color_table
[startpos
+ i
].rgbGreen
= colors
[i
].rgbGreen
;
936 bitmap
->color_table
[startpos
+ i
].rgbRed
= colors
[i
].rgbRed
;
937 bitmap
->color_table
[startpos
+ i
].rgbReserved
= 0;
940 GDI_ReleaseObj( dc
->hBitmap
);
942 if (result
) /* update colors of selected objects */
944 NtGdiGetAndSetDCDword( hdc
, NtGdiSetTextColor
, dc
->attr
->text_color
, NULL
);
945 NtGdiGetAndSetDCDword( hdc
, NtGdiSetBkColor
, dc
->attr
->background_color
, NULL
);
946 NtGdiSelectPen( hdc
, dc
->hPen
);
947 NtGdiSelectBrush( hdc
, dc
->hBrush
);
950 release_dc_ptr( dc
);
955 UINT
get_dib_dc_color_table( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
961 if (!(dc
= get_dc_ptr( hdc
))) return 0;
963 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, NTGDI_OBJ_BITMAP
)))
965 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
967 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
968 memcpy(colors
, bitmap
->color_table
+ startpos
, result
* sizeof(RGBQUAD
));
970 GDI_ReleaseObj( dc
->hBitmap
);
972 release_dc_ptr( dc
);
976 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
977 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
979 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
981 BITMAPINFOHEADER header
;
983 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
984 header
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
985 header
.biHeight
= bmp
->dib
.dsBm
.bmHeight
;
987 header
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
989 switch (header
.biBitCount
)
993 header
.biCompression
= BI_BITFIELDS
;
996 header
.biCompression
= BI_RGB
;
1000 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
1001 header
.biXPelsPerMeter
= 0;
1002 header
.biYPelsPerMeter
= 0;
1003 header
.biClrUsed
= 0;
1004 header
.biClrImportant
= 0;
1006 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
1008 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
1010 coreheader
->bcWidth
= header
.biWidth
;
1011 coreheader
->bcHeight
= header
.biHeight
;
1012 coreheader
->bcPlanes
= header
.biPlanes
;
1013 coreheader
->bcBitCount
= header
.biBitCount
;
1016 info
->bmiHeader
= header
;
1018 return bmp
->dib
.dsBm
.bmHeight
;
1021 /************************************************************************
1024 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1026 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1028 assert( src
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
) );
1030 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1032 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1033 if (coloruse
== DIB_PAL_COLORS
)
1034 memcpy( core
->bmciColors
, src
->bmiColors
, src
->bmiHeader
.biClrUsed
* sizeof(WORD
) );
1038 for (i
= 0; i
< src
->bmiHeader
.biClrUsed
; i
++)
1040 core
->bmciColors
[i
].rgbtRed
= src
->bmiColors
[i
].rgbRed
;
1041 core
->bmciColors
[i
].rgbtGreen
= src
->bmiColors
[i
].rgbGreen
;
1042 core
->bmciColors
[i
].rgbtBlue
= src
->bmiColors
[i
].rgbBlue
;
1048 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1050 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1051 /* bitfields are always at bmiColors even in larger structures */
1052 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1053 else if (src
->bmiHeader
.biClrUsed
)
1055 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1058 if (coloruse
== DIB_PAL_COLORS
)
1059 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1061 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1062 memcpy( colorptr
, src
->bmiColors
, size
);
1067 const RGBQUAD
*get_default_color_table( int bpp
)
1069 static const RGBQUAD table_1
[2] =
1071 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1073 static const RGBQUAD table_4
[16] =
1075 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1076 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1077 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1078 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1080 static const RGBQUAD table_8
[256] =
1082 /* first and last 10 entries are the default system palette entries */
1083 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1084 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1085 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1086 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1087 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1088 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1089 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1090 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1091 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1092 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1093 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1094 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1095 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1096 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1097 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1098 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1099 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1100 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1101 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1102 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1103 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1104 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1105 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1106 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1107 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1108 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1109 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1110 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1111 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1112 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1113 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1114 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1115 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1116 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1117 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1118 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1119 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1120 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1121 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1122 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1123 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1124 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1125 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1126 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1127 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1128 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1129 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1130 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1131 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1132 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1133 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1134 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1135 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1136 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1137 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1138 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1139 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1140 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1141 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1142 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1143 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1144 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1145 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1146 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1151 case 1: return table_1
;
1152 case 4: return table_4
;
1153 case 8: return table_8
;
1154 default: return NULL
;
1158 void fill_default_color_table( BITMAPINFO
*info
)
1160 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1161 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1162 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1165 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1167 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1168 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1169 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1170 info
->bmiHeader
.biPlanes
= 1;
1171 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1172 info
->bmiHeader
.biCompression
= BI_RGB
;
1173 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
1174 info
->bmiHeader
.biXPelsPerMeter
= 0;
1175 info
->bmiHeader
.biYPelsPerMeter
= 0;
1176 info
->bmiHeader
.biClrUsed
= 0;
1177 info
->bmiHeader
.biClrImportant
= 0;
1180 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1182 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1183 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1184 unsigned int info_size
;
1186 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1188 info_size
= get_dib_info_size( info
, usage
);
1189 if ((ret
= malloc( info_size
+ info
->bmiHeader
.biSizeImage
)))
1191 memcpy( ret
, info
, info_size
);
1192 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size( src_info
, usage
),
1193 info
->bmiHeader
.biSizeImage
);
1198 /******************************************************************************
1199 * NtGdiGetDIBitsInternal (win32u.@)
1201 * Retrieves bits of bitmap and copies to buffer.
1203 INT WINAPI
NtGdiGetDIBitsInternal( HDC hdc
, HBITMAP hbitmap
, UINT startscan
, UINT lines
,
1204 void *bits
, BITMAPINFO
*info
, UINT coloruse
,
1205 UINT max_bits
, UINT max_info
)
1209 int i
, dst_to_src_offset
, ret
= 0;
1211 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1212 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1213 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1214 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1215 struct gdi_image_bits src_bits
;
1216 struct bitblt_coords src
, dst
;
1217 BOOL empty_rect
= FALSE
;
1219 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1220 own copy and transfer the colour info back at the end */
1221 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1222 if (coloruse
> DIB_PAL_COLORS
) return 0;
1224 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1226 dst_info
->bmiHeader
.biClrUsed
= 0;
1227 dst_info
->bmiHeader
.biClrImportant
= 0;
1229 if (!(dc
= get_dc_ptr( hdc
)))
1231 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER
);
1235 if (!(bmp
= GDI_GetObjPtr( hbitmap
, NTGDI_OBJ_BITMAP
)))
1237 release_dc_ptr( dc
);
1241 src
.visrect
.left
= 0;
1242 src
.visrect
.top
= 0;
1243 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1244 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1246 dst
.visrect
.left
= 0;
1247 dst
.visrect
.top
= 0;
1248 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1249 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1251 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1254 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1256 ret
= fill_query_info( info
, bmp
);
1260 /* validate parameters */
1262 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1263 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1265 switch (dst_info
->bmiHeader
.biCompression
)
1268 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1269 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1270 if (bits
) goto done
; /* can't retrieve compressed bits */
1273 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1274 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1275 if (bits
) goto done
; /* can't retrieve compressed bits */
1278 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1281 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1282 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1283 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1284 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1285 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1286 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1287 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1295 if (dst_info
->bmiHeader
.biHeight
> 0)
1297 dst_to_src_offset
= -startscan
;
1298 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1299 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1303 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1304 if (dst_to_src_offset
< 0)
1306 dst_to_src_offset
= 0;
1307 lines
= dst
.visrect
.bottom
- startscan
;
1309 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1312 OffsetRect( &dst
.visrect
, 0, dst_to_src_offset
);
1313 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1314 dst
.visrect
= src
.visrect
;
1315 OffsetRect( &dst
.visrect
, 0, -dst_to_src_offset
);
1317 if (dst_info
->bmiHeader
.biHeight
> 0)
1319 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1321 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1322 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1323 memset( bits
, 0, pad_bytes
);
1324 bits
= (char *)bits
+ pad_bytes
;
1329 if (dst
.visrect
.bottom
< lines
)
1331 int pad_lines
= lines
- dst
.visrect
.bottom
;
1332 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1333 int pad_bytes
= pad_lines
* stride
;
1334 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1338 if (empty_rect
) bits
= NULL
;
1340 src
.x
= src
.visrect
.left
;
1341 src
.y
= src
.visrect
.top
;
1342 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1343 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1348 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1352 /* fill out the src colour table, if it needs one */
1353 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1354 fill_default_color_table( src_info
);
1356 /* if the src and dst are the same depth, copy the colour info across */
1357 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1359 switch (src_info
->bmiHeader
.biBitCount
)
1362 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1364 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1365 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1369 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1371 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1372 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1376 copy_color_info( dst_info
, src_info
, coloruse
);
1378 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1380 if( coloruse
== DIB_PAL_COLORS
)
1382 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1386 fill_default_color_table( dst_info
);
1392 if(dst_info
->bmiHeader
.biHeight
> 0)
1393 dst_info
->bmiHeader
.biHeight
= src
.height
;
1395 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1396 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1398 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1399 if (src_bits
.free
) src_bits
.free( &src_bits
);
1405 if (coloruse
== DIB_PAL_COLORS
)
1407 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1408 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1412 copy_color_info( info
, dst_info
, coloruse
);
1413 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
1415 info
->bmiHeader
.biClrUsed
= 0;
1416 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
1420 release_dc_ptr( dc
);
1421 GDI_ReleaseObj( hbitmap
);
1426 /***********************************************************************
1427 * NtGdiCreateDIBitmapInternal (win32u.@)
1429 * Creates a DDB (device dependent bitmap) from a DIB.
1430 * The DDB will have the same color depth as the reference DC.
1432 HBITMAP WINAPI
NtGdiCreateDIBitmapInternal( HDC hdc
, INT width
, INT height
, DWORD init
,
1433 const void *bits
, const BITMAPINFO
*data
,
1434 UINT coloruse
, UINT max_info
, UINT max_bits
,
1435 ULONG flags
, HANDLE xform
)
1439 if (coloruse
> DIB_PAL_COLORS
+ 1 || width
< 0) return 0;
1441 /* Top-down DIBs have a negative height */
1442 height
= abs( height
);
1444 TRACE( "hdc=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d)\n",
1445 hdc
, (int)init
, bits
, data
, coloruse
, width
, height
);
1448 handle
= NtGdiCreateBitmap( width
, height
, 1, 1, NULL
);
1450 handle
= NtGdiCreateCompatibleBitmap( hdc
, width
, height
);
1454 if (init
& CBM_INIT
)
1456 if (set_di_bits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1458 NtGdiDeleteObjectApp( handle
);
1468 /***********************************************************************
1469 * NtGdiCreateDIBSection (win32u.@)
1471 HBITMAP WINAPI
NtGdiCreateDIBSection( HDC hdc
, HANDLE section
, DWORD offset
, const BITMAPINFO
*bmi
,
1472 UINT usage
, UINT header_size
, ULONG flags
,
1473 ULONG_PTR color_space
, void **bits
)
1475 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1476 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1479 void *mapBits
= NULL
;
1481 if (bits
) *bits
= NULL
;
1482 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1483 if (usage
> DIB_PAL_COLORS
) return 0;
1484 if (info
->bmiHeader
.biPlanes
!= 1)
1486 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1487 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1490 if (!(bmp
= calloc( 1, sizeof(*bmp
) ))) return 0;
1492 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1493 (int)info
->bmiHeader
.biWidth
, (int)info
->bmiHeader
.biHeight
,
1494 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1495 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1496 (int)info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1498 bmp
->dib
.dsBm
.bmType
= 0;
1499 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1500 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1501 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1502 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1503 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1504 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1506 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1508 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1510 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1511 if (!(bmp
->color_table
= malloc( bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1513 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1516 /* set dsBitfields values */
1517 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1519 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1520 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1521 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1522 bmp
->dib
.dsBitfields
[2] = 0x001f;
1524 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1526 if (usage
== DIB_PAL_COLORS
) goto error
;
1527 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1528 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1529 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1530 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1532 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1534 /* get storage location for DIB bits */
1538 LARGE_INTEGER map_offset
;
1541 map_offset
.QuadPart
= offset
- (offset
% system_info
.AllocationGranularity
);
1542 map_size
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- map_offset
.QuadPart
);
1543 if (NtMapViewOfSection( section
, GetCurrentProcess(), &mapBits
, 0, 0, &map_offset
,
1544 &map_size
, ViewShare
, 0, PAGE_READWRITE
))
1546 bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- map_offset
.QuadPart
);
1550 SIZE_T size
= bmp
->dib
.dsBmih
.biSizeImage
;
1552 if (NtAllocateVirtualMemory( GetCurrentProcess(), &bmp
->dib
.dsBm
.bmBits
, zero_bits
,
1553 &size
, MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
))
1556 bmp
->dib
.dshSection
= section
;
1557 bmp
->dib
.dsOffset
= offset
;
1559 if ((ret
= alloc_gdi_handle( &bmp
->obj
, NTGDI_OBJ_BITMAP
, &dib_funcs
)))
1561 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1565 if (section
) NtUnmapViewOfSection( GetCurrentProcess(), mapBits
);
1569 NtFreeVirtualMemory( GetCurrentProcess(), &bmp
->dib
.dsBm
.bmBits
, &size
, MEM_RELEASE
);
1572 free( bmp
->color_table
);
1578 static BOOL
memory_dib_DeleteObject( HGDIOBJ handle
)
1582 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1584 free( bmp
->color_table
);
1590 static const struct gdi_obj_funcs memory_dib_funcs
=
1592 .pGetObjectW
= DIB_GetObject
,
1593 .pDeleteObject
= memory_dib_DeleteObject
,
1596 /***********************************************************************
1597 * NtGdiDdDDICreateDCFromMemory (win32u.@)
1599 NTSTATUS WINAPI
NtGdiDdDDICreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY
*desc
)
1601 const struct d3dddi_format_info
1603 D3DDDIFORMAT format
;
1604 unsigned int bit_count
;
1606 unsigned int palette_size
;
1607 DWORD mask_r
, mask_g
, mask_b
;
1609 BITMAPOBJ
*bmp
= NULL
;
1614 static const struct d3dddi_format_info format_info
[] =
1616 { D3DDDIFMT_R8G8B8
, 24, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1617 { D3DDDIFMT_A8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1618 { D3DDDIFMT_X8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1619 { D3DDDIFMT_R5G6B5
, 16, BI_BITFIELDS
, 0, 0x0000f800, 0x000007e0, 0x0000001f },
1620 { D3DDDIFMT_X1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1621 { D3DDDIFMT_A1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1622 { D3DDDIFMT_A4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1623 { D3DDDIFMT_X4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1624 { D3DDDIFMT_P8
, 8, BI_RGB
, 256, 0x00000000, 0x00000000, 0x00000000 },
1627 if (!desc
) return STATUS_INVALID_PARAMETER
;
1629 TRACE("memory %p, format %#x, width %u, height %u, pitch %u, device dc %p, color table %p.\n",
1630 desc
->pMemory
, desc
->Format
, desc
->Width
, desc
->Height
,
1631 desc
->Pitch
, desc
->hDeviceDc
, desc
->pColorTable
);
1633 if (!desc
->pMemory
) return STATUS_INVALID_PARAMETER
;
1635 for (i
= 0; i
< ARRAY_SIZE( format_info
); ++i
)
1637 if (format_info
[i
].format
== desc
->Format
)
1639 format
= &format_info
[i
];
1643 if (!format
) return STATUS_INVALID_PARAMETER
;
1645 if (desc
->Width
> (UINT_MAX
& ~3) / (format
->bit_count
/ 8) ||
1646 !desc
->Pitch
|| desc
->Pitch
< get_dib_stride( desc
->Width
, format
->bit_count
) ||
1647 !desc
->Height
|| desc
->Height
> UINT_MAX
/ desc
->Pitch
) return STATUS_INVALID_PARAMETER
;
1649 if (!desc
->hDeviceDc
|| !(dc
= NtGdiCreateCompatibleDC( desc
->hDeviceDc
)))
1650 return STATUS_INVALID_PARAMETER
;
1652 if (!(bmp
= calloc( 1, sizeof(*bmp
) ))) goto error
;
1654 bmp
->dib
.dsBm
.bmWidth
= desc
->Width
;
1655 bmp
->dib
.dsBm
.bmHeight
= desc
->Height
;
1656 bmp
->dib
.dsBm
.bmWidthBytes
= desc
->Pitch
;
1657 bmp
->dib
.dsBm
.bmPlanes
= 1;
1658 bmp
->dib
.dsBm
.bmBitsPixel
= format
->bit_count
;
1659 bmp
->dib
.dsBm
.bmBits
= desc
->pMemory
;
1661 bmp
->dib
.dsBmih
.biSize
= sizeof(bmp
->dib
.dsBmih
);
1662 bmp
->dib
.dsBmih
.biWidth
= desc
->Width
;
1663 bmp
->dib
.dsBmih
.biHeight
= -(LONG
)desc
->Height
;
1664 bmp
->dib
.dsBmih
.biPlanes
= 1;
1665 bmp
->dib
.dsBmih
.biBitCount
= format
->bit_count
;
1666 bmp
->dib
.dsBmih
.biCompression
= format
->compression
;
1667 bmp
->dib
.dsBmih
.biClrUsed
= format
->palette_size
;
1668 bmp
->dib
.dsBmih
.biClrImportant
= format
->palette_size
;
1670 bmp
->dib
.dsBitfields
[0] = format
->mask_r
;
1671 bmp
->dib
.dsBitfields
[1] = format
->mask_g
;
1672 bmp
->dib
.dsBitfields
[2] = format
->mask_b
;
1674 if (format
->palette_size
)
1676 if (!(bmp
->color_table
= malloc( format
->palette_size
* sizeof(*bmp
->color_table
) )))
1678 if (desc
->pColorTable
)
1680 for (i
= 0; i
< format
->palette_size
; ++i
)
1682 bmp
->color_table
[i
].rgbRed
= desc
->pColorTable
[i
].peRed
;
1683 bmp
->color_table
[i
].rgbGreen
= desc
->pColorTable
[i
].peGreen
;
1684 bmp
->color_table
[i
].rgbBlue
= desc
->pColorTable
[i
].peBlue
;
1685 bmp
->color_table
[i
].rgbReserved
= 0;
1690 memcpy( bmp
->color_table
, get_default_color_table( format
->bit_count
),
1691 format
->palette_size
* sizeof(*bmp
->color_table
) );
1695 if (!(bitmap
= alloc_gdi_handle( &bmp
->obj
, NTGDI_OBJ_BITMAP
, &memory_dib_funcs
))) goto error
;
1698 desc
->hBitmap
= bitmap
;
1699 NtGdiSelectBitmap( dc
, bitmap
);
1700 return STATUS_SUCCESS
;
1703 if (bmp
) free( bmp
->color_table
);
1705 NtGdiDeleteObjectApp( dc
);
1706 return STATUS_INVALID_PARAMETER
;
1710 /***********************************************************************
1711 * NtGdiDdDDIDestroyDCFromMemory (win32u.@)
1713 NTSTATUS WINAPI
NtGdiDdDDIDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY
*desc
)
1715 if (!desc
) return STATUS_INVALID_PARAMETER
;
1717 TRACE("dc %p, bitmap %p.\n", desc
->hDc
, desc
->hBitmap
);
1719 if (get_gdi_object_type( desc
->hDc
) != NTGDI_OBJ_MEMDC
||
1720 get_gdi_object_type( desc
->hBitmap
) != NTGDI_OBJ_BITMAP
) return STATUS_INVALID_PARAMETER
;
1721 NtGdiDeleteObjectApp( desc
->hBitmap
);
1722 NtGdiDeleteObjectApp( desc
->hDc
);
1724 return STATUS_SUCCESS
;
1728 /***********************************************************************
1731 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1734 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, NTGDI_OBJ_BITMAP
);
1738 if (!buffer
) ret
= sizeof(BITMAP
);
1739 else if (count
>= sizeof(DIBSECTION
))
1741 DIBSECTION
*dib
= buffer
;
1743 dib
->dsBm
.bmWidthBytes
= get_dib_stride( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmBitsPixel
);
1744 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1745 ret
= sizeof(DIBSECTION
);
1747 else if (count
>= sizeof(BITMAP
))
1749 BITMAP
*bitmap
= buffer
;
1750 *bitmap
= bmp
->dib
.dsBm
;
1751 bitmap
->bmWidthBytes
= get_dib_stride( bitmap
->bmWidth
, bitmap
->bmBitsPixel
);
1752 ret
= sizeof(BITMAP
);
1755 GDI_ReleaseObj( handle
);
1760 /***********************************************************************
1763 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1767 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1769 if (bmp
->dib
.dshSection
)
1771 NtUnmapViewOfSection( GetCurrentProcess(), (char *)bmp
->dib
.dsBm
.bmBits
-
1772 (bmp
->dib
.dsOffset
% system_info
.AllocationGranularity
) );
1777 NtFreeVirtualMemory( GetCurrentProcess(), &bmp
->dib
.dsBm
.bmBits
, &size
, MEM_RELEASE
);
1780 free( bmp
->color_table
);