2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize).
34 * The palettes are stored in different formats:
36 - BITMAPCOREINFO: Array of RGBTRIPLE
37 - BITMAPINFO: Array of RGBQUAD
40 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
43 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45 If biCompression is BI_BITFIELDS, the color masks are at the same position
46 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
47 the new headers have structure members for the masks.
50 * You should never access the color table using the bmiColors member,
51 because the passed structure may have one of the extended headers
52 mentioned above. Use this to calculate the location:
55 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 Search for "Bitmap Structures" in MSDN
69 #include "gdi_private.h"
70 #include "wine/debug.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
75 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
);
76 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
77 static BOOL
DIB_DeleteObject( HGDIOBJ handle
);
79 static const struct gdi_obj_funcs dib_funcs
=
81 DIB_SelectObject
, /* pSelectObject */
82 DIB_GetObject
, /* pGetObjectA */
83 DIB_GetObject
, /* pGetObjectW */
84 NULL
, /* pUnrealizeObject */
85 DIB_DeleteObject
/* pDeleteObject */
88 /***********************************************************************
91 * Return the size of the bitmap info structure including color table.
93 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
95 unsigned int colors
, size
, masks
= 0;
97 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
99 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
100 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
101 return sizeof(BITMAPCOREHEADER
) + colors
*
102 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
104 else /* assume BITMAPINFOHEADER */
106 if (info
->bmiHeader
.biClrUsed
) colors
= min( info
->bmiHeader
.biClrUsed
, 256 );
107 else colors
= info
->bmiHeader
.biBitCount
> 8 ? 0 : 1 << info
->bmiHeader
.biBitCount
;
108 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
109 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
110 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
114 /*******************************************************************************************
115 * Verify that the DIB parameters are valid.
117 static BOOL
is_valid_dib_format( const BITMAPINFOHEADER
*info
, BOOL allow_compression
)
119 if (info
->biWidth
<= 0) return FALSE
;
120 if (info
->biHeight
== 0) return FALSE
;
122 if (allow_compression
&& (info
->biCompression
== BI_RLE4
|| info
->biCompression
== BI_RLE8
))
124 if (info
->biHeight
< 0) return FALSE
;
125 if (!info
->biSizeImage
) return FALSE
;
126 return info
->biBitCount
== (info
->biCompression
== BI_RLE4
? 4 : 8);
129 if (!info
->biPlanes
) return FALSE
;
131 switch (info
->biBitCount
)
137 return (info
->biCompression
== BI_RGB
);
140 return (info
->biCompression
== BI_BITFIELDS
|| info
->biCompression
== BI_RGB
);
146 /*******************************************************************************************
147 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
149 static BOOL
bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER
*dst
, const BITMAPINFOHEADER
*info
)
151 if (!info
) return FALSE
;
153 if (info
->biSize
== sizeof(BITMAPCOREHEADER
))
155 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
156 dst
->biWidth
= core
->bcWidth
;
157 dst
->biHeight
= core
->bcHeight
;
158 dst
->biPlanes
= core
->bcPlanes
;
159 dst
->biBitCount
= core
->bcBitCount
;
160 dst
->biCompression
= BI_RGB
;
161 dst
->biXPelsPerMeter
= 0;
162 dst
->biYPelsPerMeter
= 0;
164 dst
->biClrImportant
= 0;
166 else if (info
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
172 WARN( "(%u): unknown/wrong size for header\n", info
->biSize
);
176 dst
->biSize
= sizeof(*dst
);
177 if (dst
->biCompression
== BI_RGB
|| dst
->biCompression
== BI_BITFIELDS
)
178 dst
->biSizeImage
= get_dib_image_size( (BITMAPINFO
*)dst
);
182 /*******************************************************************************************
183 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
185 * The resulting sanitized BITMAPINFO is guaranteed to have:
186 * - biSize set to sizeof(BITMAPINFOHEADER)
187 * - biSizeImage set to the actual image size even for non-compressed DIB
188 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
189 * - color table present only for <= 8 bpp, always starts at info->bmiColors
191 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
,
192 UINT coloruse
, BOOL allow_compression
)
196 if (coloruse
> DIB_PAL_COLORS
+ 1) return FALSE
; /* FIXME: handle DIB_PAL_COLORS+1 format */
197 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
198 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
200 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
202 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
204 /* bitfields are always at bmiColors even in larger structures */
205 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
206 dst
->bmiHeader
.biClrUsed
= 0;
208 else if (dst
->bmiHeader
.biBitCount
<= 8)
210 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
211 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
213 if (!colors
) colors
= max_colors
;
214 else colors
= min( colors
, max_colors
);
216 if (coloruse
== DIB_PAL_COLORS
)
218 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
221 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
223 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
228 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
229 for (i
= 0; i
< colors
; i
++)
231 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
232 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
233 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
234 dst
->bmiColors
[i
].rgbReserved
= 0;
237 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
238 dst
->bmiHeader
.biClrUsed
= max_colors
;
240 else dst
->bmiHeader
.biClrUsed
= 0;
245 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
247 PALETTEENTRY palEntry
[256];
248 HPALETTE palette
= GetCurrentObject( hdc
, OBJ_PAL
);
249 int i
, colors
= 1 << info
->bmiHeader
.biBitCount
;
251 info
->bmiHeader
.biClrUsed
= colors
;
253 if (!palette
) return 0;
255 memset( palEntry
, 0, sizeof(palEntry
) );
256 if (!GetPaletteEntries( palette
, 0, colors
, palEntry
))
259 for (i
= 0; i
< colors
; i
++)
261 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
262 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
263 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
264 info
->bmiColors
[i
].rgbReserved
= 0;
270 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
272 PALETTEENTRY entries
[256];
275 const WORD
*index
= (const WORD
*)info
->bmiColors
;
276 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
278 if (!colors
) return TRUE
;
279 if (!(palette
= GetCurrentObject( hdc
, OBJ_PAL
))) return FALSE
;
280 if (!(count
= GetPaletteEntries( palette
, 0, colors
, entries
))) return FALSE
;
282 for (i
= 0; i
< colors
; i
++, index
++)
284 table
[i
].rgbRed
= entries
[*index
% count
].peRed
;
285 table
[i
].rgbGreen
= entries
[*index
% count
].peGreen
;
286 table
[i
].rgbBlue
= entries
[*index
% count
].peBlue
;
287 table
[i
].rgbReserved
= 0;
289 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
290 memcpy( info
->bmiColors
, table
, colors
* sizeof(RGBQUAD
) );
291 memset( info
->bmiColors
+ colors
, 0, (info
->bmiHeader
.biClrUsed
- colors
) * sizeof(RGBQUAD
) );
295 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
297 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
298 const int bpp
= info
->bmiHeader
.biBitCount
;
301 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
303 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
306 static BOOL
build_rle_bitmap( const BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
310 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
312 BYTE skip
, num
, data
;
313 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
315 if (clip
) *clip
= NULL
;
317 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
319 out_bits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, get_dib_image_size( info
) );
320 if (!out_bits
) goto fail
;
324 *clip
= CreateRectRgn( 0, 0, 0, 0 );
325 run
= CreateRectRgn( 0, 0, 0, 0 );
326 if (!*clip
|| !run
) goto fail
;
329 x
= left
= right
= 0;
332 while (i
< info
->bmiHeader
.biSizeImage
- 1)
335 data
= in_bits
[i
+ 1];
340 if (x
+ num
> width
) num
= width
- x
;
343 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
344 if (info
->bmiHeader
.biBitCount
== 8)
345 memset( out_ptr
, s
, num
);
350 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
351 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
356 /* this will write one too many if num is odd, but that doesn't matter */
357 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
367 if(left
!= right
&& clip
)
369 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
370 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
375 left
= right
= x
= 0;
384 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
386 if (x
> width
) x
= width
;
393 else /* data bytes of data */
396 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
397 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
398 skip
= (skip
+ 1) & ~1;
399 if (x
+ num
> width
) num
= width
- x
;
402 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
403 if (info
->bmiHeader
.biBitCount
== 8)
404 memcpy( out_ptr
, in_bits
+ i
, num
);
409 const BYTE
*in_ptr
= in_bits
+ i
;
410 for ( ; num
; num
--, x
++)
414 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
418 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
422 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
433 if (run
) DeleteObject( run
);
434 if (bits
->free
) bits
->free( bits
);
436 bits
->ptr
= out_bits
;
437 bits
->is_copy
= TRUE
;
438 bits
->free
= free_heap_bits
;
443 if (run
) DeleteObject( run
);
444 if (clip
&& *clip
) DeleteObject( *clip
);
445 HeapFree( GetProcessHeap(), 0, out_bits
);
451 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
452 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
453 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
455 DC
*dc
= get_nulldrv_dc( dev
);
456 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
457 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
458 struct bitblt_coords src
, dst
;
459 struct gdi_image_bits src_bits
;
463 INT height
= abs( src_info
->bmiHeader
.biHeight
);
464 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
467 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
468 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
470 src_bits
.ptr
= (void*)bits
;
471 src_bits
.is_copy
= FALSE
;
472 src_bits
.free
= NULL
;
474 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
478 rect
.right
= xDst
+ widthDst
;
479 rect
.bottom
= yDst
+ heightDst
;
480 LPtoDP( dc
->hSelf
, (POINT
*)&rect
, 2 );
483 dst
.width
= rect
.right
- rect
.left
;
484 dst
.height
= rect
.bottom
- rect
.top
;
486 if (dc
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
489 dst
.width
= -dst
.width
;
491 rop
&= ~NOMIRRORBITMAP
;
494 src
.width
= widthSrc
;
496 src
.height
= heightSrc
;
498 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
499 non_stretch_from_origin
= TRUE
;
501 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
503 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
504 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
507 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
509 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
510 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
515 if (dst
.width
< 0 && dst
.width
== src
.width
)
517 /* This is off-by-one, but that's what Windows does */
520 dst
.width
= -dst
.width
;
521 src
.width
= -src
.width
;
523 if (dst
.height
< 0 && dst
.height
== src
.height
)
527 dst
.height
= -dst
.height
;
528 src
.height
= -src
.height
;
532 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
534 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
536 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
537 src
.y
= -src
.height
- 1;
539 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
541 src
.visrect
.left
= 0;
542 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
544 src
.visrect
.bottom
= height
;
545 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
547 if (rop
== SRCCOPY
) ret
= height
;
548 else ret
= src_info
->bmiHeader
.biHeight
;
550 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
552 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
554 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
556 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
558 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
559 copy_bitmapinfo( dst_info
, src_info
);
560 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
561 if (err
== ERROR_BAD_FORMAT
)
563 /* 1-bpp destination without a color table requires a fake 1-entry table
564 * that contains only the background color */
565 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_info
->bmiHeader
.biClrUsed
)
567 COLORREF color
= GetBkColor( dev
->hdc
);
568 dst_info
->bmiColors
[0].rgbRed
= GetRValue( color
);
569 dst_info
->bmiColors
[0].rgbGreen
= GetGValue( color
);
570 dst_info
->bmiColors
[0].rgbBlue
= GetBValue( color
);
571 dst_info
->bmiColors
[0].rgbReserved
= 0;
572 dst_info
->bmiHeader
.biClrUsed
= 1;
575 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
, FALSE
)))
577 /* get rid of the fake 1-bpp table */
578 if (dst_info
->bmiHeader
.biClrUsed
== 1) dst_info
->bmiHeader
.biClrUsed
= 0;
579 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
583 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
585 copy_bitmapinfo( src_info
, dst_info
);
586 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, GetStretchBltMode( dev
->hdc
) );
587 if (!err
) err
= dev
->funcs
->pPutImage( dev
, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
592 if (src_bits
.free
) src_bits
.free( &src_bits
);
593 if (clip
) DeleteObject( clip
);
597 /***********************************************************************
598 * StretchDIBits (GDI32.@)
600 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
601 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
602 const BITMAPINFO
*bmi
, UINT coloruse
, DWORD rop
)
604 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
605 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
610 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
612 SetLastError( ERROR_INVALID_PARAMETER
);
616 if ((dc
= get_dc_ptr( hdc
)))
618 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
620 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
621 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
622 release_dc_ptr( dc
);
628 /******************************************************************************
629 * SetDIBits [GDI32.@]
631 * Sets pixels in a bitmap using colors from DIB.
634 * hdc [I] Handle to device context
635 * hbitmap [I] Handle to bitmap
636 * startscan [I] Starting scan line
637 * lines [I] Number of scan lines
638 * bits [I] Array of bitmap bits
639 * info [I] Address of structure with data
640 * coloruse [I] Type of color indexes to use
643 * Success: Number of scan lines copied
646 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
647 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
651 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
652 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
653 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
654 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
657 struct gdi_image_bits src_bits
;
658 struct bitblt_coords src
, dst
;
659 INT src_to_dst_offset
;
662 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
) || coloruse
> DIB_PAL_COLORS
)
664 SetLastError( ERROR_INVALID_PARAMETER
);
667 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
669 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
670 if (!masks
[0] || !masks
[1] || !masks
[2])
672 SetLastError( ERROR_INVALID_PARAMETER
);
677 src_bits
.ptr
= (void *)bits
;
678 src_bits
.is_copy
= FALSE
;
679 src_bits
.free
= NULL
;
680 src_bits
.param
= NULL
;
682 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
684 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
686 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
688 if (lines
== 0) goto done
;
689 else lines
= src_info
->bmiHeader
.biHeight
;
692 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
695 dst
.visrect
.left
= 0;
697 dst
.visrect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
698 dst
.visrect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
700 src
.visrect
.left
= 0;
702 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
703 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
705 if (src_info
->bmiHeader
.biHeight
> 0)
707 src_to_dst_offset
= -startscan
;
708 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
709 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
713 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
714 /* Unlike the bottom-up case, Windows doesn't limit lines. */
715 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
720 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
721 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
722 src
.visrect
= dst
.visrect
;
723 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
725 src
.x
= src
.visrect
.left
;
726 src
.y
= src
.visrect
.top
;
727 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
728 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
730 dst
.x
= dst
.visrect
.left
;
731 dst
.y
= dst
.visrect
.top
;
732 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
733 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
735 copy_bitmapinfo( dst_info
, src_info
);
737 err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
738 if (err
== ERROR_BAD_FORMAT
)
740 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
, FALSE
);
741 if (!err
) err
= put_image_into_bitmap( bitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
);
746 if (src_bits
.free
) src_bits
.free( &src_bits
);
747 if (clip
) DeleteObject( clip
);
748 GDI_ReleaseObj( hbitmap
);
753 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
754 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
755 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
757 DC
*dc
= get_nulldrv_dc( dev
);
758 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
759 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
760 struct bitblt_coords src
, dst
;
761 struct gdi_image_bits src_bits
;
769 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
770 height
= abs( src_info
->bmiHeader
.biHeight
);
772 src_bits
.ptr
= (void *)bits
;
773 src_bits
.is_copy
= FALSE
;
774 src_bits
.free
= NULL
;
776 if (!lines
) return 0;
777 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
779 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
783 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
784 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
785 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
790 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
794 if (startscan
>= height
) return 0;
795 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
797 /* map src to top-down coordinates with startscan as origin */
799 src
.y
= startscan
+ lines
- (y_src
+ cy
);
806 /* get rid of unnecessary lines */
807 if (src
.y
>= lines
) return 0;
811 else if (src
.y
>= lines
) return lines
;
813 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
816 src
.visrect
.left
= src
.x
;
817 src
.visrect
.top
= src
.y
;
818 src
.visrect
.right
= src
.x
+ cx
;
819 src
.visrect
.bottom
= src
.y
+ cy
;
822 rect
.right
= src_info
->bmiHeader
.biWidth
;
823 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
824 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
832 LPtoDP( dev
->hdc
, &pt
, 1 );
837 if (GetLayout( dev
->hdc
) & LAYOUT_RTL
) dst
.x
-= cx
- 1;
841 rect
.right
= dst
.x
+ cx
;
842 rect
.bottom
= dst
.y
+ cy
;
843 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
845 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
846 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
847 src
.visrect
= dst
.visrect
= rect
;
848 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
849 if (is_rect_empty( &dst
.visrect
)) goto done
;
850 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
852 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
853 copy_bitmapinfo( dst_info
, src_info
);
854 err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
855 if (err
== ERROR_BAD_FORMAT
)
857 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
, FALSE
);
858 if (!err
) err
= dev
->funcs
->pPutImage( dev
, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
863 if (src_bits
.free
) src_bits
.free( &src_bits
);
864 if (clip
) DeleteObject( clip
);
868 /***********************************************************************
869 * SetDIBitsToDevice (GDI32.@)
871 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
872 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
873 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
876 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
877 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
882 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
884 SetLastError( ERROR_INVALID_PARAMETER
);
888 if ((dc
= get_dc_ptr( hdc
)))
890 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
892 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
893 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
894 release_dc_ptr( dc
);
899 /***********************************************************************
900 * SetDIBColorTable (GDI32.@)
902 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, CONST RGBQUAD
*colors
)
908 if (!(dc
= get_dc_ptr( hdc
))) return 0;
910 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
912 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
914 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
915 memcpy(bitmap
->color_table
+ startpos
, colors
, result
* sizeof(RGBQUAD
));
917 GDI_ReleaseObj( dc
->hBitmap
);
919 if (result
) /* update colors of selected objects */
921 SetTextColor( hdc
, dc
->textColor
);
922 SetBkColor( hdc
, dc
->backgroundColor
);
923 SelectObject( hdc
, dc
->hPen
);
924 SelectObject( hdc
, dc
->hBrush
);
927 release_dc_ptr( dc
);
932 /***********************************************************************
933 * GetDIBColorTable (GDI32.@)
935 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
941 if (!(dc
= get_dc_ptr( hdc
))) return 0;
943 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
945 if (startpos
< bitmap
->dib
.dsBmih
.biClrUsed
)
947 result
= min( entries
, bitmap
->dib
.dsBmih
.biClrUsed
- startpos
);
948 memcpy(colors
, bitmap
->color_table
+ startpos
, result
* sizeof(RGBQUAD
));
950 GDI_ReleaseObj( dc
->hBitmap
);
952 release_dc_ptr( dc
);
956 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
957 static const DWORD bit_fields_565
[3] = {0xf800, 0x07e0, 0x001f};
958 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
960 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
962 BITMAPINFOHEADER header
;
964 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
965 header
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
966 header
.biHeight
= bmp
->dib
.dsBm
.bmHeight
;
968 header
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
970 switch (header
.biBitCount
)
974 header
.biCompression
= BI_BITFIELDS
;
977 header
.biCompression
= BI_RGB
;
981 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
982 header
.biXPelsPerMeter
= 0;
983 header
.biYPelsPerMeter
= 0;
984 header
.biClrUsed
= 0;
985 header
.biClrImportant
= 0;
987 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
989 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
991 coreheader
->bcWidth
= header
.biWidth
;
992 coreheader
->bcHeight
= header
.biHeight
;
993 coreheader
->bcPlanes
= header
.biPlanes
;
994 coreheader
->bcBitCount
= header
.biBitCount
;
997 info
->bmiHeader
= header
;
999 return bmp
->dib
.dsBm
.bmHeight
;
1002 /************************************************************************
1005 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1007 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1009 assert( src
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
) );
1011 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1013 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1014 if (coloruse
== DIB_PAL_COLORS
)
1015 memcpy( core
->bmciColors
, src
->bmiColors
, src
->bmiHeader
.biClrUsed
* sizeof(WORD
) );
1019 for (i
= 0; i
< src
->bmiHeader
.biClrUsed
; i
++)
1021 core
->bmciColors
[i
].rgbtRed
= src
->bmiColors
[i
].rgbRed
;
1022 core
->bmciColors
[i
].rgbtGreen
= src
->bmiColors
[i
].rgbGreen
;
1023 core
->bmciColors
[i
].rgbtBlue
= src
->bmiColors
[i
].rgbBlue
;
1029 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1030 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
1032 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1033 /* bitfields are always at bmiColors even in larger structures */
1034 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1035 else if (src
->bmiHeader
.biClrUsed
)
1037 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1040 if (coloruse
== DIB_PAL_COLORS
)
1041 size
= src
->bmiHeader
.biClrUsed
* sizeof(WORD
);
1043 size
= src
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
);
1044 memcpy( colorptr
, src
->bmiColors
, size
);
1049 const RGBQUAD
*get_default_color_table( int bpp
)
1051 static const RGBQUAD table_1
[2] =
1053 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1055 static const RGBQUAD table_4
[16] =
1057 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1058 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1059 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1060 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1062 static const RGBQUAD table_8
[256] =
1064 /* first and last 10 entries are the default system palette entries */
1065 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1066 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1067 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1068 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1069 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1070 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1071 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1072 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1073 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1074 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1075 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1076 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1077 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1078 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1079 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1080 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1081 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1082 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1083 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1084 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1085 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1086 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1087 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1088 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1089 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1090 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1091 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1092 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1093 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1094 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1095 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1096 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1097 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1098 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1099 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1100 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1101 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1102 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1103 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1104 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1105 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1106 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1107 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1108 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1109 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1110 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1111 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1112 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1113 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1114 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1115 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1116 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1117 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1118 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1119 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1120 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1121 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1122 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1123 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1124 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1125 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1126 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1127 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1128 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1133 case 1: return table_1
;
1134 case 4: return table_4
;
1135 case 8: return table_8
;
1136 default: return NULL
;
1140 void fill_default_color_table( BITMAPINFO
*info
)
1142 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1143 memcpy( info
->bmiColors
, get_default_color_table( info
->bmiHeader
.biBitCount
),
1144 info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
1147 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1149 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1150 info
->bmiHeader
.biWidth
= bmp
->dib
.dsBm
.bmWidth
;
1151 info
->bmiHeader
.biHeight
= -bmp
->dib
.dsBm
.bmHeight
;
1152 info
->bmiHeader
.biPlanes
= 1;
1153 info
->bmiHeader
.biBitCount
= bmp
->dib
.dsBm
.bmBitsPixel
;
1154 info
->bmiHeader
.biCompression
= BI_RGB
;
1155 info
->bmiHeader
.biXPelsPerMeter
= 0;
1156 info
->bmiHeader
.biYPelsPerMeter
= 0;
1157 info
->bmiHeader
.biClrUsed
= 0;
1158 info
->bmiHeader
.biClrImportant
= 0;
1161 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1163 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1164 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1165 unsigned int info_size
;
1167 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1169 info_size
= get_dib_info_size( info
, usage
);
1170 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ info
->bmiHeader
.biSizeImage
)))
1172 memcpy( ret
, info
, info_size
);
1173 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size( src_info
, usage
),
1174 info
->bmiHeader
.biSizeImage
);
1179 /******************************************************************************
1180 * GetDIBits [GDI32.@]
1182 * Retrieves bits of bitmap and copies to buffer.
1185 * Success: Number of scan lines copied from bitmap
1188 INT WINAPI
GetDIBits(
1189 HDC hdc
, /* [in] Handle to device context */
1190 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1191 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1192 UINT lines
, /* [in] Number of scan lines to copy */
1193 LPVOID bits
, /* [out] Address of array for bitmap bits */
1194 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1195 UINT coloruse
) /* [in] RGB or palette index */
1199 int i
, dst_to_src_offset
, ret
= 0;
1201 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1202 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1203 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1204 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1205 struct gdi_image_bits src_bits
;
1206 struct bitblt_coords src
, dst
;
1207 BOOL empty_rect
= FALSE
;
1209 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1210 own copy and transfer the colour info back at the end */
1211 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1212 if (coloruse
> DIB_PAL_COLORS
) return 0;
1214 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1216 dst_info
->bmiHeader
.biClrUsed
= 0;
1217 dst_info
->bmiHeader
.biClrImportant
= 0;
1219 if (!(dc
= get_dc_ptr( hdc
)))
1221 SetLastError( ERROR_INVALID_PARAMETER
);
1225 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1227 release_dc_ptr( dc
);
1231 src
.visrect
.left
= 0;
1232 src
.visrect
.top
= 0;
1233 src
.visrect
.right
= bmp
->dib
.dsBm
.bmWidth
;
1234 src
.visrect
.bottom
= bmp
->dib
.dsBm
.bmHeight
;
1236 dst
.visrect
.left
= 0;
1237 dst
.visrect
.top
= 0;
1238 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1239 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1241 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1244 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1246 ret
= fill_query_info( info
, bmp
);
1250 /* validate parameters */
1252 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1253 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1255 switch (dst_info
->bmiHeader
.biCompression
)
1258 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1259 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1260 if (bits
) goto done
; /* can't retrieve compressed bits */
1263 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1264 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1265 if (bits
) goto done
; /* can't retrieve compressed bits */
1268 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1271 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1272 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1273 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1274 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1275 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1276 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1277 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1285 if (dst_info
->bmiHeader
.biHeight
> 0)
1287 dst_to_src_offset
= -startscan
;
1288 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1289 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1293 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1294 if (dst_to_src_offset
< 0)
1296 dst_to_src_offset
= 0;
1297 lines
= dst
.visrect
.bottom
- startscan
;
1299 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1302 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1303 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1304 dst
.visrect
= src
.visrect
;
1305 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1307 if (dst_info
->bmiHeader
.biHeight
> 0)
1309 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1311 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1312 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1313 memset( bits
, 0, pad_bytes
);
1314 bits
= (char *)bits
+ pad_bytes
;
1319 if (dst
.visrect
.bottom
< lines
)
1321 int pad_lines
= lines
- dst
.visrect
.bottom
;
1322 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1323 int pad_bytes
= pad_lines
* stride
;
1324 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1328 if (empty_rect
) bits
= NULL
;
1330 src
.x
= src
.visrect
.left
;
1331 src
.y
= src
.visrect
.top
;
1332 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1333 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1338 err
= get_image_from_bitmap( bmp
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1342 /* fill out the src colour table, if it needs one */
1343 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1344 fill_default_color_table( src_info
);
1346 /* if the src and dst are the same depth, copy the colour info across */
1347 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1349 switch (src_info
->bmiHeader
.biBitCount
)
1352 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1354 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1355 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1359 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1361 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1362 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1366 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1367 copy_color_info( dst_info
, src_info
, coloruse
);
1369 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1371 if( coloruse
== DIB_PAL_COLORS
)
1373 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1377 fill_default_color_table( dst_info
);
1383 if(dst_info
->bmiHeader
.biHeight
> 0)
1384 dst_info
->bmiHeader
.biHeight
= src
.height
;
1386 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1388 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
, FALSE
);
1389 if (src_bits
.free
) src_bits
.free( &src_bits
);
1393 ret
= empty_rect
? FALSE
: TRUE
;
1395 if (coloruse
== DIB_PAL_COLORS
)
1397 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1398 for (i
= 0; i
< dst_info
->bmiHeader
.biClrUsed
; i
++, index
++)
1402 copy_color_info( info
, dst_info
, coloruse
);
1403 if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
)) info
->bmiHeader
.biClrUsed
= 0;
1406 release_dc_ptr( dc
);
1407 GDI_ReleaseObj( hbitmap
);
1412 /***********************************************************************
1413 * CreateDIBitmap (GDI32.@)
1415 * Creates a DDB (device dependent bitmap) from a DIB.
1416 * The DDB will have the same color depth as the reference DC.
1418 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1419 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1422 BITMAPINFOHEADER info
;
1426 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1427 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1428 if (coloruse
> DIB_PAL_COLORS
+ 1) return 0;
1429 if (info
.biWidth
< 0) return 0;
1431 /* Top-down DIBs have a negative height */
1432 height
= abs( info
.biHeight
);
1434 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1435 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1436 info
.biBitCount
, info
.biCompression
);
1439 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1441 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1445 if (init
& CBM_INIT
)
1447 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1449 DeleteObject( handle
);
1459 /***********************************************************************
1460 * CreateDIBSection (GDI32.@)
1462 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, CONST BITMAPINFO
*bmi
, UINT usage
,
1463 VOID
**bits
, HANDLE section
, DWORD offset
)
1465 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1466 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1469 void *mapBits
= NULL
;
1471 if (bits
) *bits
= NULL
;
1472 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1473 if (usage
> DIB_PAL_COLORS
) return 0;
1474 if (info
->bmiHeader
.biPlanes
!= 1)
1476 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1477 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1480 if (!(bmp
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*bmp
) ))) return 0;
1482 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1483 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1484 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1485 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1486 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1488 bmp
->dib
.dsBm
.bmType
= 0;
1489 bmp
->dib
.dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1490 bmp
->dib
.dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1491 bmp
->dib
.dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1492 bmp
->dib
.dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1493 bmp
->dib
.dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1494 bmp
->dib
.dsBmih
= info
->bmiHeader
;
1496 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1498 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1500 bmp
->dib
.dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1501 if (!(bmp
->color_table
= HeapAlloc( GetProcessHeap(), 0,
1502 bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1504 memcpy( bmp
->color_table
, info
->bmiColors
, bmp
->dib
.dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1507 /* set dsBitfields values */
1508 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1510 bmp
->dib
.dsBmih
.biCompression
= BI_BITFIELDS
;
1511 bmp
->dib
.dsBitfields
[0] = 0x7c00;
1512 bmp
->dib
.dsBitfields
[1] = 0x03e0;
1513 bmp
->dib
.dsBitfields
[2] = 0x001f;
1515 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1517 if (usage
== DIB_PAL_COLORS
) goto error
;
1518 bmp
->dib
.dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1519 bmp
->dib
.dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1520 bmp
->dib
.dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1521 if (!bmp
->dib
.dsBitfields
[0] || !bmp
->dib
.dsBitfields
[1] || !bmp
->dib
.dsBitfields
[2]) goto error
;
1523 else bmp
->dib
.dsBitfields
[0] = bmp
->dib
.dsBitfields
[1] = bmp
->dib
.dsBitfields
[2] = 0;
1525 /* get storage location for DIB bits */
1529 SYSTEM_INFO SystemInfo
;
1533 GetSystemInfo( &SystemInfo
);
1534 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1535 mapSize
= bmp
->dib
.dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1536 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1537 if (mapBits
) bmp
->dib
.dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1542 bmp
->dib
.dsBm
.bmBits
= VirtualAlloc( NULL
, bmp
->dib
.dsBmih
.biSizeImage
,
1543 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1545 bmp
->dib
.dshSection
= section
;
1546 bmp
->dib
.dsOffset
= offset
;
1548 if (!bmp
->dib
.dsBm
.bmBits
) goto error
;
1550 if (!(ret
= alloc_gdi_handle( &bmp
->header
, OBJ_BITMAP
, &dib_funcs
))) goto error
;
1552 if (bits
) *bits
= bmp
->dib
.dsBm
.bmBits
;
1556 if (section
) UnmapViewOfFile( mapBits
);
1557 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1558 HeapFree( GetProcessHeap(), 0, bmp
->color_table
);
1559 HeapFree( GetProcessHeap(), 0, bmp
);
1564 /***********************************************************************
1567 static HGDIOBJ
DIB_SelectObject( HGDIOBJ handle
, HDC hdc
)
1574 if (!(dc
= get_dc_ptr( hdc
))) return 0;
1576 if (GetObjectType( hdc
) != OBJ_MEMDC
)
1582 if (handle
== dc
->hBitmap
) goto done
; /* nothing to do */
1584 if (!(bitmap
= GDI_GetObjPtr( handle
, OBJ_BITMAP
)))
1590 if (bitmap
->header
.selcount
)
1592 WARN( "Bitmap already selected in another DC\n" );
1593 GDI_ReleaseObj( handle
);
1598 physdev
= GET_DC_PHYSDEV( dc
, pSelectBitmap
);
1599 if (!physdev
->funcs
->pSelectBitmap( physdev
, handle
))
1601 GDI_ReleaseObj( handle
);
1606 dc
->hBitmap
= handle
;
1607 GDI_inc_ref_count( handle
);
1609 dc
->vis_rect
.left
= 0;
1610 dc
->vis_rect
.top
= 0;
1611 dc
->vis_rect
.right
= bitmap
->dib
.dsBm
.bmWidth
;
1612 dc
->vis_rect
.bottom
= bitmap
->dib
.dsBm
.bmHeight
;
1613 dc
->device_rect
= dc
->vis_rect
;
1614 GDI_ReleaseObj( handle
);
1616 GDI_dec_ref_count( ret
);
1620 release_dc_ptr( dc
);
1625 /***********************************************************************
1628 static INT
DIB_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
1631 BITMAPOBJ
*bmp
= GDI_GetObjPtr( handle
, OBJ_BITMAP
);
1635 if (!buffer
) ret
= sizeof(BITMAP
);
1636 else if (count
>= sizeof(DIBSECTION
))
1638 DIBSECTION
*dib
= buffer
;
1640 dib
->dsBmih
.biHeight
= abs( dib
->dsBmih
.biHeight
);
1641 ret
= sizeof(DIBSECTION
);
1643 else if (count
>= sizeof(BITMAP
))
1645 BITMAP
*bitmap
= buffer
;
1646 *bitmap
= bmp
->dib
.dsBm
;
1647 ret
= sizeof(BITMAP
);
1650 GDI_ReleaseObj( handle
);
1655 /***********************************************************************
1658 static BOOL
DIB_DeleteObject( HGDIOBJ handle
)
1662 if (!(bmp
= free_gdi_handle( handle
))) return FALSE
;
1664 if (bmp
->dib
.dshSection
)
1666 SYSTEM_INFO SystemInfo
;
1667 GetSystemInfo( &SystemInfo
);
1668 UnmapViewOfFile( (char *)bmp
->dib
.dsBm
.bmBits
-
1669 (bmp
->dib
.dsOffset
% SystemInfo
.dwAllocationGranularity
) );
1671 else VirtualFree( bmp
->dib
.dsBm
.bmBits
, 0, MEM_RELEASE
);
1673 HeapFree(GetProcessHeap(), 0, bmp
->color_table
);
1674 return HeapFree( GetProcessHeap(), 0, bmp
);