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 lp_to_dp( dc
, (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)
584 get_mono_dc_colors( dc
, dst_info
, 1 );
587 memcpy( dst_info
->bmiColors
, src_info
->bmiColors
, 2 * sizeof(dst_info
->bmiColors
[0]) );
588 dst_info
->bmiHeader
.biClrUsed
= 2;
592 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
)))
594 /* get rid of the fake 1-bpp table */
595 dst_info
->bmiHeader
.biClrUsed
= dst_colors
;
596 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
600 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
602 copy_bitmapinfo( src_info
, dst_info
);
603 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, dc
->stretchBltMode
);
604 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
609 if (src_bits
.free
) src_bits
.free( &src_bits
);
610 if (clip
) DeleteObject( clip
);
614 /***********************************************************************
615 * StretchDIBits (GDI32.@)
617 INT WINAPI DECLSPEC_HOTPATCH
StretchDIBits( HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
618 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
619 const void *bits
, const BITMAPINFO
*bmi
, UINT coloruse
,
622 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
623 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
629 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
631 SetLastError( ERROR_INVALID_PARAMETER
);
635 if ((dc
= get_dc_ptr( hdc
)))
638 physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
639 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
640 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
641 release_dc_ptr( dc
);
647 /******************************************************************************
648 * SetDIBits [GDI32.@]
650 * Sets pixels in a bitmap using colors from DIB.
653 * hdc [I] Handle to device context
654 * hbitmap [I] Handle to bitmap
655 * startscan [I] Starting scan line
656 * lines [I] Number of scan lines
657 * bits [I] Array of bitmap bits
658 * info [I] Address of structure with data
659 * coloruse [I] Type of color indexes to use
662 * Success: Number of scan lines copied
665 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
666 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
670 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
671 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
672 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
673 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
676 struct gdi_image_bits src_bits
;
677 struct bitblt_coords src
, dst
;
678 INT src_to_dst_offset
;
681 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
) || coloruse
> DIB_PAL_COLORS
)
683 SetLastError( ERROR_INVALID_PARAMETER
);
686 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
688 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
689 if (!masks
[0] || !masks
[1] || !masks
[2])
691 SetLastError( ERROR_INVALID_PARAMETER
);
696 src_bits
.ptr
= (void *)bits
;
697 src_bits
.is_copy
= FALSE
;
698 src_bits
.free
= NULL
;
699 src_bits
.param
= NULL
;
701 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
703 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
705 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
707 if (lines
== 0) goto done
;
708 else lines
= src_info
->bmiHeader
.biHeight
;
711 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
714 dst
.visrect
.left
= 0;
716 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
717 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
719 src
.visrect
.left
= 0;
721 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
722 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
724 if (src_info
->bmiHeader
.biHeight
> 0)
726 src_to_dst_offset
= -startscan
;
727 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
728 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
732 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
733 /* Unlike the bottom-up case, Windows doesn't limit lines. */
734 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
739 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
740 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
741 src
.visrect
= dst
.visrect
;
742 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
744 src
.x
= src
.visrect
.left
;
745 src
.y
= src
.visrect
.top
;
746 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
747 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
749 dst
.x
= dst
.visrect
.left
;
750 dst
.y
= dst
.visrect
.top
;
751 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
752 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
754 copy_bitmapinfo( dst_info
, src_info
);
756 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
757 if (err
== ERROR_BAD_FORMAT
)
759 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
760 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
765 if (src_bits
.free
) src_bits
.free( &src_bits
);
766 if (clip
) DeleteObject( clip
);
767 GDI_ReleaseObj( hbitmap
);
772 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
773 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
774 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
776 DC
*dc
= get_nulldrv_dc( dev
);
777 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
778 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
779 struct bitblt_coords src
, dst
;
780 struct gdi_image_bits src_bits
;
788 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
789 height
= abs( src_info
->bmiHeader
.biHeight
);
791 src_bits
.ptr
= (void *)bits
;
792 src_bits
.is_copy
= FALSE
;
793 src_bits
.free
= NULL
;
795 if (!lines
) return 0;
796 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
798 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
802 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
803 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
804 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
809 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
813 if (startscan
>= height
) return 0;
814 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
816 /* map src to top-down coordinates with startscan as origin */
818 src
.y
= startscan
+ lines
- (y_src
+ cy
);
825 /* get rid of unnecessary lines */
826 if (src
.y
>= lines
) return 0;
830 else if (src
.y
>= lines
) return lines
;
832 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
835 src
.visrect
.left
= src
.x
;
836 src
.visrect
.top
= src
.y
;
837 src
.visrect
.right
= src
.x
+ cx
;
838 src
.visrect
.bottom
= src
.y
+ cy
;
841 rect
.right
= src_info
->bmiHeader
.biWidth
;
842 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
843 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
851 lp_to_dp( dc
, &pt
, 1 );
856 if (dc
->layout
& LAYOUT_RTL
) dst
.x
-= cx
- 1;
860 rect
.right
= dst
.x
+ cx
;
861 rect
.bottom
= dst
.y
+ cy
;
862 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
864 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
865 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
866 src
.visrect
= dst
.visrect
= rect
;
867 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
868 if (is_rect_empty( &dst
.visrect
)) goto done
;
869 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
871 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
872 copy_bitmapinfo( dst_info
, src_info
);
873 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
874 if (err
== ERROR_BAD_FORMAT
)
876 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
877 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
882 if (src_bits
.free
) src_bits
.free( &src_bits
);
883 if (clip
) DeleteObject( clip
);
887 /***********************************************************************
888 * SetDIBitsToDevice (GDI32.@)
890 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
891 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
892 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
895 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
896 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
902 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
904 SetLastError( ERROR_INVALID_PARAMETER
);
908 if ((dc
= get_dc_ptr( hdc
)))
911 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
912 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
913 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
914 release_dc_ptr( dc
);
919 /***********************************************************************
920 * SetDIBColorTable (GDI32.@)
922 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
928 if (!(dc
= get_dc_ptr( hdc
))) return 0;
930 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
932 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
934 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
935 memcpy(bitmap
->color_table
+ startpos
, colors
, result
* sizeof(RGBQUAD
));
937 GDI_ReleaseObj( dc
->hBitmap
);
939 if (result
) /* update colors of selected objects */
941 SetTextColor( hdc
, dc
->textColor
);
942 SetBkColor( hdc
, dc
->backgroundColor
);
943 SelectObject( hdc
, dc
->hPen
);
944 SelectObject( 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
;
1049 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
1051 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1052 /* bitfields are always at bmiColors even in larger structures */
1053 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1054 else if (src
->bmiHeader
.biClrUsed
)
1056 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1059 if (coloruse
== DIB_PAL_COLORS
)
1060 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1062 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1063 memcpy( colorptr
, src
->bmiColors
, size
);
1068 const RGBQUAD
*get_default_color_table( int bpp
)
1070 static const RGBQUAD table_1
[2] =
1072 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1074 static const RGBQUAD table_4
[16] =
1076 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1077 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1078 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1079 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1081 static const RGBQUAD table_8
[256] =
1083 /* first and last 10 entries are the default system palette entries */
1084 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1085 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1086 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1087 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1088 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1089 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1090 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1091 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1092 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1093 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1094 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1095 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1096 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1097 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1098 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1099 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1100 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1101 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1102 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1103 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1104 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1105 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1106 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1107 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1108 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1109 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1110 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1111 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1112 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1113 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1114 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1115 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1116 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1117 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1118 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1119 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1120 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1121 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1122 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1123 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1124 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1125 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1126 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1127 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1128 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1129 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1130 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1131 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1132 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1133 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1134 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1135 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1136 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1137 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1138 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1139 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1140 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1141 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1142 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1143 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1144 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1145 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1146 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1147 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1152 case 1: return table_1
;
1153 case 4: return table_4
;
1154 case 8: return table_8
;
1155 default: return NULL
;
1159 void fill_default_color_table( BITMAPINFO
*info
)
1161 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1162 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1163 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1166 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1168 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1169 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1170 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1171 info
->bmiHeader
.biPlanes
= 1;
1172 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1173 info
->bmiHeader
.biCompression
= BI_RGB
;
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
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 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1386 copy_color_info( dst_info
, src_info
, coloruse
);
1388 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1390 if( coloruse
== DIB_PAL_COLORS
)
1392 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1396 fill_default_color_table( dst_info
);
1402 if(dst_info
->bmiHeader
.biHeight
> 0)
1403 dst_info
->bmiHeader
.biHeight
= src
.height
;
1405 dst_info
->bmiHeader
.biHeight
= -src
.height
;
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
)) info
->bmiHeader
.biClrUsed
= 0;
1425 release_dc_ptr( dc
);
1426 GDI_ReleaseObj( hbitmap
);
1431 /***********************************************************************
1432 * CreateDIBitmap (GDI32.@)
1434 * Creates a DDB (device dependent bitmap) from a DIB.
1435 * The DDB will have the same color depth as the reference DC.
1437 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1438 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1441 BITMAPINFOHEADER info
;
1445 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1446 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1447 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1448 if (info
.biWidth
< 0) return 0;
1450 /* Top-down DIBs have a negative height */
1451 height
= abs( info
.biHeight
);
1453 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1454 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1455 info
.biBitCount
, info
.biCompression
);
1458 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1460 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1464 if (init
& CBM_INIT
)
1466 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1468 DeleteObject( handle
);
1478 /***********************************************************************
1479 * CreateDIBSection (GDI32.@)
1481 HBITMAP WINAPI DECLSPEC_HOTPATCH
CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
1482 void **bits
, HANDLE section
, DWORD offset
)
1484 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1485 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1488 void *mapBits
= NULL
;
1490 if (bits
) *bits
= NULL
;
1491 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1492 if (usage
> DIB_PAL_COLORS
) return 0;
1493 if (info
->bmiHeader
.biPlanes
!= 1)
1495 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1496 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1499 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1501 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1502 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1503 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1504 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1505 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1507 bmp
->dib
.dsBm
.bmType
= 0;
1508 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1509 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1510 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1511 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1512 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1513 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1515 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1517 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1519 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1520 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1521 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1523 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1526 /* set dsBitfields values */
1527 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1529 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1530 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1531 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1532 bmp
->dib
.dsBitfields
[2] = 0x001f;
1534 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1536 if (usage
== DIB_PAL_COLORS
) goto error
;
1537 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1538 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1539 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1540 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1542 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1544 /* get storage location for DIB bits */
1548 SYSTEM_INFO SystemInfo
;
1552 GetSystemInfo( &SystemInfo
);
1553 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1554 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1555 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1556 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1561 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1562 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1564 bmp
->dib
.dshSection
= section
;
1565 bmp
->dib
.dsOffset
= offset
;
1567 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1569 if (!(ret
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1571 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1575 if (section
) UnmapViewOfFile( mapBits
);
1576 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1577 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1578 HeapFree( GetProcessHeap(), 0, bmp
);
1583 /***********************************************************************
1584 * D3DKMTCreateDCFromMemory (GDI32.@)
1586 NTSTATUS WINAPI
D3DKMTCreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY
*desc
)
1588 const struct d3dddi_format_info
1590 D3DDDIFORMAT format
;
1591 unsigned int bit_count
;
1593 unsigned int palette_size
;
1594 DWORD mask_r
, mask_g
, mask_b
;
1596 BITMAPOBJ
*bmp
= NULL
;
1601 static const struct d3dddi_format_info format_info
[] =
1603 { D3DDDIFMT_R8G8B8
, 24, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1604 { D3DDDIFMT_A8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1605 { D3DDDIFMT_X8R8G8B8
, 32, BI_RGB
, 0, 0x00000000, 0x00000000, 0x00000000 },
1606 { D3DDDIFMT_R5G6B5
, 16, BI_BITFIELDS
, 0, 0x0000f800, 0x000007e0, 0x0000001f },
1607 { D3DDDIFMT_X1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1608 { D3DDDIFMT_A1R5G5B5
, 16, BI_BITFIELDS
, 0, 0x00007c00, 0x000003e0, 0x0000001f },
1609 { D3DDDIFMT_P8
, 8, BI_RGB
, 256, 0x00000000, 0x00000000, 0x00000000 },
1612 if (!desc
) return STATUS_INVALID_PARAMETER
;
1614 TRACE("memory %p, format %#x, width %u, height %u, pitch %u, device dc %p, color table %p.\n",
1615 desc
->pMemory
, desc
->Format
, desc
->Width
, desc
->Height
,
1616 desc
->Pitch
, desc
->hDeviceDc
, desc
->pColorTable
);
1618 if (!desc
->pMemory
) return STATUS_INVALID_PARAMETER
;
1620 for (i
= 0; i
< sizeof(format_info
) / sizeof(*format_info
); ++i
)
1622 if (format_info
[i
].format
== desc
->Format
)
1624 format
= &format_info
[i
];
1628 if (!format
) return STATUS_INVALID_PARAMETER
;
1630 if (desc
->Width
> (UINT_MAX
& ~3) / (format
->bit_count
/ 8) ||
1631 !desc
->Pitch
|| desc
->Pitch
< get_dib_stride( desc
->Width
, format
->bit_count
) ||
1632 !desc
->Height
|| desc
->Height
> UINT_MAX
/ desc
->Pitch
) return STATUS_INVALID_PARAMETER
;
1634 if (!desc
->hDeviceDc
|| !(dc
= CreateCompatibleDC( desc
->hDeviceDc
))) return STATUS_INVALID_PARAMETER
;
1636 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) goto error
;
1638 bmp
->dib
.dsBm
.bmWidth
= desc
->Width
;
1639 bmp
->dib
.dsBm
.bmHeight
= desc
->Height
;
1640 bmp
->dib
.dsBm
.bmWidthBytes
= desc
->Pitch
;
1641 bmp
->dib
.dsBm
.bmPlanes
= 1;
1642 bmp
->dib
.dsBm
.bmBitsPixel
= format
->bit_count
;
1643 bmp
->dib
.dsBm
.bmBits
= desc
->pMemory
;
1645 bmp
->dib
.dsBmih
.biSize
= sizeof(bmp
->dib
.dsBmih
);
1646 bmp
->dib
.dsBmih
.biWidth
= desc
->Width
;
1647 bmp
->dib
.dsBmih
.biHeight
= -(LONG
)desc
->Height
;
1648 bmp
->dib
.dsBmih
.biPlanes
= 1;
1649 bmp
->dib
.dsBmih
.biBitCount
= format
->bit_count
;
1650 bmp
->dib
.dsBmih
.biCompression
= format
->compression
;
1651 bmp
->dib
.dsBmih
.biClrUsed
= format
->palette_size
;
1652 bmp
->dib
.dsBmih
.biClrImportant
= format
->palette_size
;
1654 bmp
->dib
.dsBitfields
[0] = format
->mask_r
;
1655 bmp
->dib
.dsBitfields
[1] = format
->mask_g
;
1656 bmp
->dib
.dsBitfields
[2] = format
->mask_b
;
1658 if (format
->palette_size
)
1660 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0, format
->palette_size
* sizeof(*bmp
->color_table
) )))
1662 if (desc
->pColorTable
)
1664 for (i
= 0; i
< format
->palette_size
; ++i
)
1666 bmp
->color_table
[i
].rgbRed
= desc
->pColorTable
[i
].peRed
;
1667 bmp
->color_table
[i
].rgbGreen
= desc
->pColorTable
[i
].peGreen
;
1668 bmp
->color_table
[i
].rgbBlue
= desc
->pColorTable
[i
].peBlue
;
1669 bmp
->color_table
[i
].rgbReserved
= 0;
1674 memcpy( bmp
->color_table
, get_default_color_table( format
->bit_count
),
1675 format
->palette_size
* sizeof(*bmp
->color_table
) );
1679 if (!(bitmap
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1682 desc
->hBitmap
= bitmap
;
1683 SelectObject( dc
, bitmap
);
1684 return STATUS_SUCCESS
;
1687 if (bmp
) HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1688 HeapFree( GetProcessHeap(), 0, bmp
);
1690 return STATUS_INVALID_PARAMETER
;
1694 /***********************************************************************
1695 * D3DKMTDestroyDCFromMemory (GDI32.@)
1697 NTSTATUS WINAPI
D3DKMTDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY
*desc
)
1699 if (!desc
) return STATUS_INVALID_PARAMETER
;
1701 TRACE("dc %p, bitmap %p.\n", desc
->hDc
, desc
->hBitmap
);
1703 if (GetObjectType( desc
->hDc
) != OBJ_MEMDC
||
1704 GetObjectType( desc
->hBitmap
) != OBJ_BITMAP
) return STATUS_INVALID_PARAMETER
;
1705 DeleteObject( desc
->hBitmap
);
1706 DeleteDC( desc
->hDc
);
1708 return STATUS_SUCCESS
;
1712 /***********************************************************************
1715 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
)
1722 if (!(dc
= get_dc_ptr( hdc
))) return 0;
1724 if (GetObjectType( hdc
) != OBJ_MEMDC
)
1730 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
1732 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
1738 if (GDI_get_ref_count( handle
))
1740 WARN( "Bitmap already selected in another DC\n" );
1741 GDI_ReleaseObj( handle
);
1746 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
1747 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
1749 GDI_ReleaseObj( handle
);
1754 dc
->hBitmap
= handle
;
1755 GDI_inc_ref_count( handle
);
1757 dc
->vis_rect
.left
= 0;
1758 dc
->vis_rect
.top
= 0;
1759 dc
->vis_rect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
1760 dc
->vis_rect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
1761 dc
->device_rect
= dc
->vis_rect
;
1762 GDI_ReleaseObj( handle
);
1764 GDI_dec_ref_count( ret
);
1768 release_dc_ptr( dc
);
1773 /***********************************************************************
1776 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1779 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
1783 if (!buffer
) ret
= sizeof(BITMAP
);
1784 else if (count
>= sizeof(DIBSECTION
))
1786 DIBSECTION
*dib
= buffer
;
1788 dib
->dsBm
.bmWidthBytes
= get_dib_stride( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmBitsPixel
);
1789 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1790 ret
= sizeof(DIBSECTION
);
1792 else if (count
>= sizeof(BITMAP
))
1794 BITMAP
*bitmap
= buffer
;
1795 *bitmap
= bmp
->dib
.dsBm
;
1796 bitmap
->bmWidthBytes
= get_dib_stride( bitmap
->bmWidth
, bitmap
->bmBitsPixel
);
1797 ret
= sizeof(BITMAP
);
1800 GDI_ReleaseObj( handle
);
1805 /***********************************************************************
1808 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1812 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1814 if (bmp
->dib
.dshSection
)
1816 SYSTEM_INFO SystemInfo
;
1817 GetSystemInfo( &SystemInfo
);
1818 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1819 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1821 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1823 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1824 return HeapFree( GetProcessHeap(), 0, bmp
);