2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize).
34 * The palettes are stored in different formats:
36 - BITMAPCOREINFO: Array of RGBTRIPLE
37 - BITMAPINFO: Array of RGBQUAD
40 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
43 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45 If biCompression is BI_BITFIELDS, the color masks are at the same position
46 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
47 the new headers have structure members for the masks.
50 * You should never access the color table using the bmiColors member,
51 because the passed structure may have one of the extended headers
52 mentioned above. Use this to calculate the location:
55 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 Search for "Bitmap Structures" in MSDN
70 #define WIN32_NO_STATUS
75 #include "ddk/d3dkmthk.h"
77 #include "gdi_private.h"
78 #include "wine/debug.h"
80 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
83 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
);
84 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
85 static BOOL
DIB_DeleteObject( HGDIOBJ handle
);
87 static const struct gdi_obj_funcs dib_funcs
=
89 DIB_SelectObject
, /* pSelectObject */
90 DIB_GetObject
, /* pGetObjectA */
91 DIB_GetObject
, /* pGetObjectW */
92 NULL
, /* pUnrealizeObject */
93 DIB_DeleteObject
/* pDeleteObject */
96 /***********************************************************************
99 * Return the size of the bitmap info structure including color table.
101 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
103 unsigned int colors
, size
, masks
= 0;
105 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
107 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
108 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
109 return sizeof(BITMAPCOREHEADER
) + colors
*
110 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
112 else /* assume BITMAPINFOHEADER */
114 if (info
->bmiHeader
.biClrUsed
) colors
= min( info
->bmiHeader
.biClrUsed
, 256 );
115 else colors
= info
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << info
->bmiHeader
.biBitCount
;
116 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
117 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
118 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
122 /*******************************************************************************************
123 * Verify that the DIB parameters are valid.
125 static BOOL
is_valid_dib_format( const BITMAPINFOHEADER
*info
, BOOL allow_compression
)
127 if (info
->biWidth
<= 0) return FALSE
;
128 if (info
->biHeight
== 0) return FALSE
;
130 if (allow_compression
&& (info
->biCompression
== BI_RLE4
|| info
->biCompression
== BI_RLE8
))
132 if (info
->biHeight
< 0) return FALSE
;
133 if (!info
->biSizeImage
) return FALSE
;
134 return info
->biBitCount
== (info
->biCompression
== BI_RLE4
? 4 : 8);
137 if (!info
->biPlanes
) return FALSE
;
139 /* check for size overflow */
140 if (!info
->biBitCount
) return FALSE
;
141 if (UINT_MAX
/ info
->biBitCount
< info
->biWidth
) return FALSE
;
142 if (UINT_MAX
/ get_dib_stride( info
->biWidth
, info
->biBitCount
) < abs( info
->biHeight
)) return FALSE
;
144 switch (info
->biBitCount
)
150 return (info
->biCompression
== BI_RGB
);
153 return (info
->biCompression
== BI_BITFIELDS
|| info
->biCompression
== BI_RGB
);
159 /*******************************************************************************************
160 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
162 static BOOL
bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER
*dst
, const BITMAPINFOHEADER
*info
)
164 if (!info
) return FALSE
;
166 if (info
->biSize
== sizeof(BITMAPCOREHEADER
))
168 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
169 dst
->biWidth
= core
->bcWidth
;
170 dst
->biHeight
= core
->bcHeight
;
171 dst
->biPlanes
= core
->bcPlanes
;
172 dst
->biBitCount
= core
->bcBitCount
;
173 dst
->biCompression
= BI_RGB
;
174 dst
->biXPelsPerMeter
= 0;
175 dst
->biYPelsPerMeter
= 0;
177 dst
->biClrImportant
= 0;
179 else if (info
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
185 WARN( "(%u): unknown/wrong size for header\n", info
->biSize
);
189 dst
->biSize
= sizeof(*dst
);
190 if (dst
->biCompression
== BI_RGB
|| dst
->biCompression
== BI_BITFIELDS
)
191 dst
->biSizeImage
= get_dib_image_size( (BITMAPINFO
*)dst
);
195 /*******************************************************************************************
196 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
198 * The resulting sanitized BITMAPINFO is guaranteed to have:
199 * - biSize set to sizeof(BITMAPINFOHEADER)
200 * - biSizeImage set to the actual image size even for non-compressed DIB
201 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
202 * - color table present only for <= 8 bpp, always starts at info->bmiColors
204 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
,
205 UINT coloruse
, BOOL allow_compression
)
209 if (coloruse
> DIB_PAL_COLORS
+ 1) return FALSE
; /* FIXME: handle DIB_PAL_COLORS+1 format */
210 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
211 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
213 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
215 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
217 /* bitfields are always at bmiColors even in larger structures */
218 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
219 dst
->bmiHeader
.biClrUsed
= 0;
221 else if (dst
->bmiHeader
.biBitCount
<= 8)
223 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
224 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
226 if (!colors
) colors
= max_colors
;
227 else colors
= min( colors
, max_colors
);
229 if (coloruse
== DIB_PAL_COLORS
)
231 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
234 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
236 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
241 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
242 for (i
= 0; i
< colors
; i
++)
244 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
245 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
246 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
247 dst
->bmiColors
[i
].rgbReserved
= 0;
250 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
251 dst
->bmiHeader
.biClrUsed
= max_colors
;
253 else dst
->bmiHeader
.biClrUsed
= 0;
258 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
260 PALETTEENTRY palEntry
[256];
261 HPALETTE palette
= GetCurrentObject( hdc
, OBJ_PAL
);
262 int i
, colors
= 1 << info
->bmiHeader
.biBitCount
;
264 info
->bmiHeader
.biClrUsed
= colors
;
266 if (!palette
) return 0;
268 memset( palEntry
, 0, sizeof(palEntry
) );
269 if (!GetPaletteEntries( palette
, 0, colors
, palEntry
))
272 for (i
= 0; i
< colors
; i
++)
274 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
275 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
276 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
277 info
->bmiColors
[i
].rgbReserved
= 0;
283 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
285 PALETTEENTRY entries
[256];
288 const WORD
*index
= (const WORD
*)info
->bmiColors
;
289 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
291 if (!colors
) return TRUE
;
292 if (!(palette
= GetCurrentObject( hdc
, OBJ_PAL
))) return FALSE
;
293 if (!(count
= GetPaletteEntries( palette
, 0, colors
, entries
))) return FALSE
;
295 for (i
= 0; i
< colors
; i
++, index
++)
297 table
[i
].rgbRed
= entries
[*index
% count
].peRed
;
298 table
[i
].rgbGreen
= entries
[*index
% count
].peGreen
;
299 table
[i
].rgbBlue
= entries
[*index
% count
].peBlue
;
300 table
[i
].rgbReserved
= 0;
302 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
303 memcpy( info
->bmiColors
, table
, colors
* sizeof(RGBQUAD
) );
304 memset( info
->bmiColors
+ colors
, 0, (info
->bmiHeader
.biClrUsed
- colors
) * sizeof(RGBQUAD
) );
308 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
310 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
311 const int bpp
= info
->bmiHeader
.biBitCount
;
314 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
316 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
319 static BOOL
build_rle_bitmap( const BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
323 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
325 BYTE skip
, num
, data
;
326 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
328 if (clip
) *clip
= NULL
;
330 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
332 out_bits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, get_dib_image_size( info
) );
333 if (!out_bits
) goto fail
;
337 *clip
= CreateRectRgn( 0, 0, 0, 0 );
338 run
= CreateRectRgn( 0, 0, 0, 0 );
339 if (!*clip
|| !run
) goto fail
;
342 x
= left
= right
= 0;
345 while (i
< info
->bmiHeader
.biSizeImage
- 1)
348 data
= in_bits
[i
+ 1];
353 if (x
+ num
> width
) num
= width
- x
;
356 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
357 if (info
->bmiHeader
.biBitCount
== 8)
358 memset( out_ptr
, s
, num
);
363 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
364 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
369 /* this will write one too many if num is odd, but that doesn't matter */
370 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
380 if(left
!= right
&& clip
)
382 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
383 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
388 left
= right
= x
= 0;
397 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
399 if (x
> width
) x
= width
;
406 else /* data bytes of data */
409 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
410 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
411 skip
= (skip
+ 1) & ~1;
412 if (x
+ num
> width
) num
= width
- x
;
415 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
416 if (info
->bmiHeader
.biBitCount
== 8)
417 memcpy( out_ptr
, in_bits
+ i
, num
);
422 const BYTE
*in_ptr
= in_bits
+ i
;
423 for ( ; num
; num
--, x
++)
427 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
431 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
435 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
446 if (run
) DeleteObject( run
);
447 if (bits
->free
) bits
->free( bits
);
449 bits
->ptr
= out_bits
;
450 bits
->is_copy
= TRUE
;
451 bits
->free
= free_heap_bits
;
456 if (run
) DeleteObject( run
);
457 if (clip
&& *clip
) DeleteObject( *clip
);
458 HeapFree( GetProcessHeap(), 0, out_bits
);
464 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
465 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
466 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
468 DC
*dc
= get_nulldrv_dc( dev
);
469 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
470 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
471 struct bitblt_coords src
, dst
;
472 struct gdi_image_bits src_bits
;
476 INT height
= abs( src_info
->bmiHeader
.biHeight
);
477 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
480 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
481 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
483 src_bits
.ptr
= (void*)bits
;
484 src_bits
.is_copy
= FALSE
;
485 src_bits
.free
= NULL
;
487 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
491 rect
.right
= xDst
+ widthDst
;
492 rect
.bottom
= yDst
+ heightDst
;
493 LPtoDP( dc
->hSelf
, (POINT
*)&rect
, 2 );
496 dst
.width
= rect
.right
- rect
.left
;
497 dst
.height
= rect
.bottom
- rect
.top
;
499 if (dc
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
502 dst
.width
= -dst
.width
;
504 rop
&= ~NOMIRRORBITMAP
;
507 src
.width
= widthSrc
;
509 src
.height
= heightSrc
;
511 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
512 non_stretch_from_origin
= TRUE
;
514 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
516 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
517 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
520 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
522 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
523 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
528 if (dst
.width
< 0 && dst
.width
== src
.width
)
530 /* This is off-by-one, but that's what Windows does */
533 dst
.width
= -dst
.width
;
534 src
.width
= -src
.width
;
536 if (dst
.height
< 0 && dst
.height
== src
.height
)
540 dst
.height
= -dst
.height
;
541 src
.height
= -src
.height
;
545 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
547 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
549 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
550 src
.y
= -src
.height
- 1;
552 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
554 src
.visrect
.left
= 0;
555 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
557 src
.visrect
.bottom
= height
;
558 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
560 if (rop
== SRCCOPY
) ret
= height
;
561 else ret
= src_info
->bmiHeader
.biHeight
;
563 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
565 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
567 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
569 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
571 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
572 copy_bitmapinfo( dst_info
, src_info
);
573 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
574 if (err
== ERROR_BAD_FORMAT
)
576 DWORD dst_colors
= dst_info
->bmiHeader
.biClrUsed
;
578 /* 1-bpp destination without a color table requires a fake 1-entry table
579 * that contains only the background color; except with a 1-bpp source,
580 * in which case it uses the source colors */
581 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_colors
)
583 if (src_info
->bmiHeader
.biBitCount
> 1)
585 COLORREF color
= GetBkColor( dev
->hdc
);
586 dst_info
->bmiColors
[0].rgbRed
= GetRValue( color
);
587 dst_info
->bmiColors
[0].rgbGreen
= GetGValue( color
);
588 dst_info
->bmiColors
[0].rgbBlue
= GetBValue( color
);
589 dst_info
->bmiColors
[0].rgbReserved
= 0;
590 dst_info
->bmiHeader
.biClrUsed
= 1;
594 memcpy( dst_info
->bmiColors
, src_info
->bmiColors
, 2 * sizeof(dst_info
->bmiColors
[0]) );
595 dst_info
->bmiHeader
.biClrUsed
= 2;
599 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
)))
601 /* get rid of the fake 1-bpp table */
602 dst_info
->bmiHeader
.biClrUsed
= dst_colors
;
603 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
607 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
609 copy_bitmapinfo( src_info
, dst_info
);
610 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, GetStretchBltMode( dev
->hdc
) );
611 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
616 if (src_bits
.free
) src_bits
.free( &src_bits
);
617 if (clip
) DeleteObject( clip
);
621 /***********************************************************************
622 * StretchDIBits (GDI32.@)
624 INT WINAPI DECLSPEC_HOTPATCH
StretchDIBits( HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
625 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
626 const void *bits
, const BITMAPINFO
*bmi
, UINT coloruse
,
629 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
630 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
636 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
638 SetLastError( ERROR_INVALID_PARAMETER
);
642 if ((dc
= get_dc_ptr( hdc
)))
645 physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
646 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
647 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
648 release_dc_ptr( dc
);
654 /******************************************************************************
655 * SetDIBits [GDI32.@]
657 * Sets pixels in a bitmap using colors from DIB.
660 * hdc [I] Handle to device context
661 * hbitmap [I] Handle to bitmap
662 * startscan [I] Starting scan line
663 * lines [I] Number of scan lines
664 * bits [I] Array of bitmap bits
665 * info [I] Address of structure with data
666 * coloruse [I] Type of color indexes to use
669 * Success: Number of scan lines copied
672 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
673 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
677 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
678 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
679 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
680 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
683 struct gdi_image_bits src_bits
;
684 struct bitblt_coords src
, dst
;
685 INT src_to_dst_offset
;
688 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
) || coloruse
> DIB_PAL_COLORS
)
690 SetLastError( ERROR_INVALID_PARAMETER
);
693 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
695 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
696 if (!masks
[0] || !masks
[1] || !masks
[2])
698 SetLastError( ERROR_INVALID_PARAMETER
);
703 src_bits
.ptr
= (void *)bits
;
704 src_bits
.is_copy
= FALSE
;
705 src_bits
.free
= NULL
;
706 src_bits
.param
= NULL
;
708 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
710 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
712 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
714 if (lines
== 0) goto done
;
715 else lines
= src_info
->bmiHeader
.biHeight
;
718 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
721 dst
.visrect
.left
= 0;
723 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
724 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
726 src
.visrect
.left
= 0;
728 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
729 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
731 if (src_info
->bmiHeader
.biHeight
> 0)
733 src_to_dst_offset
= -startscan
;
734 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
735 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
739 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
740 /* Unlike the bottom-up case, Windows doesn't limit lines. */
741 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
746 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
747 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
748 src
.visrect
= dst
.visrect
;
749 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
751 src
.x
= src
.visrect
.left
;
752 src
.y
= src
.visrect
.top
;
753 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
754 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
756 dst
.x
= dst
.visrect
.left
;
757 dst
.y
= dst
.visrect
.top
;
758 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
759 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
761 copy_bitmapinfo( dst_info
, src_info
);
763 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
764 if (err
== ERROR_BAD_FORMAT
)
766 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
767 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
772 if (src_bits
.free
) src_bits
.free( &src_bits
);
773 if (clip
) DeleteObject( clip
);
774 GDI_ReleaseObj( hbitmap
);
779 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
780 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
781 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
783 DC
*dc
= get_nulldrv_dc( dev
);
784 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
785 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
786 struct bitblt_coords src
, dst
;
787 struct gdi_image_bits src_bits
;
795 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
796 height
= abs( src_info
->bmiHeader
.biHeight
);
798 src_bits
.ptr
= (void *)bits
;
799 src_bits
.is_copy
= FALSE
;
800 src_bits
.free
= NULL
;
802 if (!lines
) return 0;
803 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
805 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
809 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
810 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
811 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
816 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
820 if (startscan
>= height
) return 0;
821 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
823 /* map src to top-down coordinates with startscan as origin */
825 src
.y
= startscan
+ lines
- (y_src
+ cy
);
832 /* get rid of unnecessary lines */
833 if (src
.y
>= lines
) return 0;
837 else if (src
.y
>= lines
) return lines
;
839 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
842 src
.visrect
.left
= src
.x
;
843 src
.visrect
.top
= src
.y
;
844 src
.visrect
.right
= src
.x
+ cx
;
845 src
.visrect
.bottom
= src
.y
+ cy
;
848 rect
.right
= src_info
->bmiHeader
.biWidth
;
849 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
850 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
858 LPtoDP( dev
->hdc
, &pt
, 1 );
863 if (GetLayout( dev
->hdc
) & LAYOUT_RTL
) dst
.x
-= cx
- 1;
867 rect
.right
= dst
.x
+ cx
;
868 rect
.bottom
= dst
.y
+ cy
;
869 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
871 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
872 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
873 src
.visrect
= dst
.visrect
= rect
;
874 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
875 if (is_rect_empty( &dst
.visrect
)) goto done
;
876 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
878 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
879 copy_bitmapinfo( dst_info
, src_info
);
880 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
881 if (err
== ERROR_BAD_FORMAT
)
883 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
884 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
889 if (src_bits
.free
) src_bits
.free( &src_bits
);
890 if (clip
) DeleteObject( clip
);
894 /***********************************************************************
895 * SetDIBitsToDevice (GDI32.@)
897 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
898 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
899 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
902 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
903 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
909 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
911 SetLastError( ERROR_INVALID_PARAMETER
);
915 if ((dc
= get_dc_ptr( hdc
)))
918 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
919 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
920 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
921 release_dc_ptr( dc
);
926 /***********************************************************************
927 * SetDIBColorTable (GDI32.@)
929 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
935 if (!(dc
= get_dc_ptr( hdc
))) return 0;
937 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
939 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
941 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
942 memcpy(bitmap
->color_table
+ startpos
, colors
, result
* sizeof(RGBQUAD
));
944 GDI_ReleaseObj( dc
->hBitmap
);
946 if (result
) /* update colors of selected objects */
948 SetTextColor( hdc
, dc
->textColor
);
949 SetBkColor( hdc
, dc
->backgroundColor
);
950 SelectObject( hdc
, dc
->hPen
);
951 SelectObject( hdc
, dc
->hBrush
);
954 release_dc_ptr( dc
);
959 /***********************************************************************
960 * GetDIBColorTable (GDI32.@)
962 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
968 if (!(dc
= get_dc_ptr( hdc
))) return 0;
970 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
972 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
974 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
975 memcpy(colors
, bitmap
->color_table
+ startpos
, result
* sizeof(RGBQUAD
));
977 GDI_ReleaseObj( dc
->hBitmap
);
979 release_dc_ptr( dc
);
983 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
984 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
986 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
988 BITMAPINFOHEADER header
;
990 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
991 header
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
992 header
.biHeight
= bmp
->dib
.dsBm
.bmHeight
;
994 header
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
996 switch (header
.biBitCount
)
1000 header
.biCompression
= BI_BITFIELDS
;
1003 header
.biCompression
= BI_RGB
;
1007 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
1008 header
.biXPelsPerMeter
= 0;
1009 header
.biYPelsPerMeter
= 0;
1010 header
.biClrUsed
= 0;
1011 header
.biClrImportant
= 0;
1013 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
1015 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
1017 coreheader
->bcWidth
= header
.biWidth
;
1018 coreheader
->bcHeight
= header
.biHeight
;
1019 coreheader
->bcPlanes
= header
.biPlanes
;
1020 coreheader
->bcBitCount
= header
.biBitCount
;
1023 info
->bmiHeader
= header
;
1025 return bmp
->dib
.dsBm
.bmHeight
;
1028 /************************************************************************
1031 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1033 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1035 assert( src
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
) );
1037 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1039 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1040 if (coloruse
== DIB_PAL_COLORS
)
1041 memcpy( core
->bmciColors
, src
->bmiColors
, src
->bmiHeader
.biClrUsed
* sizeof(WORD
) );
1045 for (i
= 0; i
< src
->bmiHeader
.biClrUsed
; i
++)
1047 core
->bmciColors
[i
].rgbtRed
= src
->bmiColors
[i
].rgbRed
;
1048 core
->bmciColors
[i
].rgbtGreen
= src
->bmiColors
[i
].rgbGreen
;
1049 core
->bmciColors
[i
].rgbtBlue
= src
->bmiColors
[i
].rgbBlue
;
1055 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1056 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
1058 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1059 /* bitfields are always at bmiColors even in larger structures */
1060 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1061 else if (src
->bmiHeader
.biClrUsed
)
1063 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1066 if (coloruse
== DIB_PAL_COLORS
)
1067 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1069 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1070 memcpy( colorptr
, src
->bmiColors
, size
);
1075 const RGBQUAD
*get_default_color_table( int bpp
)
1077 static const RGBQUAD table_1
[2] =
1079 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1081 static const RGBQUAD table_4
[16] =
1083 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1084 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1085 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1086 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1088 static const RGBQUAD table_8
[256] =
1090 /* first and last 10 entries are the default system palette entries */
1091 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1092 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1093 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1094 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1095 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1096 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1097 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1098 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1099 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1100 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1101 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1102 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1103 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1104 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1105 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1106 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1107 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1108 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1109 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1110 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1111 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1112 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1113 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1114 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1115 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1116 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1117 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1118 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1119 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1120 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1121 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1122 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1123 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1124 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1125 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1126 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1127 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1128 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1129 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1130 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1131 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1132 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1133 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1134 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1135 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1136 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1137 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1138 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1139 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1140 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1141 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1142 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1143 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1144 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1145 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1146 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1147 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1148 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1149 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1150 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1151 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1152 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1153 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1154 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1159 case 1: return table_1
;
1160 case 4: return table_4
;
1161 case 8: return table_8
;
1162 default: return NULL
;
1166 void fill_default_color_table( BITMAPINFO
*info
)
1168 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1169 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1170 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1173 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1175 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1176 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1177 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1178 info
->bmiHeader
.biPlanes
= 1;
1179 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1180 info
->bmiHeader
.biCompression
= BI_RGB
;
1181 info
->bmiHeader
.biXPelsPerMeter
= 0;
1182 info
->bmiHeader
.biYPelsPerMeter
= 0;
1183 info
->bmiHeader
.biClrUsed
= 0;
1184 info
->bmiHeader
.biClrImportant
= 0;
1187 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1189 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1190 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1191 unsigned int info_size
;
1193 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1195 info_size
= get_dib_info_size( info
, usage
);
1196 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ info
->bmiHeader
.biSizeImage
)))
1198 memcpy( ret
, info
, info_size
);
1199 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size( src_info
, usage
),
1200 info
->bmiHeader
.biSizeImage
);
1205 /******************************************************************************
1206 * GetDIBits [GDI32.@]
1208 * Retrieves bits of bitmap and copies to buffer.
1211 * Success: Number of scan lines copied from bitmap
1214 INT WINAPI
GetDIBits(
1215 HDC hdc
, /* [in] Handle to device context */
1216 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1217 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1218 UINT lines
, /* [in] Number of scan lines to copy */
1219 LPVOID bits
, /* [out] Address of array for bitmap bits */
1220 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1221 UINT coloruse
) /* [in] RGB or palette index */
1225 int i
, dst_to_src_offset
, ret
= 0;
1227 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1228 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1229 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1230 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1231 struct gdi_image_bits src_bits
;
1232 struct bitblt_coords src
, dst
;
1233 BOOL empty_rect
= FALSE
;
1235 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1236 own copy and transfer the colour info back at the end */
1237 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1238 if (coloruse
> DIB_PAL_COLORS
) return 0;
1240 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1242 dst_info
->bmiHeader
.biClrUsed
= 0;
1243 dst_info
->bmiHeader
.biClrImportant
= 0;
1245 if (!(dc
= get_dc_ptr( hdc
)))
1247 SetLastError( ERROR_INVALID_PARAMETER
);
1251 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1253 release_dc_ptr( dc
);
1257 src
.visrect
.left
= 0;
1258 src
.visrect
.top
= 0;
1259 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1260 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1262 dst
.visrect
.left
= 0;
1263 dst
.visrect
.top
= 0;
1264 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1265 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1267 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1270 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1272 ret
= fill_query_info( info
, bmp
);
1276 /* validate parameters */
1278 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1279 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1281 switch (dst_info
->bmiHeader
.biCompression
)
1284 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1285 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1286 if (bits
) goto done
; /* can't retrieve compressed bits */
1289 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1290 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1291 if (bits
) goto done
; /* can't retrieve compressed bits */
1294 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1297 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1298 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1299 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1300 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1301 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1302 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1303 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1311 if (dst_info
->bmiHeader
.biHeight
> 0)
1313 dst_to_src_offset
= -startscan
;
1314 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1315 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1319 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1320 if (dst_to_src_offset
< 0)
1322 dst_to_src_offset
= 0;
1323 lines
= dst
.visrect
.bottom
- startscan
;
1325 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1328 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1329 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1330 dst
.visrect
= src
.visrect
;
1331 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1333 if (dst_info
->bmiHeader
.biHeight
> 0)
1335 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1337 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1338 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1339 memset( bits
, 0, pad_bytes
);
1340 bits
= (char *)bits
+ pad_bytes
;
1345 if (dst
.visrect
.bottom
< lines
)
1347 int pad_lines
= lines
- dst
.visrect
.bottom
;
1348 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1349 int pad_bytes
= pad_lines
* stride
;
1350 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1354 if (empty_rect
) bits
= NULL
;
1356 src
.x
= src
.visrect
.left
;
1357 src
.y
= src
.visrect
.top
;
1358 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1359 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1364 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1368 /* fill out the src colour table, if it needs one */
1369 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1370 fill_default_color_table( src_info
);
1372 /* if the src and dst are the same depth, copy the colour info across */
1373 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1375 switch (src_info
->bmiHeader
.biBitCount
)
1378 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1380 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1381 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1385 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1387 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1388 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1392 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1393 copy_color_info( dst_info
, src_info
, coloruse
);
1395 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1397 if( coloruse
== DIB_PAL_COLORS
)
1399 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1403 fill_default_color_table( dst_info
);
1409 if(dst_info
->bmiHeader
.biHeight
> 0)
1410 dst_info
->bmiHeader
.biHeight
= src
.height
;
1412 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1414 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1415 if (src_bits
.free
) src_bits
.free( &src_bits
);
1421 if (coloruse
== DIB_PAL_COLORS
)
1423 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1424 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1428 copy_color_info( info
, dst_info
, coloruse
);
1429 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
)) info
->bmiHeader
.biClrUsed
= 0;
1432 release_dc_ptr( dc
);
1433 GDI_ReleaseObj( hbitmap
);
1438 /***********************************************************************
1439 * CreateDIBitmap (GDI32.@)
1441 * Creates a DDB (device dependent bitmap) from a DIB.
1442 * The DDB will have the same color depth as the reference DC.
1444 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1445 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1448 BITMAPINFOHEADER info
;
1452 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1453 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1454 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1455 if (info
.biWidth
< 0) return 0;
1457 /* Top-down DIBs have a negative height */
1458 height
= abs( info
.biHeight
);
1460 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1461 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1462 info
.biBitCount
, info
.biCompression
);
1465 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1467 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1471 if (init
& CBM_INIT
)
1473 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1475 DeleteObject( handle
);
1485 /***********************************************************************
1486 * CreateDIBSection (GDI32.@)
1488 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
1489 VOID
**bits
, HANDLE section
, DWORD offset
)
1491 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1492 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1495 void *mapBits
= NULL
;
1497 if (bits
) *bits
= NULL
;
1498 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1499 if (usage
> DIB_PAL_COLORS
) return 0;
1500 if (info
->bmiHeader
.biPlanes
!= 1)
1502 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1503 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1506 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1508 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1509 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1510 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1511 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1512 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1514 bmp
->dib
.dsBm
.bmType
= 0;
1515 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1516 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1517 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1518 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1519 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1520 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1522 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1524 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1526 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1527 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1528 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1530 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1533 /* set dsBitfields values */
1534 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1536 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1537 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1538 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1539 bmp
->dib
.dsBitfields
[2] = 0x001f;
1541 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1543 if (usage
== DIB_PAL_COLORS
) goto error
;
1544 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1545 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1546 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1547 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1549 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1551 /* get storage location for DIB bits */
1555 SYSTEM_INFO SystemInfo
;
1559 GetSystemInfo( &SystemInfo
);
1560 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1561 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1562 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1563 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1568 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1569 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1571 bmp
->dib
.dshSection
= section
;
1572 bmp
->dib
.dsOffset
= offset
;
1574 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1576 if (!(ret
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1578 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1582 if (section
) UnmapViewOfFile( mapBits
);
1583 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1584 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1585 HeapFree( GetProcessHeap(), 0, bmp
);
1590 /***********************************************************************
1591 * D3DKMTCreateDCFromMemory (GDI32.@)
1593 NTSTATUS WINAPI
D3DKMTCreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY
*desc
)
1595 const struct d3dddi_format_info
1597 D3DDDIFORMAT format
;
1598 unsigned int bit_count
;
1600 unsigned int palette_size
;
1601 DWORD mask_r
, mask_g
, mask_b
;
1603 BITMAPOBJ
*bmp
= NULL
;
1608 static const struct d3dddi_format_info format_info
[] =
1610 { D3DDDIFMT_R8G8B8
, 24, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1611 { D3DDDIFMT_A8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1612 { D3DDDIFMT_X8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1613 { D3DDDIFMT_R5G6B5
, 16, BI_BITFIELDS
, 0, 0x0000f800, 0x000007e0, 0x0000001f },
1614 { D3DDDIFMT_X1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1615 { D3DDDIFMT_A1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1616 { D3DDDIFMT_P8
, 8, BI_RGB
, 256, 0x00000000, 0x00000000, 0x00000000 },
1619 if (!desc
) return STATUS_INVALID_PARAMETER
;
1621 TRACE("memory %p, format %#x, width %u, height %u, pitch %u, device dc %p, color table %p.\n",
1622 desc
->pMemory
, desc
->Format
, desc
->Width
, desc
->Height
,
1623 desc
->Pitch
, desc
->hDeviceDc
, desc
->pColorTable
);
1625 if (!desc
->pMemory
) return STATUS_INVALID_PARAMETER
;
1627 for (i
= 0; i
< sizeof(format_info
) / sizeof(*format_info
); ++i
)
1629 if (format_info
[i
].format
== desc
->Format
)
1631 format
= &format_info
[i
];
1635 if (!format
) return STATUS_INVALID_PARAMETER
;
1637 if (desc
->Width
> (UINT_MAX
& ~3) / (format
->bit_count
/ 8) ||
1638 !desc
->Pitch
|| desc
->Pitch
< get_dib_stride( desc
->Width
, format
->bit_count
) ||
1639 !desc
->Height
|| desc
->Height
> UINT_MAX
/ desc
->Pitch
) return STATUS_INVALID_PARAMETER
;
1641 if (!desc
->hDeviceDc
|| !(dc
= CreateCompatibleDC( desc
->hDeviceDc
))) return STATUS_INVALID_PARAMETER
;
1643 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) goto error
;
1645 bmp
->dib
.dsBm
.bmWidth
= desc
->Width
;
1646 bmp
->dib
.dsBm
.bmHeight
= desc
->Height
;
1647 bmp
->dib
.dsBm
.bmWidthBytes
= desc
->Pitch
;
1648 bmp
->dib
.dsBm
.bmPlanes
= 1;
1649 bmp
->dib
.dsBm
.bmBitsPixel
= format
->bit_count
;
1650 bmp
->dib
.dsBm
.bmBits
= desc
->pMemory
;
1652 bmp
->dib
.dsBmih
.biSize
= sizeof(bmp
->dib
.dsBmih
);
1653 bmp
->dib
.dsBmih
.biWidth
= desc
->Width
;
1654 bmp
->dib
.dsBmih
.biHeight
= -(LONG
)desc
->Height
;
1655 bmp
->dib
.dsBmih
.biPlanes
= 1;
1656 bmp
->dib
.dsBmih
.biBitCount
= format
->bit_count
;
1657 bmp
->dib
.dsBmih
.biCompression
= format
->compression
;
1658 bmp
->dib
.dsBmih
.biClrUsed
= format
->palette_size
;
1659 bmp
->dib
.dsBmih
.biClrImportant
= format
->palette_size
;
1661 bmp
->dib
.dsBitfields
[0] = format
->mask_r
;
1662 bmp
->dib
.dsBitfields
[1] = format
->mask_g
;
1663 bmp
->dib
.dsBitfields
[2] = format
->mask_b
;
1665 if (format
->palette_size
)
1667 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0, format
->palette_size
* sizeof(*bmp
->color_table
) )))
1669 if (desc
->pColorTable
)
1671 for (i
= 0; i
< format
->palette_size
; ++i
)
1673 bmp
->color_table
[i
].rgbRed
= desc
->pColorTable
[i
].peRed
;
1674 bmp
->color_table
[i
].rgbGreen
= desc
->pColorTable
[i
].peGreen
;
1675 bmp
->color_table
[i
].rgbBlue
= desc
->pColorTable
[i
].peBlue
;
1676 bmp
->color_table
[i
].rgbReserved
= 0;
1681 memcpy( bmp
->color_table
, get_default_color_table( format
->bit_count
),
1682 format
->palette_size
* sizeof(*bmp
->color_table
) );
1686 if (!(bitmap
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1689 desc
->hBitmap
= bitmap
;
1690 SelectObject( dc
, bitmap
);
1691 return STATUS_SUCCESS
;
1694 if (bmp
) HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1695 HeapFree( GetProcessHeap(), 0, bmp
);
1697 return STATUS_INVALID_PARAMETER
;
1701 /***********************************************************************
1702 * D3DKMTDestroyDCFromMemory (GDI32.@)
1704 NTSTATUS WINAPI
D3DKMTDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY
*desc
)
1706 if (!desc
) return STATUS_INVALID_PARAMETER
;
1708 TRACE("dc %p, bitmap %p.\n", desc
->hDc
, desc
->hBitmap
);
1710 if (GetObjectType( desc
->hDc
) != OBJ_MEMDC
||
1711 GetObjectType( desc
->hBitmap
) != OBJ_BITMAP
) return STATUS_INVALID_PARAMETER
;
1712 DeleteObject( desc
->hBitmap
);
1713 DeleteDC( desc
->hDc
);
1715 return STATUS_SUCCESS
;
1719 /***********************************************************************
1722 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
)
1729 if (!(dc
= get_dc_ptr( hdc
))) return 0;
1731 if (GetObjectType( hdc
) != OBJ_MEMDC
)
1737 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
1739 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
1745 if (GDI_get_ref_count( handle
))
1747 WARN( "Bitmap already selected in another DC\n" );
1748 GDI_ReleaseObj( handle
);
1753 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
1754 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
1756 GDI_ReleaseObj( handle
);
1761 dc
->hBitmap
= handle
;
1762 GDI_inc_ref_count( handle
);
1764 dc
->vis_rect
.left
= 0;
1765 dc
->vis_rect
.top
= 0;
1766 dc
->vis_rect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
1767 dc
->vis_rect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
1768 dc
->device_rect
= dc
->vis_rect
;
1769 GDI_ReleaseObj( handle
);
1771 GDI_dec_ref_count( ret
);
1775 release_dc_ptr( dc
);
1780 /***********************************************************************
1783 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1786 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
1790 if (!buffer
) ret
= sizeof(BITMAP
);
1791 else if (count
>= sizeof(DIBSECTION
))
1793 DIBSECTION
*dib
= buffer
;
1795 dib
->dsBm
.bmWidthBytes
= get_dib_stride( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmBitsPixel
);
1796 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1797 ret
= sizeof(DIBSECTION
);
1799 else if (count
>= sizeof(BITMAP
))
1801 BITMAP
*bitmap
= buffer
;
1802 *bitmap
= bmp
->dib
.dsBm
;
1803 bitmap
->bmWidthBytes
= get_dib_stride( bitmap
->bmWidth
, bitmap
->bmBitsPixel
);
1804 ret
= sizeof(BITMAP
);
1807 GDI_ReleaseObj( handle
);
1812 /***********************************************************************
1815 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1819 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1821 if (bmp
->dib
.dshSection
)
1823 SYSTEM_INFO SystemInfo
;
1824 GetSystemInfo( &SystemInfo
);
1825 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1826 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1828 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1830 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1831 return HeapFree( GetProcessHeap(), 0, bmp
);