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
69 #include "gdi_private.h"
70 #include "wine/debug.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
75 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
);
76 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
77 static BOOL
DIB_DeleteObject( HGDIOBJ handle
);
79 static const struct gdi_obj_funcs dib_funcs
=
81 DIB_SelectObject
, /* pSelectObject */
82 DIB_GetObject
, /* pGetObjectA */
83 DIB_GetObject
, /* pGetObjectW */
84 NULL
, /* pUnrealizeObject */
85 DIB_DeleteObject
/* pDeleteObject */
88 /***********************************************************************
91 * Return the size of the bitmap info structure including color table.
93 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
95 unsigned int colors
, size
, masks
= 0;
97 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
99 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
100 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
101 return sizeof(BITMAPCOREHEADER
) + colors
*
102 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
104 else /* assume BITMAPINFOHEADER */
106 if (info
->bmiHeader
.biClrUsed
) colors
= min( info
->bmiHeader
.biClrUsed
, 256 );
107 else colors
= info
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << info
->bmiHeader
.biBitCount
;
108 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
109 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
110 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
114 /*******************************************************************************************
115 * Verify that the DIB parameters are valid.
117 static BOOL
is_valid_dib_format( const BITMAPINFOHEADER
*info
, BOOL allow_compression
)
119 if (info
->biWidth
<= 0) return FALSE
;
120 if (info
->biHeight
== 0) return FALSE
;
122 if (allow_compression
&& (info
->biCompression
== BI_RLE4
|| info
->biCompression
== BI_RLE8
))
124 if (info
->biHeight
< 0) return FALSE
;
125 if (!info
->biSizeImage
) return FALSE
;
126 return info
->biBitCount
== (info
->biCompression
== BI_RLE4
? 4 : 8);
129 if (!info
->biPlanes
) return FALSE
;
131 /* check for size overflow */
132 if (!info
->biBitCount
) return FALSE
;
133 if (UINT_MAX
/ info
->biBitCount
< info
->biWidth
) return FALSE
;
134 if (UINT_MAX
/ get_dib_stride( info
->biWidth
, info
->biBitCount
) < abs( info
->biHeight
)) return FALSE
;
136 switch (info
->biBitCount
)
142 return (info
->biCompression
== BI_RGB
);
145 return (info
->biCompression
== BI_BITFIELDS
|| info
->biCompression
== BI_RGB
);
151 /*******************************************************************************************
152 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
154 static BOOL
bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER
*dst
, const BITMAPINFOHEADER
*info
)
156 if (!info
) return FALSE
;
158 if (info
->biSize
== sizeof(BITMAPCOREHEADER
))
160 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
161 dst
->biWidth
= core
->bcWidth
;
162 dst
->biHeight
= core
->bcHeight
;
163 dst
->biPlanes
= core
->bcPlanes
;
164 dst
->biBitCount
= core
->bcBitCount
;
165 dst
->biCompression
= BI_RGB
;
166 dst
->biXPelsPerMeter
= 0;
167 dst
->biYPelsPerMeter
= 0;
169 dst
->biClrImportant
= 0;
171 else if (info
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
177 WARN( "(%u): unknown/wrong size for header\n", info
->biSize
);
181 dst
->biSize
= sizeof(*dst
);
182 if (dst
->biCompression
== BI_RGB
|| dst
->biCompression
== BI_BITFIELDS
)
183 dst
->biSizeImage
= get_dib_image_size( (BITMAPINFO
*)dst
);
187 /*******************************************************************************************
188 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
190 * The resulting sanitized BITMAPINFO is guaranteed to have:
191 * - biSize set to sizeof(BITMAPINFOHEADER)
192 * - biSizeImage set to the actual image size even for non-compressed DIB
193 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
194 * - color table present only for <= 8 bpp, always starts at info->bmiColors
196 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
,
197 UINT coloruse
, BOOL allow_compression
)
201 if (coloruse
> DIB_PAL_COLORS
+ 1) return FALSE
; /* FIXME: handle DIB_PAL_COLORS+1 format */
202 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
203 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
205 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
207 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
209 /* bitfields are always at bmiColors even in larger structures */
210 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
211 dst
->bmiHeader
.biClrUsed
= 0;
213 else if (dst
->bmiHeader
.biBitCount
<= 8)
215 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
216 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
218 if (!colors
) colors
= max_colors
;
219 else colors
= min( colors
, max_colors
);
221 if (coloruse
== DIB_PAL_COLORS
)
223 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
226 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
228 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
233 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
234 for (i
= 0; i
< colors
; i
++)
236 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
237 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
238 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
239 dst
->bmiColors
[i
].rgbReserved
= 0;
242 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
243 dst
->bmiHeader
.biClrUsed
= max_colors
;
245 else dst
->bmiHeader
.biClrUsed
= 0;
250 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
252 PALETTEENTRY palEntry
[256];
253 HPALETTE palette
= GetCurrentObject( hdc
, OBJ_PAL
);
254 int i
, colors
= 1 << info
->bmiHeader
.biBitCount
;
256 info
->bmiHeader
.biClrUsed
= colors
;
258 if (!palette
) return 0;
260 memset( palEntry
, 0, sizeof(palEntry
) );
261 if (!GetPaletteEntries( palette
, 0, colors
, palEntry
))
264 for (i
= 0; i
< colors
; i
++)
266 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
267 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
268 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
269 info
->bmiColors
[i
].rgbReserved
= 0;
275 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
277 PALETTEENTRY entries
[256];
280 const WORD
*index
= (const WORD
*)info
->bmiColors
;
281 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
283 if (!colors
) return TRUE
;
284 if (!(palette
= GetCurrentObject( hdc
, OBJ_PAL
))) return FALSE
;
285 if (!(count
= GetPaletteEntries( palette
, 0, colors
, entries
))) return FALSE
;
287 for (i
= 0; i
< colors
; i
++, index
++)
289 table
[i
].rgbRed
= entries
[*index
% count
].peRed
;
290 table
[i
].rgbGreen
= entries
[*index
% count
].peGreen
;
291 table
[i
].rgbBlue
= entries
[*index
% count
].peBlue
;
292 table
[i
].rgbReserved
= 0;
294 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
295 memcpy( info
->bmiColors
, table
, colors
* sizeof(RGBQUAD
) );
296 memset( info
->bmiColors
+ colors
, 0, (info
->bmiHeader
.biClrUsed
- colors
) * sizeof(RGBQUAD
) );
300 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
302 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
303 const int bpp
= info
->bmiHeader
.biBitCount
;
306 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
308 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
311 static BOOL
build_rle_bitmap( const BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
315 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
317 BYTE skip
, num
, data
;
318 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
320 if (clip
) *clip
= NULL
;
322 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
324 out_bits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, get_dib_image_size( info
) );
325 if (!out_bits
) goto fail
;
329 *clip
= CreateRectRgn( 0, 0, 0, 0 );
330 run
= CreateRectRgn( 0, 0, 0, 0 );
331 if (!*clip
|| !run
) goto fail
;
334 x
= left
= right
= 0;
337 while (i
< info
->bmiHeader
.biSizeImage
- 1)
340 data
= in_bits
[i
+ 1];
345 if (x
+ num
> width
) num
= width
- x
;
348 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
349 if (info
->bmiHeader
.biBitCount
== 8)
350 memset( out_ptr
, s
, num
);
355 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
356 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
361 /* this will write one too many if num is odd, but that doesn't matter */
362 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
372 if(left
!= right
&& clip
)
374 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
375 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
380 left
= right
= x
= 0;
389 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
391 if (x
> width
) x
= width
;
398 else /* data bytes of data */
401 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
402 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
403 skip
= (skip
+ 1) & ~1;
404 if (x
+ num
> width
) num
= width
- x
;
407 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
408 if (info
->bmiHeader
.biBitCount
== 8)
409 memcpy( out_ptr
, in_bits
+ i
, num
);
414 const BYTE
*in_ptr
= in_bits
+ i
;
415 for ( ; num
; num
--, x
++)
419 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
423 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
427 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
438 if (run
) DeleteObject( run
);
439 if (bits
->free
) bits
->free( bits
);
441 bits
->ptr
= out_bits
;
442 bits
->is_copy
= TRUE
;
443 bits
->free
= free_heap_bits
;
448 if (run
) DeleteObject( run
);
449 if (clip
&& *clip
) DeleteObject( *clip
);
450 HeapFree( GetProcessHeap(), 0, out_bits
);
456 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
457 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
458 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
460 DC
*dc
= get_nulldrv_dc( dev
);
461 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
462 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
463 struct bitblt_coords src
, dst
;
464 struct gdi_image_bits src_bits
;
468 INT height
= abs( src_info
->bmiHeader
.biHeight
);
469 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
472 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
473 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
475 src_bits
.ptr
= (void*)bits
;
476 src_bits
.is_copy
= FALSE
;
477 src_bits
.free
= NULL
;
479 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
483 rect
.right
= xDst
+ widthDst
;
484 rect
.bottom
= yDst
+ heightDst
;
485 LPtoDP( dc
->hSelf
, (POINT
*)&rect
, 2 );
488 dst
.width
= rect
.right
- rect
.left
;
489 dst
.height
= rect
.bottom
- rect
.top
;
491 if (dc
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
494 dst
.width
= -dst
.width
;
496 rop
&= ~NOMIRRORBITMAP
;
499 src
.width
= widthSrc
;
501 src
.height
= heightSrc
;
503 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
504 non_stretch_from_origin
= TRUE
;
506 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
508 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
509 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
512 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
514 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
515 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
520 if (dst
.width
< 0 && dst
.width
== src
.width
)
522 /* This is off-by-one, but that's what Windows does */
525 dst
.width
= -dst
.width
;
526 src
.width
= -src
.width
;
528 if (dst
.height
< 0 && dst
.height
== src
.height
)
532 dst
.height
= -dst
.height
;
533 src
.height
= -src
.height
;
537 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
539 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
541 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
542 src
.y
= -src
.height
- 1;
544 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
546 src
.visrect
.left
= 0;
547 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
549 src
.visrect
.bottom
= height
;
550 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
552 if (rop
== SRCCOPY
) ret
= height
;
553 else ret
= src_info
->bmiHeader
.biHeight
;
555 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
557 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
559 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
561 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
563 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
564 copy_bitmapinfo( dst_info
, src_info
);
565 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
566 if (err
== ERROR_BAD_FORMAT
)
568 /* 1-bpp destination without a color table requires a fake 1-entry table
569 * that contains only the background color */
570 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_info
->bmiHeader
.biClrUsed
)
572 COLORREF color
= GetBkColor( dev
->hdc
);
573 dst_info
->bmiColors
[0].rgbRed
= GetRValue( color
);
574 dst_info
->bmiColors
[0].rgbGreen
= GetGValue( color
);
575 dst_info
->bmiColors
[0].rgbBlue
= GetBValue( color
);
576 dst_info
->bmiColors
[0].rgbReserved
= 0;
577 dst_info
->bmiHeader
.biClrUsed
= 1;
580 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
)))
582 /* get rid of the fake 1-bpp table */
583 if (dst_info
->bmiHeader
.biClrUsed
== 1) dst_info
->bmiHeader
.biClrUsed
= 0;
584 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
588 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
590 copy_bitmapinfo( src_info
, dst_info
);
591 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, GetStretchBltMode( dev
->hdc
) );
592 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
597 if (src_bits
.free
) src_bits
.free( &src_bits
);
598 if (clip
) DeleteObject( clip
);
602 /***********************************************************************
603 * StretchDIBits (GDI32.@)
605 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
606 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
607 const BITMAPINFO
*bmi
, UINT coloruse
, DWORD rop
)
609 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
610 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
616 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
618 SetLastError( ERROR_INVALID_PARAMETER
);
622 if ((dc
= get_dc_ptr( hdc
)))
625 physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
626 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
627 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
628 release_dc_ptr( dc
);
634 /******************************************************************************
635 * SetDIBits [GDI32.@]
637 * Sets pixels in a bitmap using colors from DIB.
640 * hdc [I] Handle to device context
641 * hbitmap [I] Handle to bitmap
642 * startscan [I] Starting scan line
643 * lines [I] Number of scan lines
644 * bits [I] Array of bitmap bits
645 * info [I] Address of structure with data
646 * coloruse [I] Type of color indexes to use
649 * Success: Number of scan lines copied
652 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
653 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
657 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
658 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
659 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
660 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
663 struct gdi_image_bits src_bits
;
664 struct bitblt_coords src
, dst
;
665 INT src_to_dst_offset
;
668 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
) || coloruse
> DIB_PAL_COLORS
)
670 SetLastError( ERROR_INVALID_PARAMETER
);
673 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
675 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
676 if (!masks
[0] || !masks
[1] || !masks
[2])
678 SetLastError( ERROR_INVALID_PARAMETER
);
683 src_bits
.ptr
= (void *)bits
;
684 src_bits
.is_copy
= FALSE
;
685 src_bits
.free
= NULL
;
686 src_bits
.param
= NULL
;
688 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
690 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
692 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
694 if (lines
== 0) goto done
;
695 else lines
= src_info
->bmiHeader
.biHeight
;
698 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
701 dst
.visrect
.left
= 0;
703 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
704 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
706 src
.visrect
.left
= 0;
708 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
709 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
711 if (src_info
->bmiHeader
.biHeight
> 0)
713 src_to_dst_offset
= -startscan
;
714 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
715 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
719 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
720 /* Unlike the bottom-up case, Windows doesn't limit lines. */
721 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
726 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
727 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
728 src
.visrect
= dst
.visrect
;
729 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
731 src
.x
= src
.visrect
.left
;
732 src
.y
= src
.visrect
.top
;
733 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
734 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
736 dst
.x
= dst
.visrect
.left
;
737 dst
.y
= dst
.visrect
.top
;
738 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
739 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
741 copy_bitmapinfo( dst_info
, src_info
);
743 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
744 if (err
== ERROR_BAD_FORMAT
)
746 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
747 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
752 if (src_bits
.free
) src_bits
.free( &src_bits
);
753 if (clip
) DeleteObject( clip
);
754 GDI_ReleaseObj( hbitmap
);
759 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
760 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
761 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
763 DC
*dc
= get_nulldrv_dc( dev
);
764 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
765 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
766 struct bitblt_coords src
, dst
;
767 struct gdi_image_bits src_bits
;
775 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
776 height
= abs( src_info
->bmiHeader
.biHeight
);
778 src_bits
.ptr
= (void *)bits
;
779 src_bits
.is_copy
= FALSE
;
780 src_bits
.free
= NULL
;
782 if (!lines
) return 0;
783 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
785 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
789 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
790 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
791 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
796 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
800 if (startscan
>= height
) return 0;
801 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
803 /* map src to top-down coordinates with startscan as origin */
805 src
.y
= startscan
+ lines
- (y_src
+ cy
);
812 /* get rid of unnecessary lines */
813 if (src
.y
>= lines
) return 0;
817 else if (src
.y
>= lines
) return lines
;
819 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
822 src
.visrect
.left
= src
.x
;
823 src
.visrect
.top
= src
.y
;
824 src
.visrect
.right
= src
.x
+ cx
;
825 src
.visrect
.bottom
= src
.y
+ cy
;
828 rect
.right
= src_info
->bmiHeader
.biWidth
;
829 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
830 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
838 LPtoDP( dev
->hdc
, &pt
, 1 );
843 if (GetLayout( dev
->hdc
) & LAYOUT_RTL
) dst
.x
-= cx
- 1;
847 rect
.right
= dst
.x
+ cx
;
848 rect
.bottom
= dst
.y
+ cy
;
849 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
851 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
852 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
853 src
.visrect
= dst
.visrect
= rect
;
854 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
855 if (is_rect_empty( &dst
.visrect
)) goto done
;
856 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
858 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
859 copy_bitmapinfo( dst_info
, src_info
);
860 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
861 if (err
== ERROR_BAD_FORMAT
)
863 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
864 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
869 if (src_bits
.free
) src_bits
.free( &src_bits
);
870 if (clip
) DeleteObject( clip
);
874 /***********************************************************************
875 * SetDIBitsToDevice (GDI32.@)
877 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
878 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
879 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
882 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
883 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
889 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
891 SetLastError( ERROR_INVALID_PARAMETER
);
895 if ((dc
= get_dc_ptr( hdc
)))
898 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
899 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
900 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
901 release_dc_ptr( dc
);
906 /***********************************************************************
907 * SetDIBColorTable (GDI32.@)
909 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
915 if (!(dc
= get_dc_ptr( hdc
))) return 0;
917 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
919 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
921 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
922 memcpy(bitmap
->color_table
+ startpos
, colors
, result
* sizeof(RGBQUAD
));
924 GDI_ReleaseObj( dc
->hBitmap
);
926 if (result
) /* update colors of selected objects */
928 SetTextColor( hdc
, dc
->textColor
);
929 SetBkColor( hdc
, dc
->backgroundColor
);
930 SelectObject( hdc
, dc
->hPen
);
931 SelectObject( hdc
, dc
->hBrush
);
934 release_dc_ptr( dc
);
939 /***********************************************************************
940 * GetDIBColorTable (GDI32.@)
942 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
948 if (!(dc
= get_dc_ptr( hdc
))) return 0;
950 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
952 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
954 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
955 memcpy(colors
, bitmap
->color_table
+ startpos
, result
* sizeof(RGBQUAD
));
957 GDI_ReleaseObj( dc
->hBitmap
);
959 release_dc_ptr( dc
);
963 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
964 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
966 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
968 BITMAPINFOHEADER header
;
970 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
971 header
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
972 header
.biHeight
= bmp
->dib
.dsBm
.bmHeight
;
974 header
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
976 switch (header
.biBitCount
)
980 header
.biCompression
= BI_BITFIELDS
;
983 header
.biCompression
= BI_RGB
;
987 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
988 header
.biXPelsPerMeter
= 0;
989 header
.biYPelsPerMeter
= 0;
990 header
.biClrUsed
= 0;
991 header
.biClrImportant
= 0;
993 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
995 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
997 coreheader
->bcWidth
= header
.biWidth
;
998 coreheader
->bcHeight
= header
.biHeight
;
999 coreheader
->bcPlanes
= header
.biPlanes
;
1000 coreheader
->bcBitCount
= header
.biBitCount
;
1003 info
->bmiHeader
= header
;
1005 return bmp
->dib
.dsBm
.bmHeight
;
1008 /************************************************************************
1011 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1013 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1015 assert( src
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
) );
1017 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1019 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1020 if (coloruse
== DIB_PAL_COLORS
)
1021 memcpy( core
->bmciColors
, src
->bmiColors
, src
->bmiHeader
.biClrUsed
* sizeof(WORD
) );
1025 for (i
= 0; i
< src
->bmiHeader
.biClrUsed
; i
++)
1027 core
->bmciColors
[i
].rgbtRed
= src
->bmiColors
[i
].rgbRed
;
1028 core
->bmciColors
[i
].rgbtGreen
= src
->bmiColors
[i
].rgbGreen
;
1029 core
->bmciColors
[i
].rgbtBlue
= src
->bmiColors
[i
].rgbBlue
;
1035 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1036 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
1038 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1039 /* bitfields are always at bmiColors even in larger structures */
1040 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1041 else if (src
->bmiHeader
.biClrUsed
)
1043 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1046 if (coloruse
== DIB_PAL_COLORS
)
1047 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1049 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1050 memcpy( colorptr
, src
->bmiColors
, size
);
1055 const RGBQUAD
*get_default_color_table( int bpp
)
1057 static const RGBQUAD table_1
[2] =
1059 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1061 static const RGBQUAD table_4
[16] =
1063 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1064 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1065 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1066 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1068 static const RGBQUAD table_8
[256] =
1070 /* first and last 10 entries are the default system palette entries */
1071 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1072 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1073 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1074 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1075 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1076 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1077 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1078 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1079 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1080 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1081 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1082 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1083 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1084 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1085 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1086 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1087 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1088 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1089 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1090 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1091 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1092 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1093 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1094 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1095 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1096 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1097 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1098 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1099 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1100 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1101 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1102 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1103 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1104 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1105 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1106 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1107 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1108 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1109 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1110 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1111 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1112 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1113 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1114 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1115 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1116 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1117 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1118 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1119 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1120 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1121 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1122 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1123 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1124 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1125 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1126 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1127 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1128 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1129 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1130 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1131 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1132 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1133 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1134 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1139 case 1: return table_1
;
1140 case 4: return table_4
;
1141 case 8: return table_8
;
1142 default: return NULL
;
1146 void fill_default_color_table( BITMAPINFO
*info
)
1148 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1149 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1150 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1153 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1155 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1156 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1157 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1158 info
->bmiHeader
.biPlanes
= 1;
1159 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1160 info
->bmiHeader
.biCompression
= BI_RGB
;
1161 info
->bmiHeader
.biXPelsPerMeter
= 0;
1162 info
->bmiHeader
.biYPelsPerMeter
= 0;
1163 info
->bmiHeader
.biClrUsed
= 0;
1164 info
->bmiHeader
.biClrImportant
= 0;
1167 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1169 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1170 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1171 unsigned int info_size
;
1173 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1175 info_size
= get_dib_info_size( info
, usage
);
1176 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ info
->bmiHeader
.biSizeImage
)))
1178 memcpy( ret
, info
, info_size
);
1179 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size( src_info
, usage
),
1180 info
->bmiHeader
.biSizeImage
);
1185 /******************************************************************************
1186 * GetDIBits [GDI32.@]
1188 * Retrieves bits of bitmap and copies to buffer.
1191 * Success: Number of scan lines copied from bitmap
1194 INT WINAPI
GetDIBits(
1195 HDC hdc
, /* [in] Handle to device context */
1196 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1197 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1198 UINT lines
, /* [in] Number of scan lines to copy */
1199 LPVOID bits
, /* [out] Address of array for bitmap bits */
1200 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1201 UINT coloruse
) /* [in] RGB or palette index */
1205 int i
, dst_to_src_offset
, ret
= 0;
1207 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1208 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1209 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1210 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1211 struct gdi_image_bits src_bits
;
1212 struct bitblt_coords src
, dst
;
1213 BOOL empty_rect
= FALSE
;
1215 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1216 own copy and transfer the colour info back at the end */
1217 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1218 if (coloruse
> DIB_PAL_COLORS
) return 0;
1220 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1222 dst_info
->bmiHeader
.biClrUsed
= 0;
1223 dst_info
->bmiHeader
.biClrImportant
= 0;
1225 if (!(dc
= get_dc_ptr( hdc
)))
1227 SetLastError( ERROR_INVALID_PARAMETER
);
1231 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1233 release_dc_ptr( dc
);
1237 src
.visrect
.left
= 0;
1238 src
.visrect
.top
= 0;
1239 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1240 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1242 dst
.visrect
.left
= 0;
1243 dst
.visrect
.top
= 0;
1244 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1245 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1247 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1250 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1252 ret
= fill_query_info( info
, bmp
);
1256 /* validate parameters */
1258 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1259 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1261 switch (dst_info
->bmiHeader
.biCompression
)
1264 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1265 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1266 if (bits
) goto done
; /* can't retrieve compressed bits */
1269 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1270 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1271 if (bits
) goto done
; /* can't retrieve compressed bits */
1274 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1277 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1278 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1279 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1280 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1281 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1282 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1283 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1291 if (dst_info
->bmiHeader
.biHeight
> 0)
1293 dst_to_src_offset
= -startscan
;
1294 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1295 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1299 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1300 if (dst_to_src_offset
< 0)
1302 dst_to_src_offset
= 0;
1303 lines
= dst
.visrect
.bottom
- startscan
;
1305 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1308 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1309 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1310 dst
.visrect
= src
.visrect
;
1311 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1313 if (dst_info
->bmiHeader
.biHeight
> 0)
1315 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1317 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1318 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1319 memset( bits
, 0, pad_bytes
);
1320 bits
= (char *)bits
+ pad_bytes
;
1325 if (dst
.visrect
.bottom
< lines
)
1327 int pad_lines
= lines
- dst
.visrect
.bottom
;
1328 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1329 int pad_bytes
= pad_lines
* stride
;
1330 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1334 if (empty_rect
) bits
= NULL
;
1336 src
.x
= src
.visrect
.left
;
1337 src
.y
= src
.visrect
.top
;
1338 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1339 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1344 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1348 /* fill out the src colour table, if it needs one */
1349 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1350 fill_default_color_table( src_info
);
1352 /* if the src and dst are the same depth, copy the colour info across */
1353 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1355 switch (src_info
->bmiHeader
.biBitCount
)
1358 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1360 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1361 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1365 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1367 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1368 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1372 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1373 copy_color_info( dst_info
, src_info
, coloruse
);
1375 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1377 if( coloruse
== DIB_PAL_COLORS
)
1379 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1383 fill_default_color_table( dst_info
);
1389 if(dst_info
->bmiHeader
.biHeight
> 0)
1390 dst_info
->bmiHeader
.biHeight
= src
.height
;
1392 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1394 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1395 if (src_bits
.free
) src_bits
.free( &src_bits
);
1401 if (coloruse
== DIB_PAL_COLORS
)
1403 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1404 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1408 copy_color_info( info
, dst_info
, coloruse
);
1409 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
)) info
->bmiHeader
.biClrUsed
= 0;
1412 release_dc_ptr( dc
);
1413 GDI_ReleaseObj( hbitmap
);
1418 /***********************************************************************
1419 * CreateDIBitmap (GDI32.@)
1421 * Creates a DDB (device dependent bitmap) from a DIB.
1422 * The DDB will have the same color depth as the reference DC.
1424 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1425 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1428 BITMAPINFOHEADER info
;
1432 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1433 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1434 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1435 if (info
.biWidth
< 0) return 0;
1437 /* Top-down DIBs have a negative height */
1438 height
= abs( info
.biHeight
);
1440 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1441 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1442 info
.biBitCount
, info
.biCompression
);
1445 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1447 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1451 if (init
& CBM_INIT
)
1453 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1455 DeleteObject( handle
);
1465 /***********************************************************************
1466 * CreateDIBSection (GDI32.@)
1468 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
1469 VOID
**bits
, HANDLE section
, DWORD offset
)
1471 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1472 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1475 void *mapBits
= NULL
;
1477 if (bits
) *bits
= NULL
;
1478 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1479 if (usage
> DIB_PAL_COLORS
) return 0;
1480 if (info
->bmiHeader
.biPlanes
!= 1)
1482 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1483 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1486 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1488 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1489 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1490 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1491 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1492 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1494 bmp
->dib
.dsBm
.bmType
= 0;
1495 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1496 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1497 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1498 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1499 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1500 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1502 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1504 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1506 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1507 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1508 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1510 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1513 /* set dsBitfields values */
1514 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1516 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1517 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1518 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1519 bmp
->dib
.dsBitfields
[2] = 0x001f;
1521 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1523 if (usage
== DIB_PAL_COLORS
) goto error
;
1524 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1525 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1526 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1527 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1529 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1531 /* get storage location for DIB bits */
1535 SYSTEM_INFO SystemInfo
;
1539 GetSystemInfo( &SystemInfo
);
1540 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1541 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1542 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1543 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1548 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1549 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1551 bmp
->dib
.dshSection
= section
;
1552 bmp
->dib
.dsOffset
= offset
;
1554 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1556 if (!(ret
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1558 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1562 if (section
) UnmapViewOfFile( mapBits
);
1563 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1564 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1565 HeapFree( GetProcessHeap(), 0, bmp
);
1570 /***********************************************************************
1573 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
)
1580 if (!(dc
= get_dc_ptr( hdc
))) return 0;
1582 if (GetObjectType( hdc
) != OBJ_MEMDC
)
1588 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
1590 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
1596 if (GDI_get_ref_count( handle
))
1598 WARN( "Bitmap already selected in another DC\n" );
1599 GDI_ReleaseObj( handle
);
1604 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
1605 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
1607 GDI_ReleaseObj( handle
);
1612 dc
->hBitmap
= handle
;
1613 GDI_inc_ref_count( handle
);
1615 dc
->vis_rect
.left
= 0;
1616 dc
->vis_rect
.top
= 0;
1617 dc
->vis_rect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
1618 dc
->vis_rect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
1619 dc
->device_rect
= dc
->vis_rect
;
1620 GDI_ReleaseObj( handle
);
1622 GDI_dec_ref_count( ret
);
1626 release_dc_ptr( dc
);
1631 /***********************************************************************
1634 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1637 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
1641 if (!buffer
) ret
= sizeof(BITMAP
);
1642 else if (count
>= sizeof(DIBSECTION
))
1644 DIBSECTION
*dib
= buffer
;
1646 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1647 ret
= sizeof(DIBSECTION
);
1649 else if (count
>= sizeof(BITMAP
))
1651 BITMAP
*bitmap
= buffer
;
1652 *bitmap
= bmp
->dib
.dsBm
;
1653 ret
= sizeof(BITMAP
);
1656 GDI_ReleaseObj( handle
);
1661 /***********************************************************************
1664 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1668 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1670 if (bmp
->dib
.dshSection
)
1672 SYSTEM_INFO SystemInfo
;
1673 GetSystemInfo( &SystemInfo
);
1674 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1675 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1677 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1679 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1680 return HeapFree( GetProcessHeap(), 0, bmp
);