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_565
[3] = {0xf800, 0x07e0, 0x001f};
965 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
967 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
969 BITMAPINFOHEADER header
;
971 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
972 header
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
973 header
.biHeight
= bmp
->dib
.dsBm
.bmHeight
;
975 header
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
977 switch (header
.biBitCount
)
981 header
.biCompression
= BI_BITFIELDS
;
984 header
.biCompression
= BI_RGB
;
988 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
989 header
.biXPelsPerMeter
= 0;
990 header
.biYPelsPerMeter
= 0;
991 header
.biClrUsed
= 0;
992 header
.biClrImportant
= 0;
994 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
996 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
998 coreheader
->bcWidth
= header
.biWidth
;
999 coreheader
->bcHeight
= header
.biHeight
;
1000 coreheader
->bcPlanes
= header
.biPlanes
;
1001 coreheader
->bcBitCount
= header
.biBitCount
;
1004 info
->bmiHeader
= header
;
1006 return bmp
->dib
.dsBm
.bmHeight
;
1009 /************************************************************************
1012 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1014 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1016 assert( src
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
) );
1018 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1020 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1021 if (coloruse
== DIB_PAL_COLORS
)
1022 memcpy( core
->bmciColors
, src
->bmiColors
, src
->bmiHeader
.biClrUsed
* sizeof(WORD
) );
1026 for (i
= 0; i
< src
->bmiHeader
.biClrUsed
; i
++)
1028 core
->bmciColors
[i
].rgbtRed
= src
->bmiColors
[i
].rgbRed
;
1029 core
->bmciColors
[i
].rgbtGreen
= src
->bmiColors
[i
].rgbGreen
;
1030 core
->bmciColors
[i
].rgbtBlue
= src
->bmiColors
[i
].rgbBlue
;
1036 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1037 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
1039 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1040 /* bitfields are always at bmiColors even in larger structures */
1041 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1042 else if (src
->bmiHeader
.biClrUsed
)
1044 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1047 if (coloruse
== DIB_PAL_COLORS
)
1048 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1050 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1051 memcpy( colorptr
, src
->bmiColors
, size
);
1056 const RGBQUAD
*get_default_color_table( int bpp
)
1058 static const RGBQUAD table_1
[2] =
1060 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1062 static const RGBQUAD table_4
[16] =
1064 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1065 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1066 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1067 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1069 static const RGBQUAD table_8
[256] =
1071 /* first and last 10 entries are the default system palette entries */
1072 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1073 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1074 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1075 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1076 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1077 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1078 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1079 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1080 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1081 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1082 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1083 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1084 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1085 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1086 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1087 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1088 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1089 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1090 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1091 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1092 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1093 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1094 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1095 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1096 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1097 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1098 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1099 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1100 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1101 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1102 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1103 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1104 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1105 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1106 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1107 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1108 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1109 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1110 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1111 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1112 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1113 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1114 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1115 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1116 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1117 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1118 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1119 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1120 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1121 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1122 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1123 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1124 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1125 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1126 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1127 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1128 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1129 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1130 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1131 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1132 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1133 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1134 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1135 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1140 case 1: return table_1
;
1141 case 4: return table_4
;
1142 case 8: return table_8
;
1143 default: return NULL
;
1147 void fill_default_color_table( BITMAPINFO
*info
)
1149 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1150 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1151 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1154 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1156 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1157 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1158 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1159 info
->bmiHeader
.biPlanes
= 1;
1160 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1161 info
->bmiHeader
.biCompression
= BI_RGB
;
1162 info
->bmiHeader
.biXPelsPerMeter
= 0;
1163 info
->bmiHeader
.biYPelsPerMeter
= 0;
1164 info
->bmiHeader
.biClrUsed
= 0;
1165 info
->bmiHeader
.biClrImportant
= 0;
1168 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1170 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1171 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1172 unsigned int info_size
;
1174 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1176 info_size
= get_dib_info_size( info
, usage
);
1177 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ info
->bmiHeader
.biSizeImage
)))
1179 memcpy( ret
, info
, info_size
);
1180 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size( src_info
, usage
),
1181 info
->bmiHeader
.biSizeImage
);
1186 /******************************************************************************
1187 * GetDIBits [GDI32.@]
1189 * Retrieves bits of bitmap and copies to buffer.
1192 * Success: Number of scan lines copied from bitmap
1195 INT WINAPI
GetDIBits(
1196 HDC hdc
, /* [in] Handle to device context */
1197 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1198 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1199 UINT lines
, /* [in] Number of scan lines to copy */
1200 LPVOID bits
, /* [out] Address of array for bitmap bits */
1201 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1202 UINT coloruse
) /* [in] RGB or palette index */
1206 int i
, dst_to_src_offset
, ret
= 0;
1208 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1209 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1210 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1211 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1212 struct gdi_image_bits src_bits
;
1213 struct bitblt_coords src
, dst
;
1214 BOOL empty_rect
= FALSE
;
1216 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1217 own copy and transfer the colour info back at the end */
1218 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1219 if (coloruse
> DIB_PAL_COLORS
) return 0;
1221 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1223 dst_info
->bmiHeader
.biClrUsed
= 0;
1224 dst_info
->bmiHeader
.biClrImportant
= 0;
1226 if (!(dc
= get_dc_ptr( hdc
)))
1228 SetLastError( ERROR_INVALID_PARAMETER
);
1232 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1234 release_dc_ptr( dc
);
1238 src
.visrect
.left
= 0;
1239 src
.visrect
.top
= 0;
1240 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1241 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1243 dst
.visrect
.left
= 0;
1244 dst
.visrect
.top
= 0;
1245 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1246 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1248 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1251 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1253 ret
= fill_query_info( info
, bmp
);
1257 /* validate parameters */
1259 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1260 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1262 switch (dst_info
->bmiHeader
.biCompression
)
1265 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1266 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1267 if (bits
) goto done
; /* can't retrieve compressed bits */
1270 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1271 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1272 if (bits
) goto done
; /* can't retrieve compressed bits */
1275 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1278 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1279 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1280 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1281 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1282 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1283 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1284 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1292 if (dst_info
->bmiHeader
.biHeight
> 0)
1294 dst_to_src_offset
= -startscan
;
1295 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1296 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1300 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1301 if (dst_to_src_offset
< 0)
1303 dst_to_src_offset
= 0;
1304 lines
= dst
.visrect
.bottom
- startscan
;
1306 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1309 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1310 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1311 dst
.visrect
= src
.visrect
;
1312 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1314 if (dst_info
->bmiHeader
.biHeight
> 0)
1316 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1318 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1319 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1320 memset( bits
, 0, pad_bytes
);
1321 bits
= (char *)bits
+ pad_bytes
;
1326 if (dst
.visrect
.bottom
< lines
)
1328 int pad_lines
= lines
- dst
.visrect
.bottom
;
1329 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1330 int pad_bytes
= pad_lines
* stride
;
1331 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1335 if (empty_rect
) bits
= NULL
;
1337 src
.x
= src
.visrect
.left
;
1338 src
.y
= src
.visrect
.top
;
1339 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1340 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1345 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1349 /* fill out the src colour table, if it needs one */
1350 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1351 fill_default_color_table( src_info
);
1353 /* if the src and dst are the same depth, copy the colour info across */
1354 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1356 switch (src_info
->bmiHeader
.biBitCount
)
1359 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1361 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1362 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1366 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1368 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1369 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1373 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1374 copy_color_info( dst_info
, src_info
, coloruse
);
1376 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1378 if( coloruse
== DIB_PAL_COLORS
)
1380 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1384 fill_default_color_table( dst_info
);
1390 if(dst_info
->bmiHeader
.biHeight
> 0)
1391 dst_info
->bmiHeader
.biHeight
= src
.height
;
1393 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1395 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1396 if (src_bits
.free
) src_bits
.free( &src_bits
);
1402 if (coloruse
== DIB_PAL_COLORS
)
1404 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1405 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1409 copy_color_info( info
, dst_info
, coloruse
);
1410 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
)) info
->bmiHeader
.biClrUsed
= 0;
1413 release_dc_ptr( dc
);
1414 GDI_ReleaseObj( hbitmap
);
1419 /***********************************************************************
1420 * CreateDIBitmap (GDI32.@)
1422 * Creates a DDB (device dependent bitmap) from a DIB.
1423 * The DDB will have the same color depth as the reference DC.
1425 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1426 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1429 BITMAPINFOHEADER info
;
1433 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1434 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1435 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1436 if (info
.biWidth
< 0) return 0;
1438 /* Top-down DIBs have a negative height */
1439 height
= abs( info
.biHeight
);
1441 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1442 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1443 info
.biBitCount
, info
.biCompression
);
1446 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1448 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1452 if (init
& CBM_INIT
)
1454 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1456 DeleteObject( handle
);
1466 /***********************************************************************
1467 * CreateDIBSection (GDI32.@)
1469 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
1470 VOID
**bits
, HANDLE section
, DWORD offset
)
1472 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1473 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1476 void *mapBits
= NULL
;
1478 if (bits
) *bits
= NULL
;
1479 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1480 if (usage
> DIB_PAL_COLORS
) return 0;
1481 if (info
->bmiHeader
.biPlanes
!= 1)
1483 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1484 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1487 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1489 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1490 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1491 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1492 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1493 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1495 bmp
->dib
.dsBm
.bmType
= 0;
1496 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1497 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1498 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1499 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1500 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1501 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1503 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1505 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1507 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1508 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1509 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1511 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1514 /* set dsBitfields values */
1515 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1517 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1518 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1519 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1520 bmp
->dib
.dsBitfields
[2] = 0x001f;
1522 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1524 if (usage
== DIB_PAL_COLORS
) goto error
;
1525 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1526 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1527 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1528 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1530 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1532 /* get storage location for DIB bits */
1536 SYSTEM_INFO SystemInfo
;
1540 GetSystemInfo( &SystemInfo
);
1541 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1542 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1543 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1544 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1549 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1550 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1552 bmp
->dib
.dshSection
= section
;
1553 bmp
->dib
.dsOffset
= offset
;
1555 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1557 if (!(ret
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1559 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1563 if (section
) UnmapViewOfFile( mapBits
);
1564 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1565 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1566 HeapFree( GetProcessHeap(), 0, bmp
);
1571 /***********************************************************************
1574 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
)
1581 if (!(dc
= get_dc_ptr( hdc
))) return 0;
1583 if (GetObjectType( hdc
) != OBJ_MEMDC
)
1589 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
1591 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
1597 if (GDI_get_ref_count( handle
))
1599 WARN( "Bitmap already selected in another DC\n" );
1600 GDI_ReleaseObj( handle
);
1605 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
1606 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
1608 GDI_ReleaseObj( handle
);
1613 dc
->hBitmap
= handle
;
1614 GDI_inc_ref_count( handle
);
1616 dc
->vis_rect
.left
= 0;
1617 dc
->vis_rect
.top
= 0;
1618 dc
->vis_rect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
1619 dc
->vis_rect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
1620 dc
->device_rect
= dc
->vis_rect
;
1621 GDI_ReleaseObj( handle
);
1623 GDI_dec_ref_count( ret
);
1627 release_dc_ptr( dc
);
1632 /***********************************************************************
1635 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1638 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
1642 if (!buffer
) ret
= sizeof(BITMAP
);
1643 else if (count
>= sizeof(DIBSECTION
))
1645 DIBSECTION
*dib
= buffer
;
1647 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1648 ret
= sizeof(DIBSECTION
);
1650 else if (count
>= sizeof(BITMAP
))
1652 BITMAP
*bitmap
= buffer
;
1653 *bitmap
= bmp
->dib
.dsBm
;
1654 ret
= sizeof(BITMAP
);
1657 GDI_ReleaseObj( handle
);
1662 /***********************************************************************
1665 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1669 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1671 if (bmp
->dib
.dshSection
)
1673 SYSTEM_INFO SystemInfo
;
1674 GetSystemInfo( &SystemInfo
);
1675 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1676 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1678 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1680 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1681 return HeapFree( GetProcessHeap(), 0, bmp
);