2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize).
34 * The palettes are stored in different formats:
36 - BITMAPCOREINFO: Array of RGBTRIPLE
37 - BITMAPINFO: Array of RGBQUAD
40 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
43 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45 If biCompression is BI_BITFIELDS, the color masks are at the same position
46 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
47 the new headers have structure members for the masks.
50 * You should never access the color table using the bmiColors member,
51 because the passed structure may have one of the extended headers
52 mentioned above. Use this to calculate the location:
55 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 Search for "Bitmap Structures" in MSDN
68 #define WIN32_NO_STATUS
73 #include "ddk/d3dkmthk.h"
75 #include "gdi_private.h"
76 #include "wine/debug.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
81 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
82 static BOOL
DIB_DeleteObject( HGDIOBJ handle
);
84 static const struct gdi_obj_funcs dib_funcs
=
86 DIB_GetObject
, /* pGetObjectA */
87 DIB_GetObject
, /* pGetObjectW */
88 NULL
, /* pUnrealizeObject */
89 DIB_DeleteObject
/* pDeleteObject */
92 /***********************************************************************
95 * Return the size of the bitmap info structure including color table.
97 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
99 unsigned int colors
, size
, masks
= 0;
101 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
103 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
104 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
105 return sizeof(BITMAPCOREHEADER
) + colors
*
106 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
108 else /* assume BITMAPINFOHEADER */
110 if (info
->bmiHeader
.biClrUsed
) colors
= min( info
->bmiHeader
.biClrUsed
, 256 );
111 else colors
= info
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << info
->bmiHeader
.biBitCount
;
112 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
113 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
114 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
118 /*******************************************************************************************
119 * Verify that the DIB parameters are valid.
121 static BOOL
is_valid_dib_format( const BITMAPINFOHEADER
*info
, BOOL allow_compression
)
123 if (info
->biWidth
<= 0) return FALSE
;
124 if (info
->biHeight
== 0) return FALSE
;
126 if (allow_compression
&& (info
->biCompression
== BI_RLE4
|| info
->biCompression
== BI_RLE8
))
128 if (info
->biHeight
< 0) return FALSE
;
129 if (!info
->biSizeImage
) return FALSE
;
130 return info
->biBitCount
== (info
->biCompression
== BI_RLE4
? 4 : 8);
133 if (!info
->biPlanes
) return FALSE
;
135 /* check for size overflow */
136 if (!info
->biBitCount
) return FALSE
;
137 if (UINT_MAX
/ info
->biBitCount
< info
->biWidth
) return FALSE
;
138 if (UINT_MAX
/ get_dib_stride( info
->biWidth
, info
->biBitCount
) < abs( info
->biHeight
)) return FALSE
;
140 switch (info
->biBitCount
)
146 return (info
->biCompression
== BI_RGB
);
149 return (info
->biCompression
== BI_BITFIELDS
|| info
->biCompression
== BI_RGB
);
155 /*******************************************************************************************
156 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
158 static BOOL
bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER
*dst
, const BITMAPINFOHEADER
*info
)
160 if (!info
) return FALSE
;
162 if (info
->biSize
== sizeof(BITMAPCOREHEADER
))
164 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
165 dst
->biWidth
= core
->bcWidth
;
166 dst
->biHeight
= core
->bcHeight
;
167 dst
->biPlanes
= core
->bcPlanes
;
168 dst
->biBitCount
= core
->bcBitCount
;
169 dst
->biCompression
= BI_RGB
;
170 dst
->biXPelsPerMeter
= 0;
171 dst
->biYPelsPerMeter
= 0;
173 dst
->biClrImportant
= 0;
175 else if (info
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
181 WARN( "(%u): unknown/wrong size for header\n", info
->biSize
);
185 dst
->biSize
= sizeof(*dst
);
186 if (dst
->biCompression
== BI_RGB
|| dst
->biCompression
== BI_BITFIELDS
)
187 dst
->biSizeImage
= get_dib_image_size( (BITMAPINFO
*)dst
);
191 /*******************************************************************************************
192 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
194 * The resulting sanitized BITMAPINFO is guaranteed to have:
195 * - biSize set to sizeof(BITMAPINFOHEADER)
196 * - biSizeImage set to the actual image size even for non-compressed DIB
197 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
198 * - color table present only for <= 8 bpp, always starts at info->bmiColors
200 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
,
201 UINT coloruse
, BOOL allow_compression
)
205 if (coloruse
> DIB_PAL_COLORS
+ 1) return FALSE
; /* FIXME: handle DIB_PAL_COLORS+1 format */
206 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
207 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
209 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
211 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
213 /* bitfields are always at bmiColors even in larger structures */
214 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
215 dst
->bmiHeader
.biClrUsed
= 0;
217 else if (dst
->bmiHeader
.biBitCount
<= 8)
219 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
220 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
222 if (!colors
) colors
= max_colors
;
223 else colors
= min( colors
, max_colors
);
225 if (coloruse
== DIB_PAL_COLORS
)
227 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
230 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
232 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
237 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
238 for (i
= 0; i
< colors
; i
++)
240 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
241 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
242 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
243 dst
->bmiColors
[i
].rgbReserved
= 0;
246 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
247 dst
->bmiHeader
.biClrUsed
= max_colors
;
249 else dst
->bmiHeader
.biClrUsed
= 0;
254 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
256 PALETTEENTRY palEntry
[256];
257 HPALETTE palette
= GetCurrentObject( hdc
, OBJ_PAL
);
258 int i
, colors
= 1 << info
->bmiHeader
.biBitCount
;
260 info
->bmiHeader
.biClrUsed
= colors
;
262 if (!palette
) return 0;
264 memset( palEntry
, 0, sizeof(palEntry
) );
265 if (!GetPaletteEntries( palette
, 0, colors
, palEntry
))
268 for (i
= 0; i
< colors
; i
++)
270 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
271 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
272 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
273 info
->bmiColors
[i
].rgbReserved
= 0;
279 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
281 PALETTEENTRY entries
[256];
284 const WORD
*index
= (const WORD
*)info
->bmiColors
;
285 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
287 if (!colors
) return TRUE
;
288 if (!(palette
= GetCurrentObject( hdc
, OBJ_PAL
))) return FALSE
;
289 if (!(count
= GetPaletteEntries( palette
, 0, colors
, entries
))) return FALSE
;
291 for (i
= 0; i
< colors
; i
++, index
++)
293 table
[i
].rgbRed
= entries
[*index
% count
].peRed
;
294 table
[i
].rgbGreen
= entries
[*index
% count
].peGreen
;
295 table
[i
].rgbBlue
= entries
[*index
% count
].peBlue
;
296 table
[i
].rgbReserved
= 0;
298 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
299 memcpy( info
->bmiColors
, table
, colors
* sizeof(RGBQUAD
) );
300 memset( info
->bmiColors
+ colors
, 0, (info
->bmiHeader
.biClrUsed
- colors
) * sizeof(RGBQUAD
) );
304 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
306 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
307 const int bpp
= info
->bmiHeader
.biBitCount
;
310 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
312 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
315 static BOOL
build_rle_bitmap( BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
319 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
321 BYTE skip
, num
, data
;
322 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
324 if (clip
) *clip
= NULL
;
326 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
328 out_bits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, get_dib_image_size( info
) );
329 if (!out_bits
) goto fail
;
333 *clip
= CreateRectRgn( 0, 0, 0, 0 );
334 run
= CreateRectRgn( 0, 0, 0, 0 );
335 if (!*clip
|| !run
) goto fail
;
338 x
= left
= right
= 0;
341 while (i
< info
->bmiHeader
.biSizeImage
- 1)
344 data
= in_bits
[i
+ 1];
349 if (x
+ num
> width
) num
= width
- x
;
352 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
353 if (info
->bmiHeader
.biBitCount
== 8)
354 memset( out_ptr
, s
, num
);
359 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
360 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
365 /* this will write one too many if num is odd, but that doesn't matter */
366 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
376 if(left
!= right
&& clip
)
378 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
379 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
384 left
= right
= x
= 0;
393 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
395 if (x
> width
) x
= width
;
402 else /* data bytes of data */
405 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
406 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
407 skip
= (skip
+ 1) & ~1;
408 if (x
+ num
> width
) num
= width
- x
;
411 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
412 if (info
->bmiHeader
.biBitCount
== 8)
413 memcpy( out_ptr
, in_bits
+ i
, num
);
418 const BYTE
*in_ptr
= in_bits
+ i
;
419 for ( ; num
; num
--, x
++)
423 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
427 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
431 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
442 if (run
) DeleteObject( run
);
443 if (bits
->free
) bits
->free( bits
);
445 bits
->ptr
= out_bits
;
446 bits
->is_copy
= TRUE
;
447 bits
->free
= free_heap_bits
;
448 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
453 if (run
) DeleteObject( run
);
454 if (clip
&& *clip
) DeleteObject( *clip
);
455 HeapFree( GetProcessHeap(), 0, out_bits
);
461 INT CDECL
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
462 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
463 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
465 DC
*dc
= get_nulldrv_dc( dev
);
466 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
467 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
468 struct bitblt_coords src
, dst
;
469 struct gdi_image_bits src_bits
;
473 INT height
= abs( src_info
->bmiHeader
.biHeight
);
474 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
477 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
478 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
480 src_bits
.ptr
= (void*)bits
;
481 src_bits
.is_copy
= FALSE
;
482 src_bits
.free
= NULL
;
484 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
488 rect
.right
= xDst
+ widthDst
;
489 rect
.bottom
= yDst
+ heightDst
;
490 lp_to_dp( dc
, (POINT
*)&rect
, 2 );
493 dst
.width
= rect
.right
- rect
.left
;
494 dst
.height
= rect
.bottom
- rect
.top
;
496 if (dc
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
499 dst
.width
= -dst
.width
;
501 rop
&= ~NOMIRRORBITMAP
;
504 src
.width
= widthSrc
;
506 src
.height
= heightSrc
;
508 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
509 non_stretch_from_origin
= TRUE
;
511 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
513 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
514 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
517 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
519 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
520 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
525 if (dst
.width
< 0 && dst
.width
== src
.width
)
527 /* This is off-by-one, but that's what Windows does */
530 dst
.width
= -dst
.width
;
531 src
.width
= -src
.width
;
533 if (dst
.height
< 0 && dst
.height
== src
.height
)
537 dst
.height
= -dst
.height
;
538 src
.height
= -src
.height
;
542 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
544 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
546 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
547 src
.y
= -src
.height
- 1;
549 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
551 src
.visrect
.left
= 0;
552 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
554 src
.visrect
.bottom
= height
;
555 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
557 if (rop
== SRCCOPY
) ret
= height
;
558 else ret
= src_info
->bmiHeader
.biHeight
;
560 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
562 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
564 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
566 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
568 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
569 copy_bitmapinfo( dst_info
, src_info
);
570 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
571 if (err
== ERROR_BAD_FORMAT
)
573 DWORD dst_colors
= dst_info
->bmiHeader
.biClrUsed
;
575 /* 1-bpp destination without a color table requires a fake 1-entry table
576 * that contains only the background color. There is no source DC to get
577 * it from, so the background is hardcoded to the default color. */
578 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_colors
)
580 static const RGBQUAD default_bg
= { 255, 255, 255 };
581 dst_info
->bmiColors
[0] = default_bg
;
582 dst_info
->bmiHeader
.biClrUsed
= 1;
585 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
)))
587 /* get rid of the fake 1-bpp table */
588 dst_info
->bmiHeader
.biClrUsed
= dst_colors
;
589 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
593 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
595 copy_bitmapinfo( src_info
, dst_info
);
596 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, dc
->stretchBltMode
);
597 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
602 if (src_bits
.free
) src_bits
.free( &src_bits
);
603 if (clip
) DeleteObject( clip
);
607 /***********************************************************************
608 * StretchDIBits (GDI32.@)
610 INT WINAPI DECLSPEC_HOTPATCH
StretchDIBits( HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
611 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
612 const void *bits
, const BITMAPINFO
*bmi
, UINT coloruse
,
615 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
616 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
622 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
624 SetLastError( ERROR_INVALID_PARAMETER
);
628 if ((dc
= get_dc_ptr( hdc
)))
631 physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
632 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
633 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
634 release_dc_ptr( dc
);
640 /******************************************************************************
641 * SetDIBits [GDI32.@]
643 * Sets pixels in a bitmap using colors from DIB.
646 * hdc [I] Handle to device context
647 * hbitmap [I] Handle to bitmap
648 * startscan [I] Starting scan line
649 * lines [I] Number of scan lines
650 * bits [I] Array of bitmap bits
651 * info [I] Address of structure with data
652 * coloruse [I] Type of color indexes to use
655 * Success: Number of scan lines copied
658 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
659 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
663 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
664 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
665 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
666 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
669 struct gdi_image_bits src_bits
;
670 struct bitblt_coords src
, dst
;
671 INT src_to_dst_offset
;
674 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
) || coloruse
> DIB_PAL_COLORS
)
676 SetLastError( ERROR_INVALID_PARAMETER
);
679 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
681 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
682 if (!masks
[0] || !masks
[1] || !masks
[2])
684 SetLastError( ERROR_INVALID_PARAMETER
);
689 src_bits
.ptr
= (void *)bits
;
690 src_bits
.is_copy
= FALSE
;
691 src_bits
.free
= NULL
;
692 src_bits
.param
= NULL
;
694 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
696 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
698 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
700 if (lines
== 0) goto done
;
701 else lines
= src_info
->bmiHeader
.biHeight
;
704 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
707 dst
.visrect
.left
= 0;
709 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
710 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
712 src
.visrect
.left
= 0;
714 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
715 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
717 if (src_info
->bmiHeader
.biHeight
> 0)
719 src_to_dst_offset
= -startscan
;
720 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
721 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
725 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
726 /* Unlike the bottom-up case, Windows doesn't limit lines. */
727 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
732 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
733 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
734 src
.visrect
= dst
.visrect
;
735 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
737 src
.x
= src
.visrect
.left
;
738 src
.y
= src
.visrect
.top
;
739 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
740 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
742 dst
.x
= dst
.visrect
.left
;
743 dst
.y
= dst
.visrect
.top
;
744 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
745 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
747 copy_bitmapinfo( dst_info
, src_info
);
749 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
750 if (err
== ERROR_BAD_FORMAT
)
752 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
753 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
758 if (src_bits
.free
) src_bits
.free( &src_bits
);
759 if (clip
) DeleteObject( clip
);
760 GDI_ReleaseObj( hbitmap
);
765 INT CDECL
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
766 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
767 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
769 DC
*dc
= get_nulldrv_dc( dev
);
770 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
771 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
772 struct bitblt_coords src
, dst
;
773 struct gdi_image_bits src_bits
;
781 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
782 height
= abs( src_info
->bmiHeader
.biHeight
);
784 src_bits
.ptr
= (void *)bits
;
785 src_bits
.is_copy
= FALSE
;
786 src_bits
.free
= NULL
;
788 if (!lines
) return 0;
789 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
791 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
795 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
796 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
797 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
802 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
806 if (startscan
>= height
) return 0;
807 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
809 /* map src to top-down coordinates with startscan as origin */
811 src
.y
= startscan
+ lines
- (y_src
+ cy
);
818 /* get rid of unnecessary lines */
819 if (src
.y
>= lines
) return 0;
823 else if (src
.y
>= lines
) return lines
;
825 src_info
->bmiHeader
.biHeight
= top_down
? -min( lines
, height
) : lines
;
826 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( src_info
);
829 src
.visrect
.left
= src
.x
;
830 src
.visrect
.top
= src
.y
;
831 src
.visrect
.right
= src
.x
+ cx
;
832 src
.visrect
.bottom
= src
.y
+ cy
;
835 rect
.right
= src_info
->bmiHeader
.biWidth
;
836 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
837 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
845 lp_to_dp( dc
, &pt
, 1 );
850 if (dc
->layout
& LAYOUT_RTL
) dst
.x
-= cx
- 1;
854 rect
.right
= dst
.x
+ cx
;
855 rect
.bottom
= dst
.y
+ cy
;
856 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
858 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
859 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
860 src
.visrect
= dst
.visrect
= rect
;
861 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
862 if (is_rect_empty( &dst
.visrect
)) goto done
;
863 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
865 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
866 copy_bitmapinfo( dst_info
, src_info
);
867 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
868 if (err
== ERROR_BAD_FORMAT
)
870 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
871 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
876 if (src_bits
.free
) src_bits
.free( &src_bits
);
877 if (clip
) DeleteObject( clip
);
881 /***********************************************************************
882 * SetDIBitsToDevice (GDI32.@)
884 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
885 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
886 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
889 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
890 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
896 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
898 SetLastError( ERROR_INVALID_PARAMETER
);
902 if ((dc
= get_dc_ptr( hdc
)))
905 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
906 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
907 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
908 release_dc_ptr( dc
);
913 /***********************************************************************
914 * SetDIBColorTable (GDI32.@)
916 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
922 if (!(dc
= get_dc_ptr( hdc
))) return 0;
924 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
926 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
928 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
929 for (i
= 0; i
< result
; i
++)
931 bitmap
->color_table
[startpos
+ i
].rgbBlue
= colors
[i
].rgbBlue
;
932 bitmap
->color_table
[startpos
+ i
].rgbGreen
= colors
[i
].rgbGreen
;
933 bitmap
->color_table
[startpos
+ i
].rgbRed
= colors
[i
].rgbRed
;
934 bitmap
->color_table
[startpos
+ i
].rgbReserved
= 0;
937 GDI_ReleaseObj( dc
->hBitmap
);
939 if (result
) /* update colors of selected objects */
941 SetTextColor( hdc
, dc
->textColor
);
942 SetBkColor( hdc
, dc
->backgroundColor
);
943 NtGdiSelectPen( hdc
, dc
->hPen
);
944 NtGdiSelectBrush( hdc
, dc
->hBrush
);
947 release_dc_ptr( dc
);
952 /***********************************************************************
953 * GetDIBColorTable (GDI32.@)
955 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
961 if (!(dc
= get_dc_ptr( hdc
))) return 0;
963 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, 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
= HeapAlloc( GetProcessHeap(), 0, 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 * GetDIBits [GDI32.@]
1201 * Retrieves bits of bitmap and copies to buffer.
1204 * Success: Number of scan lines copied from bitmap
1207 INT WINAPI DECLSPEC_HOTPATCH
GetDIBits(
1208 HDC hdc
, /* [in] Handle to device context */
1209 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1210 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1211 UINT lines
, /* [in] Number of scan lines to copy */
1212 LPVOID bits
, /* [out] Address of array for bitmap bits */
1213 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1214 UINT coloruse
) /* [in] RGB or palette index */
1218 int i
, dst_to_src_offset
, ret
= 0;
1220 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1221 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1222 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1223 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1224 struct gdi_image_bits src_bits
;
1225 struct bitblt_coords src
, dst
;
1226 BOOL empty_rect
= FALSE
;
1228 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1229 own copy and transfer the colour info back at the end */
1230 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1231 if (coloruse
> DIB_PAL_COLORS
) return 0;
1233 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1235 dst_info
->bmiHeader
.biClrUsed
= 0;
1236 dst_info
->bmiHeader
.biClrImportant
= 0;
1238 if (!(dc
= get_dc_ptr( hdc
)))
1240 SetLastError( ERROR_INVALID_PARAMETER
);
1244 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1246 release_dc_ptr( dc
);
1250 src
.visrect
.left
= 0;
1251 src
.visrect
.top
= 0;
1252 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1253 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1255 dst
.visrect
.left
= 0;
1256 dst
.visrect
.top
= 0;
1257 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1258 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1260 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1263 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1265 ret
= fill_query_info( info
, bmp
);
1269 /* validate parameters */
1271 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1272 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1274 switch (dst_info
->bmiHeader
.biCompression
)
1277 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1278 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1279 if (bits
) goto done
; /* can't retrieve compressed bits */
1282 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1283 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1284 if (bits
) goto done
; /* can't retrieve compressed bits */
1287 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1290 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1291 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1292 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1293 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1294 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1295 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1296 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1304 if (dst_info
->bmiHeader
.biHeight
> 0)
1306 dst_to_src_offset
= -startscan
;
1307 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1308 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1312 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1313 if (dst_to_src_offset
< 0)
1315 dst_to_src_offset
= 0;
1316 lines
= dst
.visrect
.bottom
- startscan
;
1318 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1321 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1322 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1323 dst
.visrect
= src
.visrect
;
1324 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1326 if (dst_info
->bmiHeader
.biHeight
> 0)
1328 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1330 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1331 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1332 memset( bits
, 0, pad_bytes
);
1333 bits
= (char *)bits
+ pad_bytes
;
1338 if (dst
.visrect
.bottom
< lines
)
1340 int pad_lines
= lines
- dst
.visrect
.bottom
;
1341 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1342 int pad_bytes
= pad_lines
* stride
;
1343 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1347 if (empty_rect
) bits
= NULL
;
1349 src
.x
= src
.visrect
.left
;
1350 src
.y
= src
.visrect
.top
;
1351 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1352 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1357 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1361 /* fill out the src colour table, if it needs one */
1362 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1363 fill_default_color_table( src_info
);
1365 /* if the src and dst are the same depth, copy the colour info across */
1366 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1368 switch (src_info
->bmiHeader
.biBitCount
)
1371 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1373 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1374 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1378 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1380 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1381 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1385 copy_color_info( dst_info
, src_info
, coloruse
);
1387 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1389 if( coloruse
== DIB_PAL_COLORS
)
1391 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1395 fill_default_color_table( dst_info
);
1401 if(dst_info
->bmiHeader
.biHeight
> 0)
1402 dst_info
->bmiHeader
.biHeight
= src
.height
;
1404 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1405 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1407 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1408 if (src_bits
.free
) src_bits
.free( &src_bits
);
1414 if (coloruse
== DIB_PAL_COLORS
)
1416 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1417 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1421 copy_color_info( info
, dst_info
, coloruse
);
1422 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
1424 info
->bmiHeader
.biClrUsed
= 0;
1425 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
1429 release_dc_ptr( dc
);
1430 GDI_ReleaseObj( hbitmap
);
1435 /***********************************************************************
1436 * CreateDIBitmap (GDI32.@)
1438 * Creates a DDB (device dependent bitmap) from a DIB.
1439 * The DDB will have the same color depth as the reference DC.
1441 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1442 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1445 BITMAPINFOHEADER info
;
1449 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1450 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1451 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1452 if (info
.biWidth
< 0) return 0;
1454 /* Top-down DIBs have a negative height */
1455 height
= abs( info
.biHeight
);
1457 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1458 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1459 info
.biBitCount
, info
.biCompression
);
1462 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1464 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1468 if (init
& CBM_INIT
)
1470 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1472 DeleteObject( handle
);
1482 /***********************************************************************
1483 * CreateDIBSection (GDI32.@)
1485 HBITMAP WINAPI DECLSPEC_HOTPATCH
CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
1486 void **bits
, HANDLE section
, DWORD offset
)
1488 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1489 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1492 void *mapBits
= NULL
;
1494 if (bits
) *bits
= NULL
;
1495 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1496 if (usage
> DIB_PAL_COLORS
) return 0;
1497 if (info
->bmiHeader
.biPlanes
!= 1)
1499 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1500 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1503 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1505 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1506 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1507 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1508 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1509 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1511 bmp
->dib
.dsBm
.bmType
= 0;
1512 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1513 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1514 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1515 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1516 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1517 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1519 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1521 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1523 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1524 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1525 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1527 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1530 /* set dsBitfields values */
1531 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1533 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1534 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1535 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1536 bmp
->dib
.dsBitfields
[2] = 0x001f;
1538 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1540 if (usage
== DIB_PAL_COLORS
) goto error
;
1541 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1542 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1543 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1544 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1546 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1548 /* get storage location for DIB bits */
1552 SYSTEM_INFO SystemInfo
;
1556 GetSystemInfo( &SystemInfo
);
1557 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1558 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1559 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1560 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1565 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1566 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1568 bmp
->dib
.dshSection
= section
;
1569 bmp
->dib
.dsOffset
= offset
;
1571 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1573 if (!(ret
= alloc_gdi_handle( &bmp
->obj
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1575 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1579 if (section
) UnmapViewOfFile( mapBits
);
1580 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1581 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1582 HeapFree( GetProcessHeap(), 0, bmp
);
1587 /***********************************************************************
1588 * D3DKMTCreateDCFromMemory (GDI32.@)
1590 NTSTATUS WINAPI
D3DKMTCreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY
*desc
)
1592 const struct d3dddi_format_info
1594 D3DDDIFORMAT format
;
1595 unsigned int bit_count
;
1597 unsigned int palette_size
;
1598 DWORD mask_r
, mask_g
, mask_b
;
1600 BITMAPOBJ
*bmp
= NULL
;
1605 static const struct d3dddi_format_info format_info
[] =
1607 { D3DDDIFMT_R8G8B8
, 24, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1608 { D3DDDIFMT_A8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1609 { D3DDDIFMT_X8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1610 { D3DDDIFMT_R5G6B5
, 16, BI_BITFIELDS
, 0, 0x0000f800, 0x000007e0, 0x0000001f },
1611 { D3DDDIFMT_X1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1612 { D3DDDIFMT_A1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1613 { D3DDDIFMT_A4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1614 { D3DDDIFMT_X4R4G4B4
, 16, BI_BITFIELDS
, 0, 0x00000f00, 0x000000f0, 0x0000000f },
1615 { D3DDDIFMT_P8
, 8, BI_RGB
, 256, 0x00000000, 0x00000000, 0x00000000 },
1618 if (!desc
) return STATUS_INVALID_PARAMETER
;
1620 TRACE("memory %p, format %#x, width %u, height %u, pitch %u, device dc %p, color table %p.\n",
1621 desc
->pMemory
, desc
->Format
, desc
->Width
, desc
->Height
,
1622 desc
->Pitch
, desc
->hDeviceDc
, desc
->pColorTable
);
1624 if (!desc
->pMemory
) return STATUS_INVALID_PARAMETER
;
1626 for (i
= 0; i
< ARRAY_SIZE( format_info
); ++i
)
1628 if (format_info
[i
].format
== desc
->Format
)
1630 format
= &format_info
[i
];
1634 if (!format
) return STATUS_INVALID_PARAMETER
;
1636 if (desc
->Width
> (UINT_MAX
& ~3) / (format
->bit_count
/ 8) ||
1637 !desc
->Pitch
|| desc
->Pitch
< get_dib_stride( desc
->Width
, format
->bit_count
) ||
1638 !desc
->Height
|| desc
->Height
> UINT_MAX
/ desc
->Pitch
) return STATUS_INVALID_PARAMETER
;
1640 if (!desc
->hDeviceDc
|| !(dc
= CreateCompatibleDC( desc
->hDeviceDc
))) return STATUS_INVALID_PARAMETER
;
1642 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) goto error
;
1644 bmp
->dib
.dsBm
.bmWidth
= desc
->Width
;
1645 bmp
->dib
.dsBm
.bmHeight
= desc
->Height
;
1646 bmp
->dib
.dsBm
.bmWidthBytes
= desc
->Pitch
;
1647 bmp
->dib
.dsBm
.bmPlanes
= 1;
1648 bmp
->dib
.dsBm
.bmBitsPixel
= format
->bit_count
;
1649 bmp
->dib
.dsBm
.bmBits
= desc
->pMemory
;
1651 bmp
->dib
.dsBmih
.biSize
= sizeof(bmp
->dib
.dsBmih
);
1652 bmp
->dib
.dsBmih
.biWidth
= desc
->Width
;
1653 bmp
->dib
.dsBmih
.biHeight
= -(LONG
)desc
->Height
;
1654 bmp
->dib
.dsBmih
.biPlanes
= 1;
1655 bmp
->dib
.dsBmih
.biBitCount
= format
->bit_count
;
1656 bmp
->dib
.dsBmih
.biCompression
= format
->compression
;
1657 bmp
->dib
.dsBmih
.biClrUsed
= format
->palette_size
;
1658 bmp
->dib
.dsBmih
.biClrImportant
= format
->palette_size
;
1660 bmp
->dib
.dsBitfields
[0] = format
->mask_r
;
1661 bmp
->dib
.dsBitfields
[1] = format
->mask_g
;
1662 bmp
->dib
.dsBitfields
[2] = format
->mask_b
;
1664 if (format
->palette_size
)
1666 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0, format
->palette_size
* sizeof(*bmp
->color_table
) )))
1668 if (desc
->pColorTable
)
1670 for (i
= 0; i
< format
->palette_size
; ++i
)
1672 bmp
->color_table
[i
].rgbRed
= desc
->pColorTable
[i
].peRed
;
1673 bmp
->color_table
[i
].rgbGreen
= desc
->pColorTable
[i
].peGreen
;
1674 bmp
->color_table
[i
].rgbBlue
= desc
->pColorTable
[i
].peBlue
;
1675 bmp
->color_table
[i
].rgbReserved
= 0;
1680 memcpy( bmp
->color_table
, get_default_color_table( format
->bit_count
),
1681 format
->palette_size
* sizeof(*bmp
->color_table
) );
1685 if (!(bitmap
= alloc_gdi_handle( &bmp
->obj
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1688 desc
->hBitmap
= bitmap
;
1689 NtGdiSelectBitmap( dc
, bitmap
);
1690 return STATUS_SUCCESS
;
1693 if (bmp
) HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1694 HeapFree( GetProcessHeap(), 0, bmp
);
1696 return STATUS_INVALID_PARAMETER
;
1700 /***********************************************************************
1701 * D3DKMTDestroyDCFromMemory (GDI32.@)
1703 NTSTATUS WINAPI
D3DKMTDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY
*desc
)
1705 if (!desc
) return STATUS_INVALID_PARAMETER
;
1707 TRACE("dc %p, bitmap %p.\n", desc
->hDc
, desc
->hBitmap
);
1709 if (GetObjectType( desc
->hDc
) != OBJ_MEMDC
||
1710 GetObjectType( desc
->hBitmap
) != OBJ_BITMAP
) return STATUS_INVALID_PARAMETER
;
1711 DeleteObject( desc
->hBitmap
);
1712 DeleteDC( desc
->hDc
);
1714 return STATUS_SUCCESS
;
1718 /***********************************************************************
1721 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1724 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
1728 if (!buffer
) ret
= sizeof(BITMAP
);
1729 else if (count
>= sizeof(DIBSECTION
))
1731 DIBSECTION
*dib
= buffer
;
1733 dib
->dsBm
.bmWidthBytes
= get_dib_stride( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmBitsPixel
);
1734 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1735 ret
= sizeof(DIBSECTION
);
1737 else if (count
>= sizeof(BITMAP
))
1739 BITMAP
*bitmap
= buffer
;
1740 *bitmap
= bmp
->dib
.dsBm
;
1741 bitmap
->bmWidthBytes
= get_dib_stride( bitmap
->bmWidth
, bitmap
->bmBitsPixel
);
1742 ret
= sizeof(BITMAP
);
1745 GDI_ReleaseObj( handle
);
1750 /***********************************************************************
1753 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1757 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1759 if (bmp
->dib
.dshSection
)
1761 SYSTEM_INFO SystemInfo
;
1762 GetSystemInfo( &SystemInfo
);
1763 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1764 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1766 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1768 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1769 HeapFree( GetProcessHeap(), 0, bmp
);