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
71 #include "gdi_private.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
77 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
);
78 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
79 static BOOL
DIB_DeleteObject( HGDIOBJ handle
);
81 static const struct gdi_obj_funcs dib_funcs
=
83 DIB_SelectObject
, /* pSelectObject */
84 DIB_GetObject
, /* pGetObjectA */
85 DIB_GetObject
, /* pGetObjectW */
86 NULL
, /* pUnrealizeObject */
87 DIB_DeleteObject
/* pDeleteObject */
90 /***********************************************************************
93 * Return the size of the bitmap info structure including color table.
95 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
97 unsigned int colors
, size
, masks
= 0;
99 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
101 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
102 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
103 return sizeof(BITMAPCOREHEADER
) + colors
*
104 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
106 else /* assume BITMAPINFOHEADER */
108 if (info
->bmiHeader
.biClrUsed
) colors
= min( info
->bmiHeader
.biClrUsed
, 256 );
109 else colors
= info
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << info
->bmiHeader
.biBitCount
;
110 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
111 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
112 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
116 /*******************************************************************************************
117 * Verify that the DIB parameters are valid.
119 static BOOL
is_valid_dib_format( const BITMAPINFOHEADER
*info
, BOOL allow_compression
)
121 if (info
->biWidth
<= 0) return FALSE
;
122 if (info
->biHeight
== 0) return FALSE
;
124 if (allow_compression
&& (info
->biCompression
== BI_RLE4
|| info
->biCompression
== BI_RLE8
))
126 if (info
->biHeight
< 0) return FALSE
;
127 if (!info
->biSizeImage
) return FALSE
;
128 return info
->biBitCount
== (info
->biCompression
== BI_RLE4
? 4 : 8);
131 if (!info
->biPlanes
) return FALSE
;
133 /* check for size overflow */
134 if (!info
->biBitCount
) return FALSE
;
135 if (UINT_MAX
/ info
->biBitCount
< info
->biWidth
) return FALSE
;
136 if (UINT_MAX
/ get_dib_stride( info
->biWidth
, info
->biBitCount
) < abs( info
->biHeight
)) return FALSE
;
138 switch (info
->biBitCount
)
144 return (info
->biCompression
== BI_RGB
);
147 return (info
->biCompression
== BI_BITFIELDS
|| info
->biCompression
== BI_RGB
);
153 /*******************************************************************************************
154 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
156 static BOOL
bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER
*dst
, const BITMAPINFOHEADER
*info
)
158 if (!info
) return FALSE
;
160 if (info
->biSize
== sizeof(BITMAPCOREHEADER
))
162 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
163 dst
->biWidth
= core
->bcWidth
;
164 dst
->biHeight
= core
->bcHeight
;
165 dst
->biPlanes
= core
->bcPlanes
;
166 dst
->biBitCount
= core
->bcBitCount
;
167 dst
->biCompression
= BI_RGB
;
168 dst
->biXPelsPerMeter
= 0;
169 dst
->biYPelsPerMeter
= 0;
171 dst
->biClrImportant
= 0;
173 else if (info
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
179 WARN( "(%u): unknown/wrong size for header\n", info
->biSize
);
183 dst
->biSize
= sizeof(*dst
);
184 if (dst
->biCompression
== BI_RGB
|| dst
->biCompression
== BI_BITFIELDS
)
185 dst
->biSizeImage
= get_dib_image_size( (BITMAPINFO
*)dst
);
189 /*******************************************************************************************
190 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
192 * The resulting sanitized BITMAPINFO is guaranteed to have:
193 * - biSize set to sizeof(BITMAPINFOHEADER)
194 * - biSizeImage set to the actual image size even for non-compressed DIB
195 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
196 * - color table present only for <= 8 bpp, always starts at info->bmiColors
198 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
,
199 UINT coloruse
, BOOL allow_compression
)
203 if (coloruse
> DIB_PAL_COLORS
+ 1) return FALSE
; /* FIXME: handle DIB_PAL_COLORS+1 format */
204 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
205 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
207 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
209 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
211 /* bitfields are always at bmiColors even in larger structures */
212 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
213 dst
->bmiHeader
.biClrUsed
= 0;
215 else if (dst
->bmiHeader
.biBitCount
<= 8)
217 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
218 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
220 if (!colors
) colors
= max_colors
;
221 else colors
= min( colors
, max_colors
);
223 if (coloruse
== DIB_PAL_COLORS
)
225 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
228 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
230 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
235 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
236 for (i
= 0; i
< colors
; i
++)
238 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
239 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
240 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
241 dst
->bmiColors
[i
].rgbReserved
= 0;
244 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
245 dst
->bmiHeader
.biClrUsed
= max_colors
;
247 else dst
->bmiHeader
.biClrUsed
= 0;
252 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
254 PALETTEENTRY palEntry
[256];
255 HPALETTE palette
= GetCurrentObject( hdc
, OBJ_PAL
);
256 int i
, colors
= 1 << info
->bmiHeader
.biBitCount
;
258 info
->bmiHeader
.biClrUsed
= colors
;
260 if (!palette
) return 0;
262 memset( palEntry
, 0, sizeof(palEntry
) );
263 if (!GetPaletteEntries( palette
, 0, colors
, palEntry
))
266 for (i
= 0; i
< colors
; i
++)
268 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
269 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
270 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
271 info
->bmiColors
[i
].rgbReserved
= 0;
277 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
279 PALETTEENTRY entries
[256];
282 const WORD
*index
= (const WORD
*)info
->bmiColors
;
283 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
285 if (!colors
) return TRUE
;
286 if (!(palette
= GetCurrentObject( hdc
, OBJ_PAL
))) return FALSE
;
287 if (!(count
= GetPaletteEntries( palette
, 0, colors
, entries
))) return FALSE
;
289 for (i
= 0; i
< colors
; i
++, index
++)
291 table
[i
].rgbRed
= entries
[*index
% count
].peRed
;
292 table
[i
].rgbGreen
= entries
[*index
% count
].peGreen
;
293 table
[i
].rgbBlue
= entries
[*index
% count
].peBlue
;
294 table
[i
].rgbReserved
= 0;
296 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
297 memcpy( info
->bmiColors
, table
, colors
* sizeof(RGBQUAD
) );
298 memset( info
->bmiColors
+ colors
, 0, (info
->bmiHeader
.biClrUsed
- colors
) * sizeof(RGBQUAD
) );
302 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
304 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
305 const int bpp
= info
->bmiHeader
.biBitCount
;
308 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
310 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
313 static BOOL
build_rle_bitmap( const BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
317 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
319 BYTE skip
, num
, data
;
320 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
322 if (clip
) *clip
= NULL
;
324 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
326 out_bits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, get_dib_image_size( info
) );
327 if (!out_bits
) goto fail
;
331 *clip
= CreateRectRgn( 0, 0, 0, 0 );
332 run
= CreateRectRgn( 0, 0, 0, 0 );
333 if (!*clip
|| !run
) goto fail
;
336 x
= left
= right
= 0;
339 while (i
< info
->bmiHeader
.biSizeImage
- 1)
342 data
= in_bits
[i
+ 1];
347 if (x
+ num
> width
) num
= width
- x
;
350 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
351 if (info
->bmiHeader
.biBitCount
== 8)
352 memset( out_ptr
, s
, num
);
357 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
358 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
363 /* this will write one too many if num is odd, but that doesn't matter */
364 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
374 if(left
!= right
&& clip
)
376 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
377 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
382 left
= right
= x
= 0;
391 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
393 if (x
> width
) x
= width
;
400 else /* data bytes of data */
403 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
404 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
405 skip
= (skip
+ 1) & ~1;
406 if (x
+ num
> width
) num
= width
- x
;
409 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
410 if (info
->bmiHeader
.biBitCount
== 8)
411 memcpy( out_ptr
, in_bits
+ i
, num
);
416 const BYTE
*in_ptr
= in_bits
+ i
;
417 for ( ; num
; num
--, x
++)
421 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
425 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
429 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
440 if (run
) DeleteObject( run
);
441 if (bits
->free
) bits
->free( bits
);
443 bits
->ptr
= out_bits
;
444 bits
->is_copy
= TRUE
;
445 bits
->free
= free_heap_bits
;
450 if (run
) DeleteObject( run
);
451 if (clip
&& *clip
) DeleteObject( *clip
);
452 HeapFree( GetProcessHeap(), 0, out_bits
);
458 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
459 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
460 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
462 DC
*dc
= get_nulldrv_dc( dev
);
463 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
464 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
465 struct bitblt_coords src
, dst
;
466 struct gdi_image_bits src_bits
;
470 INT height
= abs( src_info
->bmiHeader
.biHeight
);
471 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
474 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
475 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
477 src_bits
.ptr
= (void*)bits
;
478 src_bits
.is_copy
= FALSE
;
479 src_bits
.free
= NULL
;
481 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
485 rect
.right
= xDst
+ widthDst
;
486 rect
.bottom
= yDst
+ heightDst
;
487 LPtoDP( dc
->hSelf
, (POINT
*)&rect
, 2 );
490 dst
.width
= rect
.right
- rect
.left
;
491 dst
.height
= rect
.bottom
- rect
.top
;
493 if (dc
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
496 dst
.width
= -dst
.width
;
498 rop
&= ~NOMIRRORBITMAP
;
501 src
.width
= widthSrc
;
503 src
.height
= heightSrc
;
505 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
506 non_stretch_from_origin
= TRUE
;
508 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
510 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
511 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
514 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
516 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
517 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
522 if (dst
.width
< 0 && dst
.width
== src
.width
)
524 /* This is off-by-one, but that's what Windows does */
527 dst
.width
= -dst
.width
;
528 src
.width
= -src
.width
;
530 if (dst
.height
< 0 && dst
.height
== src
.height
)
534 dst
.height
= -dst
.height
;
535 src
.height
= -src
.height
;
539 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
541 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
543 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
544 src
.y
= -src
.height
- 1;
546 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
548 src
.visrect
.left
= 0;
549 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
551 src
.visrect
.bottom
= height
;
552 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
554 if (rop
== SRCCOPY
) ret
= height
;
555 else ret
= src_info
->bmiHeader
.biHeight
;
557 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
559 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
561 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
563 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
565 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
566 copy_bitmapinfo( dst_info
, src_info
);
567 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
568 if (err
== ERROR_BAD_FORMAT
)
570 DWORD dst_colors
= dst_info
->bmiHeader
.biClrUsed
;
572 /* 1-bpp destination without a color table requires a fake 1-entry table
573 * that contains only the background color; except with a 1-bpp source,
574 * in which case it uses the source colors */
575 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_colors
)
577 if (src_info
->bmiHeader
.biBitCount
> 1)
579 COLORREF color
= GetBkColor( dev
->hdc
);
580 dst_info
->bmiColors
[0].rgbRed
= GetRValue( color
);
581 dst_info
->bmiColors
[0].rgbGreen
= GetGValue( color
);
582 dst_info
->bmiColors
[0].rgbBlue
= GetBValue( color
);
583 dst_info
->bmiColors
[0].rgbReserved
= 0;
584 dst_info
->bmiHeader
.biClrUsed
= 1;
588 memcpy( dst_info
->bmiColors
, src_info
->bmiColors
, 2 * sizeof(dst_info
->bmiColors
[0]) );
589 dst_info
->bmiHeader
.biClrUsed
= 2;
593 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
)))
595 /* get rid of the fake 1-bpp table */
596 dst_info
->bmiHeader
.biClrUsed
= dst_colors
;
597 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
601 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
603 copy_bitmapinfo( src_info
, dst_info
);
604 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, GetStretchBltMode( dev
->hdc
) );
605 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
610 if (src_bits
.free
) src_bits
.free( &src_bits
);
611 if (clip
) DeleteObject( clip
);
615 /***********************************************************************
616 * StretchDIBits (GDI32.@)
618 INT WINAPI DECLSPEC_HOTPATCH
StretchDIBits( HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
619 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
620 const void *bits
, const BITMAPINFO
*bmi
, UINT coloruse
,
623 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
624 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
630 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
632 SetLastError( ERROR_INVALID_PARAMETER
);
636 if ((dc
= get_dc_ptr( hdc
)))
639 physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
640 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
641 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
642 release_dc_ptr( dc
);
648 /******************************************************************************
649 * SetDIBits [GDI32.@]
651 * Sets pixels in a bitmap using colors from DIB.
654 * hdc [I] Handle to device context
655 * hbitmap [I] Handle to bitmap
656 * startscan [I] Starting scan line
657 * lines [I] Number of scan lines
658 * bits [I] Array of bitmap bits
659 * info [I] Address of structure with data
660 * coloruse [I] Type of color indexes to use
663 * Success: Number of scan lines copied
666 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
667 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
671 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
672 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
673 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
674 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
677 struct gdi_image_bits src_bits
;
678 struct bitblt_coords src
, dst
;
679 INT src_to_dst_offset
;
682 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
) || coloruse
> DIB_PAL_COLORS
)
684 SetLastError( ERROR_INVALID_PARAMETER
);
687 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
689 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
690 if (!masks
[0] || !masks
[1] || !masks
[2])
692 SetLastError( ERROR_INVALID_PARAMETER
);
697 src_bits
.ptr
= (void *)bits
;
698 src_bits
.is_copy
= FALSE
;
699 src_bits
.free
= NULL
;
700 src_bits
.param
= NULL
;
702 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
704 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
706 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
708 if (lines
== 0) goto done
;
709 else lines
= src_info
->bmiHeader
.biHeight
;
712 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
715 dst
.visrect
.left
= 0;
717 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
718 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
720 src
.visrect
.left
= 0;
722 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
723 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
725 if (src_info
->bmiHeader
.biHeight
> 0)
727 src_to_dst_offset
= -startscan
;
728 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
729 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
733 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
734 /* Unlike the bottom-up case, Windows doesn't limit lines. */
735 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
740 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
741 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
742 src
.visrect
= dst
.visrect
;
743 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
745 src
.x
= src
.visrect
.left
;
746 src
.y
= src
.visrect
.top
;
747 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
748 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
750 dst
.x
= dst
.visrect
.left
;
751 dst
.y
= dst
.visrect
.top
;
752 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
753 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
755 copy_bitmapinfo( dst_info
, src_info
);
757 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
758 if (err
== ERROR_BAD_FORMAT
)
760 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
761 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
766 if (src_bits
.free
) src_bits
.free( &src_bits
);
767 if (clip
) DeleteObject( clip
);
768 GDI_ReleaseObj( hbitmap
);
773 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
774 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
775 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
777 DC
*dc
= get_nulldrv_dc( dev
);
778 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
779 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
780 struct bitblt_coords src
, dst
;
781 struct gdi_image_bits src_bits
;
789 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
790 height
= abs( src_info
->bmiHeader
.biHeight
);
792 src_bits
.ptr
= (void *)bits
;
793 src_bits
.is_copy
= FALSE
;
794 src_bits
.free
= NULL
;
796 if (!lines
) return 0;
797 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
799 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
803 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
804 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
805 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
810 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
814 if (startscan
>= height
) return 0;
815 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
817 /* map src to top-down coordinates with startscan as origin */
819 src
.y
= startscan
+ lines
- (y_src
+ cy
);
826 /* get rid of unnecessary lines */
827 if (src
.y
>= lines
) return 0;
831 else if (src
.y
>= lines
) return lines
;
833 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
836 src
.visrect
.left
= src
.x
;
837 src
.visrect
.top
= src
.y
;
838 src
.visrect
.right
= src
.x
+ cx
;
839 src
.visrect
.bottom
= src
.y
+ cy
;
842 rect
.right
= src_info
->bmiHeader
.biWidth
;
843 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
844 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
852 LPtoDP( dev
->hdc
, &pt
, 1 );
857 if (GetLayout( dev
->hdc
) & LAYOUT_RTL
) dst
.x
-= cx
- 1;
861 rect
.right
= dst
.x
+ cx
;
862 rect
.bottom
= dst
.y
+ cy
;
863 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
865 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
866 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
867 src
.visrect
= dst
.visrect
= rect
;
868 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
869 if (is_rect_empty( &dst
.visrect
)) goto done
;
870 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
872 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
873 copy_bitmapinfo( dst_info
, src_info
);
874 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
875 if (err
== ERROR_BAD_FORMAT
)
877 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
878 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
883 if (src_bits
.free
) src_bits
.free( &src_bits
);
884 if (clip
) DeleteObject( clip
);
888 /***********************************************************************
889 * SetDIBitsToDevice (GDI32.@)
891 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
892 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
893 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
896 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
897 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
903 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
905 SetLastError( ERROR_INVALID_PARAMETER
);
909 if ((dc
= get_dc_ptr( hdc
)))
912 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
913 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
914 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
915 release_dc_ptr( dc
);
920 /***********************************************************************
921 * SetDIBColorTable (GDI32.@)
923 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
929 if (!(dc
= get_dc_ptr( hdc
))) return 0;
931 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
933 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
935 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
936 memcpy(bitmap
->color_table
+ startpos
, colors
, result
* sizeof(RGBQUAD
));
938 GDI_ReleaseObj( dc
->hBitmap
);
940 if (result
) /* update colors of selected objects */
942 SetTextColor( hdc
, dc
->textColor
);
943 SetBkColor( hdc
, dc
->backgroundColor
);
944 SelectObject( hdc
, dc
->hPen
);
945 SelectObject( hdc
, dc
->hBrush
);
948 release_dc_ptr( dc
);
953 /***********************************************************************
954 * GetDIBColorTable (GDI32.@)
956 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
962 if (!(dc
= get_dc_ptr( hdc
))) return 0;
964 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
966 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
968 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
969 memcpy(colors
, bitmap
->color_table
+ startpos
, result
* sizeof(RGBQUAD
));
971 GDI_ReleaseObj( dc
->hBitmap
);
973 release_dc_ptr( dc
);
977 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
978 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
980 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
982 BITMAPINFOHEADER header
;
984 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
985 header
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
986 header
.biHeight
= bmp
->dib
.dsBm
.bmHeight
;
988 header
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
990 switch (header
.biBitCount
)
994 header
.biCompression
= BI_BITFIELDS
;
997 header
.biCompression
= BI_RGB
;
1001 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
1002 header
.biXPelsPerMeter
= 0;
1003 header
.biYPelsPerMeter
= 0;
1004 header
.biClrUsed
= 0;
1005 header
.biClrImportant
= 0;
1007 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
1009 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
1011 coreheader
->bcWidth
= header
.biWidth
;
1012 coreheader
->bcHeight
= header
.biHeight
;
1013 coreheader
->bcPlanes
= header
.biPlanes
;
1014 coreheader
->bcBitCount
= header
.biBitCount
;
1017 info
->bmiHeader
= header
;
1019 return bmp
->dib
.dsBm
.bmHeight
;
1022 /************************************************************************
1025 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1027 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1029 assert( src
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
) );
1031 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1033 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1034 if (coloruse
== DIB_PAL_COLORS
)
1035 memcpy( core
->bmciColors
, src
->bmiColors
, src
->bmiHeader
.biClrUsed
* sizeof(WORD
) );
1039 for (i
= 0; i
< src
->bmiHeader
.biClrUsed
; i
++)
1041 core
->bmciColors
[i
].rgbtRed
= src
->bmiColors
[i
].rgbRed
;
1042 core
->bmciColors
[i
].rgbtGreen
= src
->bmiColors
[i
].rgbGreen
;
1043 core
->bmciColors
[i
].rgbtBlue
= src
->bmiColors
[i
].rgbBlue
;
1049 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1050 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
1052 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1053 /* bitfields are always at bmiColors even in larger structures */
1054 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1055 else if (src
->bmiHeader
.biClrUsed
)
1057 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1060 if (coloruse
== DIB_PAL_COLORS
)
1061 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1063 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1064 memcpy( colorptr
, src
->bmiColors
, size
);
1069 const RGBQUAD
*get_default_color_table( int bpp
)
1071 static const RGBQUAD table_1
[2] =
1073 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1075 static const RGBQUAD table_4
[16] =
1077 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1078 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1079 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1080 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1082 static const RGBQUAD table_8
[256] =
1084 /* first and last 10 entries are the default system palette entries */
1085 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1086 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1087 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1088 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1089 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1090 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1091 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1092 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1093 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1094 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1095 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1096 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1097 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1098 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1099 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1100 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1101 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1102 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1103 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1104 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1105 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1106 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1107 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1108 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1109 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1110 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1111 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1112 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1113 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1114 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1115 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1116 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1117 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1118 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1119 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1120 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1121 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1122 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1123 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1124 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1125 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1126 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1127 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1128 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1129 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1130 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1131 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1132 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1133 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1134 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1135 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1136 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1137 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1138 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1139 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1140 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1141 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1142 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1143 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1144 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1145 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1146 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1147 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1148 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1153 case 1: return table_1
;
1154 case 4: return table_4
;
1155 case 8: return table_8
;
1156 default: return NULL
;
1160 void fill_default_color_table( BITMAPINFO
*info
)
1162 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1163 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1164 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1167 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1169 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1170 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1171 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1172 info
->bmiHeader
.biPlanes
= 1;
1173 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1174 info
->bmiHeader
.biCompression
= BI_RGB
;
1175 info
->bmiHeader
.biXPelsPerMeter
= 0;
1176 info
->bmiHeader
.biYPelsPerMeter
= 0;
1177 info
->bmiHeader
.biClrUsed
= 0;
1178 info
->bmiHeader
.biClrImportant
= 0;
1181 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1183 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1184 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1185 unsigned int info_size
;
1187 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1189 info_size
= get_dib_info_size( info
, usage
);
1190 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ info
->bmiHeader
.biSizeImage
)))
1192 memcpy( ret
, info
, info_size
);
1193 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size( src_info
, usage
),
1194 info
->bmiHeader
.biSizeImage
);
1199 /******************************************************************************
1200 * GetDIBits [GDI32.@]
1202 * Retrieves bits of bitmap and copies to buffer.
1205 * Success: Number of scan lines copied from bitmap
1208 INT WINAPI
GetDIBits(
1209 HDC hdc
, /* [in] Handle to device context */
1210 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1211 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1212 UINT lines
, /* [in] Number of scan lines to copy */
1213 LPVOID bits
, /* [out] Address of array for bitmap bits */
1214 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1215 UINT coloruse
) /* [in] RGB or palette index */
1219 int i
, dst_to_src_offset
, ret
= 0;
1221 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1222 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1223 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1224 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1225 struct gdi_image_bits src_bits
;
1226 struct bitblt_coords src
, dst
;
1227 BOOL empty_rect
= FALSE
;
1229 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1230 own copy and transfer the colour info back at the end */
1231 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1232 if (coloruse
> DIB_PAL_COLORS
) return 0;
1234 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1236 dst_info
->bmiHeader
.biClrUsed
= 0;
1237 dst_info
->bmiHeader
.biClrImportant
= 0;
1239 if (!(dc
= get_dc_ptr( hdc
)))
1241 SetLastError( ERROR_INVALID_PARAMETER
);
1245 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1247 release_dc_ptr( dc
);
1251 src
.visrect
.left
= 0;
1252 src
.visrect
.top
= 0;
1253 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1254 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1256 dst
.visrect
.left
= 0;
1257 dst
.visrect
.top
= 0;
1258 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1259 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1261 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1264 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1266 ret
= fill_query_info( info
, bmp
);
1270 /* validate parameters */
1272 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1273 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1275 switch (dst_info
->bmiHeader
.biCompression
)
1278 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1279 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1280 if (bits
) goto done
; /* can't retrieve compressed bits */
1283 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1284 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1285 if (bits
) goto done
; /* can't retrieve compressed bits */
1288 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1291 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1292 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1293 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1294 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1295 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1296 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1297 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1305 if (dst_info
->bmiHeader
.biHeight
> 0)
1307 dst_to_src_offset
= -startscan
;
1308 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1309 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1313 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1314 if (dst_to_src_offset
< 0)
1316 dst_to_src_offset
= 0;
1317 lines
= dst
.visrect
.bottom
- startscan
;
1319 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1322 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1323 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1324 dst
.visrect
= src
.visrect
;
1325 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1327 if (dst_info
->bmiHeader
.biHeight
> 0)
1329 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1331 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1332 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1333 memset( bits
, 0, pad_bytes
);
1334 bits
= (char *)bits
+ pad_bytes
;
1339 if (dst
.visrect
.bottom
< lines
)
1341 int pad_lines
= lines
- dst
.visrect
.bottom
;
1342 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1343 int pad_bytes
= pad_lines
* stride
;
1344 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1348 if (empty_rect
) bits
= NULL
;
1350 src
.x
= src
.visrect
.left
;
1351 src
.y
= src
.visrect
.top
;
1352 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1353 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1358 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1362 /* fill out the src colour table, if it needs one */
1363 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1364 fill_default_color_table( src_info
);
1366 /* if the src and dst are the same depth, copy the colour info across */
1367 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1369 switch (src_info
->bmiHeader
.biBitCount
)
1372 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1374 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1375 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1379 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1381 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1382 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1386 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1387 copy_color_info( dst_info
, src_info
, coloruse
);
1389 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1391 if( coloruse
== DIB_PAL_COLORS
)
1393 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1397 fill_default_color_table( dst_info
);
1403 if(dst_info
->bmiHeader
.biHeight
> 0)
1404 dst_info
->bmiHeader
.biHeight
= src
.height
;
1406 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1408 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1409 if (src_bits
.free
) src_bits
.free( &src_bits
);
1415 if (coloruse
== DIB_PAL_COLORS
)
1417 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1418 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1422 copy_color_info( info
, dst_info
, coloruse
);
1423 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
)) info
->bmiHeader
.biClrUsed
= 0;
1426 release_dc_ptr( dc
);
1427 GDI_ReleaseObj( hbitmap
);
1432 /***********************************************************************
1433 * CreateDIBitmap (GDI32.@)
1435 * Creates a DDB (device dependent bitmap) from a DIB.
1436 * The DDB will have the same color depth as the reference DC.
1438 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1439 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1442 BITMAPINFOHEADER info
;
1446 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1447 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1448 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1449 if (info
.biWidth
< 0) return 0;
1451 /* Top-down DIBs have a negative height */
1452 height
= abs( info
.biHeight
);
1454 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1455 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1456 info
.biBitCount
, info
.biCompression
);
1459 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1461 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1465 if (init
& CBM_INIT
)
1467 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1469 DeleteObject( handle
);
1479 /***********************************************************************
1480 * CreateDIBSection (GDI32.@)
1482 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
1483 VOID
**bits
, HANDLE section
, DWORD offset
)
1485 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1486 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1489 void *mapBits
= NULL
;
1491 if (bits
) *bits
= NULL
;
1492 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1493 if (usage
> DIB_PAL_COLORS
) return 0;
1494 if (info
->bmiHeader
.biPlanes
!= 1)
1496 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1497 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1500 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1502 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1503 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1504 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1505 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1506 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1508 bmp
->dib
.dsBm
.bmType
= 0;
1509 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1510 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1511 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1512 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1513 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1514 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1516 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1518 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1520 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1521 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1522 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1524 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1527 /* set dsBitfields values */
1528 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1530 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1531 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1532 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1533 bmp
->dib
.dsBitfields
[2] = 0x001f;
1535 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1537 if (usage
== DIB_PAL_COLORS
) goto error
;
1538 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1539 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1540 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1541 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1543 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1545 /* get storage location for DIB bits */
1549 SYSTEM_INFO SystemInfo
;
1553 GetSystemInfo( &SystemInfo
);
1554 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1555 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1556 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1557 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1562 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1563 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1565 bmp
->dib
.dshSection
= section
;
1566 bmp
->dib
.dsOffset
= offset
;
1568 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1570 if (!(ret
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1572 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1576 if (section
) UnmapViewOfFile( mapBits
);
1577 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1578 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1579 HeapFree( GetProcessHeap(), 0, bmp
);
1584 /***********************************************************************
1587 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
)
1594 if (!(dc
= get_dc_ptr( hdc
))) return 0;
1596 if (GetObjectType( hdc
) != OBJ_MEMDC
)
1602 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
1604 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
1610 if (GDI_get_ref_count( handle
))
1612 WARN( "Bitmap already selected in another DC\n" );
1613 GDI_ReleaseObj( handle
);
1618 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
1619 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
1621 GDI_ReleaseObj( handle
);
1626 dc
->hBitmap
= handle
;
1627 GDI_inc_ref_count( handle
);
1629 dc
->vis_rect
.left
= 0;
1630 dc
->vis_rect
.top
= 0;
1631 dc
->vis_rect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
1632 dc
->vis_rect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
1633 dc
->device_rect
= dc
->vis_rect
;
1634 GDI_ReleaseObj( handle
);
1636 GDI_dec_ref_count( ret
);
1640 release_dc_ptr( dc
);
1645 /***********************************************************************
1648 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1651 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
1655 if (!buffer
) ret
= sizeof(BITMAP
);
1656 else if (count
>= sizeof(DIBSECTION
))
1658 DIBSECTION
*dib
= buffer
;
1660 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1661 ret
= sizeof(DIBSECTION
);
1663 else if (count
>= sizeof(BITMAP
))
1665 BITMAP
*bitmap
= buffer
;
1666 *bitmap
= bmp
->dib
.dsBm
;
1667 ret
= sizeof(BITMAP
);
1670 GDI_ReleaseObj( handle
);
1675 /***********************************************************************
1678 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1682 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1684 if (bmp
->dib
.dshSection
)
1686 SYSTEM_INFO SystemInfo
;
1687 GetSystemInfo( &SystemInfo
);
1688 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1689 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1691 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1693 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1694 return HeapFree( GetProcessHeap(), 0, bmp
);