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 /* 1-bpp destination without a color table requires a fake 1-entry table
571 * that contains only the background color */
572 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_info
->bmiHeader
.biClrUsed
)
574 COLORREF color
= GetBkColor( dev
->hdc
);
575 dst_info
->bmiColors
[0].rgbRed
= GetRValue( color
);
576 dst_info
->bmiColors
[0].rgbGreen
= GetGValue( color
);
577 dst_info
->bmiColors
[0].rgbBlue
= GetBValue( color
);
578 dst_info
->bmiColors
[0].rgbReserved
= 0;
579 dst_info
->bmiHeader
.biClrUsed
= 1;
582 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
)))
584 /* get rid of the fake 1-bpp table */
585 if (dst_info
->bmiHeader
.biClrUsed
== 1) dst_info
->bmiHeader
.biClrUsed
= 0;
586 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
590 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
592 copy_bitmapinfo( src_info
, dst_info
);
593 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, GetStretchBltMode( dev
->hdc
) );
594 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
599 if (src_bits
.free
) src_bits
.free( &src_bits
);
600 if (clip
) DeleteObject( clip
);
604 /***********************************************************************
605 * StretchDIBits (GDI32.@)
607 INT WINAPI DECLSPEC_HOTPATCH
StretchDIBits( HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
608 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
609 const void *bits
, const BITMAPINFO
*bmi
, UINT coloruse
,
612 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
613 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
619 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
621 SetLastError( ERROR_INVALID_PARAMETER
);
625 if ((dc
= get_dc_ptr( hdc
)))
628 physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
629 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
630 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
631 release_dc_ptr( dc
);
637 /******************************************************************************
638 * SetDIBits [GDI32.@]
640 * Sets pixels in a bitmap using colors from DIB.
643 * hdc [I] Handle to device context
644 * hbitmap [I] Handle to bitmap
645 * startscan [I] Starting scan line
646 * lines [I] Number of scan lines
647 * bits [I] Array of bitmap bits
648 * info [I] Address of structure with data
649 * coloruse [I] Type of color indexes to use
652 * Success: Number of scan lines copied
655 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
656 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
660 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
661 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
662 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
663 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
666 struct gdi_image_bits src_bits
;
667 struct bitblt_coords src
, dst
;
668 INT src_to_dst_offset
;
671 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
) || coloruse
> DIB_PAL_COLORS
)
673 SetLastError( ERROR_INVALID_PARAMETER
);
676 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
678 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
679 if (!masks
[0] || !masks
[1] || !masks
[2])
681 SetLastError( ERROR_INVALID_PARAMETER
);
686 src_bits
.ptr
= (void *)bits
;
687 src_bits
.is_copy
= FALSE
;
688 src_bits
.free
= NULL
;
689 src_bits
.param
= NULL
;
691 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
693 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
695 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
697 if (lines
== 0) goto done
;
698 else lines
= src_info
->bmiHeader
.biHeight
;
701 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
704 dst
.visrect
.left
= 0;
706 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
707 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
709 src
.visrect
.left
= 0;
711 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
712 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
714 if (src_info
->bmiHeader
.biHeight
> 0)
716 src_to_dst_offset
= -startscan
;
717 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
718 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
722 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
723 /* Unlike the bottom-up case, Windows doesn't limit lines. */
724 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
729 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
730 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
731 src
.visrect
= dst
.visrect
;
732 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
734 src
.x
= src
.visrect
.left
;
735 src
.y
= src
.visrect
.top
;
736 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
737 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
739 dst
.x
= dst
.visrect
.left
;
740 dst
.y
= dst
.visrect
.top
;
741 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
742 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
744 copy_bitmapinfo( dst_info
, src_info
);
746 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
747 if (err
== ERROR_BAD_FORMAT
)
749 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
750 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
755 if (src_bits
.free
) src_bits
.free( &src_bits
);
756 if (clip
) DeleteObject( clip
);
757 GDI_ReleaseObj( hbitmap
);
762 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
763 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
764 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
766 DC
*dc
= get_nulldrv_dc( dev
);
767 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
768 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
769 struct bitblt_coords src
, dst
;
770 struct gdi_image_bits src_bits
;
778 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
779 height
= abs( src_info
->bmiHeader
.biHeight
);
781 src_bits
.ptr
= (void *)bits
;
782 src_bits
.is_copy
= FALSE
;
783 src_bits
.free
= NULL
;
785 if (!lines
) return 0;
786 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
788 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
792 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
793 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
794 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
799 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
803 if (startscan
>= height
) return 0;
804 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
806 /* map src to top-down coordinates with startscan as origin */
808 src
.y
= startscan
+ lines
- (y_src
+ cy
);
815 /* get rid of unnecessary lines */
816 if (src
.y
>= lines
) return 0;
820 else if (src
.y
>= lines
) return lines
;
822 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
825 src
.visrect
.left
= src
.x
;
826 src
.visrect
.top
= src
.y
;
827 src
.visrect
.right
= src
.x
+ cx
;
828 src
.visrect
.bottom
= src
.y
+ cy
;
831 rect
.right
= src_info
->bmiHeader
.biWidth
;
832 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
833 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
841 LPtoDP( dev
->hdc
, &pt
, 1 );
846 if (GetLayout( dev
->hdc
) & LAYOUT_RTL
) dst
.x
-= cx
- 1;
850 rect
.right
= dst
.x
+ cx
;
851 rect
.bottom
= dst
.y
+ cy
;
852 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
854 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
855 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
856 src
.visrect
= dst
.visrect
= rect
;
857 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
858 if (is_rect_empty( &dst
.visrect
)) goto done
;
859 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
861 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
862 copy_bitmapinfo( dst_info
, src_info
);
863 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
864 if (err
== ERROR_BAD_FORMAT
)
866 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
);
867 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
872 if (src_bits
.free
) src_bits
.free( &src_bits
);
873 if (clip
) DeleteObject( clip
);
877 /***********************************************************************
878 * SetDIBitsToDevice (GDI32.@)
880 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
881 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
882 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
885 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
886 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
892 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
894 SetLastError( ERROR_INVALID_PARAMETER
);
898 if ((dc
= get_dc_ptr( hdc
)))
901 physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
902 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
903 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
904 release_dc_ptr( dc
);
909 /***********************************************************************
910 * SetDIBColorTable (GDI32.@)
912 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, const RGBQUAD
*colors
)
918 if (!(dc
= get_dc_ptr( hdc
))) return 0;
920 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
922 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
924 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
925 memcpy(bitmap
->color_table
+ startpos
, colors
, result
* sizeof(RGBQUAD
));
927 GDI_ReleaseObj( dc
->hBitmap
);
929 if (result
) /* update colors of selected objects */
931 SetTextColor( hdc
, dc
->textColor
);
932 SetBkColor( hdc
, dc
->backgroundColor
);
933 SelectObject( hdc
, dc
->hPen
);
934 SelectObject( hdc
, dc
->hBrush
);
937 release_dc_ptr( dc
);
942 /***********************************************************************
943 * GetDIBColorTable (GDI32.@)
945 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
951 if (!(dc
= get_dc_ptr( hdc
))) return 0;
953 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
955 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
957 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
958 memcpy(colors
, bitmap
->color_table
+ startpos
, result
* sizeof(RGBQUAD
));
960 GDI_ReleaseObj( dc
->hBitmap
);
962 release_dc_ptr( dc
);
966 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
967 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
969 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
971 BITMAPINFOHEADER header
;
973 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
974 header
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
975 header
.biHeight
= bmp
->dib
.dsBm
.bmHeight
;
977 header
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
979 switch (header
.biBitCount
)
983 header
.biCompression
= BI_BITFIELDS
;
986 header
.biCompression
= BI_RGB
;
990 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
991 header
.biXPelsPerMeter
= 0;
992 header
.biYPelsPerMeter
= 0;
993 header
.biClrUsed
= 0;
994 header
.biClrImportant
= 0;
996 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
998 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
1000 coreheader
->bcWidth
= header
.biWidth
;
1001 coreheader
->bcHeight
= header
.biHeight
;
1002 coreheader
->bcPlanes
= header
.biPlanes
;
1003 coreheader
->bcBitCount
= header
.biBitCount
;
1006 info
->bmiHeader
= header
;
1008 return bmp
->dib
.dsBm
.bmHeight
;
1011 /************************************************************************
1014 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1016 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1018 assert( src
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
) );
1020 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1022 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1023 if (coloruse
== DIB_PAL_COLORS
)
1024 memcpy( core
->bmciColors
, src
->bmiColors
, src
->bmiHeader
.biClrUsed
* sizeof(WORD
) );
1028 for (i
= 0; i
< src
->bmiHeader
.biClrUsed
; i
++)
1030 core
->bmciColors
[i
].rgbtRed
= src
->bmiColors
[i
].rgbRed
;
1031 core
->bmciColors
[i
].rgbtGreen
= src
->bmiColors
[i
].rgbGreen
;
1032 core
->bmciColors
[i
].rgbtBlue
= src
->bmiColors
[i
].rgbBlue
;
1038 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1039 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
1041 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1042 /* bitfields are always at bmiColors even in larger structures */
1043 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1044 else if (src
->bmiHeader
.biClrUsed
)
1046 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1049 if (coloruse
== DIB_PAL_COLORS
)
1050 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1052 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1053 memcpy( colorptr
, src
->bmiColors
, size
);
1058 const RGBQUAD
*get_default_color_table( int bpp
)
1060 static const RGBQUAD table_1
[2] =
1062 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1064 static const RGBQUAD table_4
[16] =
1066 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1067 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1068 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1069 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1071 static const RGBQUAD table_8
[256] =
1073 /* first and last 10 entries are the default system palette entries */
1074 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1075 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1076 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1077 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1078 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1079 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1080 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1081 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1082 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1083 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1084 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1085 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1086 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1087 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1088 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1089 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1090 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1091 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1092 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1093 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1094 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1095 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1096 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1097 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1098 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1099 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1100 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1101 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1102 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1103 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1104 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1105 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1106 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1107 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1108 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1109 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1110 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1111 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1112 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1113 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1114 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1115 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1116 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1117 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1118 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1119 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1120 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1121 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1122 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1123 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1124 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1125 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1126 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1127 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1128 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1129 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1130 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1131 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1132 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1133 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1134 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1135 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1136 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1137 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1142 case 1: return table_1
;
1143 case 4: return table_4
;
1144 case 8: return table_8
;
1145 default: return NULL
;
1149 void fill_default_color_table( BITMAPINFO
*info
)
1151 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1152 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1153 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1156 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1158 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1159 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1160 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1161 info
->bmiHeader
.biPlanes
= 1;
1162 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1163 info
->bmiHeader
.biCompression
= BI_RGB
;
1164 info
->bmiHeader
.biXPelsPerMeter
= 0;
1165 info
->bmiHeader
.biYPelsPerMeter
= 0;
1166 info
->bmiHeader
.biClrUsed
= 0;
1167 info
->bmiHeader
.biClrImportant
= 0;
1170 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1172 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1173 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1174 unsigned int info_size
;
1176 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1178 info_size
= get_dib_info_size( info
, usage
);
1179 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ info
->bmiHeader
.biSizeImage
)))
1181 memcpy( ret
, info
, info_size
);
1182 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size( src_info
, usage
),
1183 info
->bmiHeader
.biSizeImage
);
1188 /******************************************************************************
1189 * GetDIBits [GDI32.@]
1191 * Retrieves bits of bitmap and copies to buffer.
1194 * Success: Number of scan lines copied from bitmap
1197 INT WINAPI
GetDIBits(
1198 HDC hdc
, /* [in] Handle to device context */
1199 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1200 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1201 UINT lines
, /* [in] Number of scan lines to copy */
1202 LPVOID bits
, /* [out] Address of array for bitmap bits */
1203 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1204 UINT coloruse
) /* [in] RGB or palette index */
1208 int i
, dst_to_src_offset
, ret
= 0;
1210 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1211 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1212 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1213 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1214 struct gdi_image_bits src_bits
;
1215 struct bitblt_coords src
, dst
;
1216 BOOL empty_rect
= FALSE
;
1218 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1219 own copy and transfer the colour info back at the end */
1220 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1221 if (coloruse
> DIB_PAL_COLORS
) return 0;
1223 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1225 dst_info
->bmiHeader
.biClrUsed
= 0;
1226 dst_info
->bmiHeader
.biClrImportant
= 0;
1228 if (!(dc
= get_dc_ptr( hdc
)))
1230 SetLastError( ERROR_INVALID_PARAMETER
);
1234 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1236 release_dc_ptr( dc
);
1240 src
.visrect
.left
= 0;
1241 src
.visrect
.top
= 0;
1242 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1243 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1245 dst
.visrect
.left
= 0;
1246 dst
.visrect
.top
= 0;
1247 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1248 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1250 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1253 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1255 ret
= fill_query_info( info
, bmp
);
1259 /* validate parameters */
1261 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1262 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1264 switch (dst_info
->bmiHeader
.biCompression
)
1267 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1268 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1269 if (bits
) goto done
; /* can't retrieve compressed bits */
1272 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1273 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1274 if (bits
) goto done
; /* can't retrieve compressed bits */
1277 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1280 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1281 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1282 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1283 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1284 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1285 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1286 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1294 if (dst_info
->bmiHeader
.biHeight
> 0)
1296 dst_to_src_offset
= -startscan
;
1297 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1298 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1302 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1303 if (dst_to_src_offset
< 0)
1305 dst_to_src_offset
= 0;
1306 lines
= dst
.visrect
.bottom
- startscan
;
1308 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1311 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1312 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1313 dst
.visrect
= src
.visrect
;
1314 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1316 if (dst_info
->bmiHeader
.biHeight
> 0)
1318 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1320 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1321 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1322 memset( bits
, 0, pad_bytes
);
1323 bits
= (char *)bits
+ pad_bytes
;
1328 if (dst
.visrect
.bottom
< lines
)
1330 int pad_lines
= lines
- dst
.visrect
.bottom
;
1331 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1332 int pad_bytes
= pad_lines
* stride
;
1333 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1337 if (empty_rect
) bits
= NULL
;
1339 src
.x
= src
.visrect
.left
;
1340 src
.y
= src
.visrect
.top
;
1341 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1342 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1347 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1351 /* fill out the src colour table, if it needs one */
1352 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1353 fill_default_color_table( src_info
);
1355 /* if the src and dst are the same depth, copy the colour info across */
1356 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1358 switch (src_info
->bmiHeader
.biBitCount
)
1361 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1363 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1364 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1368 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1370 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1371 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1375 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1376 copy_color_info( dst_info
, src_info
, coloruse
);
1378 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1380 if( coloruse
== DIB_PAL_COLORS
)
1382 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1386 fill_default_color_table( dst_info
);
1392 if(dst_info
->bmiHeader
.biHeight
> 0)
1393 dst_info
->bmiHeader
.biHeight
= src
.height
;
1395 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1397 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1398 if (src_bits
.free
) src_bits
.free( &src_bits
);
1404 if (coloruse
== DIB_PAL_COLORS
)
1406 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1407 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1411 copy_color_info( info
, dst_info
, coloruse
);
1412 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
)) info
->bmiHeader
.biClrUsed
= 0;
1415 release_dc_ptr( dc
);
1416 GDI_ReleaseObj( hbitmap
);
1421 /***********************************************************************
1422 * CreateDIBitmap (GDI32.@)
1424 * Creates a DDB (device dependent bitmap) from a DIB.
1425 * The DDB will have the same color depth as the reference DC.
1427 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1428 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1431 BITMAPINFOHEADER info
;
1435 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1436 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1437 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1438 if (info
.biWidth
< 0) return 0;
1440 /* Top-down DIBs have a negative height */
1441 height
= abs( info
.biHeight
);
1443 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1444 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1445 info
.biBitCount
, info
.biCompression
);
1448 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1450 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1454 if (init
& CBM_INIT
)
1456 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1458 DeleteObject( handle
);
1468 /***********************************************************************
1469 * CreateDIBSection (GDI32.@)
1471 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, const BITMAPINFO
*bmi
, UINT usage
,
1472 VOID
**bits
, HANDLE section
, DWORD offset
)
1474 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1475 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1478 void *mapBits
= NULL
;
1480 if (bits
) *bits
= NULL
;
1481 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1482 if (usage
> DIB_PAL_COLORS
) return 0;
1483 if (info
->bmiHeader
.biPlanes
!= 1)
1485 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1486 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1489 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1491 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1492 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1493 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1494 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1495 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1497 bmp
->dib
.dsBm
.bmType
= 0;
1498 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1499 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1500 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1501 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1502 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1503 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1505 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1507 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1509 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1510 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1511 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1513 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1516 /* set dsBitfields values */
1517 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1519 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1520 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1521 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1522 bmp
->dib
.dsBitfields
[2] = 0x001f;
1524 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1526 if (usage
== DIB_PAL_COLORS
) goto error
;
1527 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1528 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1529 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1530 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1532 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1534 /* get storage location for DIB bits */
1538 SYSTEM_INFO SystemInfo
;
1542 GetSystemInfo( &SystemInfo
);
1543 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1544 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1545 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1546 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1551 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1552 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1554 bmp
->dib
.dshSection
= section
;
1555 bmp
->dib
.dsOffset
= offset
;
1557 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1559 if (!(ret
= alloc_gdi_handle( bmp
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1561 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1565 if (section
) UnmapViewOfFile( mapBits
);
1566 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1567 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1568 HeapFree( GetProcessHeap(), 0, bmp
);
1573 /***********************************************************************
1576 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
)
1583 if (!(dc
= get_dc_ptr( hdc
))) return 0;
1585 if (GetObjectType( hdc
) != OBJ_MEMDC
)
1591 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
1593 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
1599 if (GDI_get_ref_count( handle
))
1601 WARN( "Bitmap already selected in another DC\n" );
1602 GDI_ReleaseObj( handle
);
1607 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
1608 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
1610 GDI_ReleaseObj( handle
);
1615 dc
->hBitmap
= handle
;
1616 GDI_inc_ref_count( handle
);
1618 dc
->vis_rect
.left
= 0;
1619 dc
->vis_rect
.top
= 0;
1620 dc
->vis_rect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
1621 dc
->vis_rect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
1622 dc
->device_rect
= dc
->vis_rect
;
1623 GDI_ReleaseObj( handle
);
1625 GDI_dec_ref_count( ret
);
1629 release_dc_ptr( dc
);
1634 /***********************************************************************
1637 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1640 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
1644 if (!buffer
) ret
= sizeof(BITMAP
);
1645 else if (count
>= sizeof(DIBSECTION
))
1647 DIBSECTION
*dib
= buffer
;
1649 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1650 ret
= sizeof(DIBSECTION
);
1652 else if (count
>= sizeof(BITMAP
))
1654 BITMAP
*bitmap
= buffer
;
1655 *bitmap
= bmp
->dib
.dsBm
;
1656 ret
= sizeof(BITMAP
);
1659 GDI_ReleaseObj( handle
);
1664 /***********************************************************************
1667 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1671 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1673 if (bmp
->dib
.dshSection
)
1675 SYSTEM_INFO SystemInfo
;
1676 GetSystemInfo( &SystemInfo
);
1677 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1678 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1680 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1682 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1683 return HeapFree( GetProcessHeap(), 0, bmp
);