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 /***********************************************************************
78 * Return the size of the bitmap info structure including color table.
80 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
82 unsigned int colors
, size
, masks
= 0;
84 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
86 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
87 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
88 return sizeof(BITMAPCOREHEADER
) + colors
*
89 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
91 else /* assume BITMAPINFOHEADER */
93 colors
= get_dib_num_of_colors( info
);
94 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
95 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
96 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
100 /*******************************************************************************************
101 * Verify that the DIB parameters are valid.
103 static BOOL
is_valid_dib_format( const BITMAPINFOHEADER
*info
, BOOL allow_compression
)
105 if (info
->biWidth
<= 0) return FALSE
;
106 if (info
->biHeight
== 0) return FALSE
;
108 if (allow_compression
&& (info
->biCompression
== BI_RLE4
|| info
->biCompression
== BI_RLE8
))
110 if (info
->biHeight
< 0) return FALSE
;
111 if (!info
->biSizeImage
) return FALSE
;
112 return info
->biBitCount
== (info
->biCompression
== BI_RLE4
? 4 : 8);
115 if (!info
->biPlanes
) return FALSE
;
117 switch (info
->biBitCount
)
123 return (info
->biCompression
== BI_RGB
);
126 return (info
->biCompression
== BI_BITFIELDS
|| info
->biCompression
== BI_RGB
);
132 /*******************************************************************************************
133 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
135 static BOOL
bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER
*dst
, const BITMAPINFOHEADER
*info
)
137 if (!info
) return FALSE
;
139 if (info
->biSize
== sizeof(BITMAPCOREHEADER
))
141 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
142 dst
->biWidth
= core
->bcWidth
;
143 dst
->biHeight
= core
->bcHeight
;
144 dst
->biPlanes
= core
->bcPlanes
;
145 dst
->biBitCount
= core
->bcBitCount
;
146 dst
->biCompression
= BI_RGB
;
147 dst
->biXPelsPerMeter
= 0;
148 dst
->biYPelsPerMeter
= 0;
150 dst
->biClrImportant
= 0;
152 else if (info
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
158 WARN( "(%u): unknown/wrong size for header\n", info
->biSize
);
162 dst
->biSize
= sizeof(*dst
);
163 if (dst
->biCompression
== BI_RGB
|| dst
->biCompression
== BI_BITFIELDS
)
164 dst
->biSizeImage
= get_dib_image_size( (BITMAPINFO
*)dst
);
168 /*******************************************************************************************
169 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
171 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
,
172 UINT coloruse
, BOOL allow_compression
)
177 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
178 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
180 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
181 colors
= get_dib_num_of_colors( dst
);
183 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
185 /* bitfields are always at bmiColors even in larger structures */
186 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
190 if (coloruse
== DIB_PAL_COLORS
)
191 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
192 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
193 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
197 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
198 for (i
= 0; i
< colors
; i
++)
200 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
201 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
202 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
203 dst
->bmiColors
[i
].rgbReserved
= 0;
210 static int fill_color_table_from_palette( BITMAPINFO
*info
, DC
*dc
)
212 PALETTEENTRY palEntry
[256];
213 int i
, colors
= get_dib_num_of_colors( info
);
215 if (!colors
) return 0;
217 memset( palEntry
, 0, sizeof(palEntry
) );
218 if (!GetPaletteEntries( dc
->hPalette
, 0, colors
, palEntry
))
221 for (i
= 0; i
< colors
; i
++)
223 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
224 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
225 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
226 info
->bmiColors
[i
].rgbReserved
= 0;
232 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
234 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
235 const int bpp
= info
->bmiHeader
.biBitCount
;
238 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
240 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
243 static BOOL
build_rle_bitmap( const BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
247 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
249 BYTE skip
, num
, data
;
250 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
254 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
256 out_bits
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
) );
257 *clip
= CreateRectRgn( 0, 0, 0, 0 );
258 run
= CreateRectRgn( 0, 0, 0, 0 );
259 if (!out_bits
|| !*clip
|| !run
) goto fail
;
261 x
= left
= right
= 0;
264 while (i
< info
->bmiHeader
.biSizeImage
- 1)
267 data
= in_bits
[i
+ 1];
272 if (x
+ num
> width
) num
= width
- x
;
275 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
276 if (info
->bmiHeader
.biBitCount
== 8)
277 memset( out_ptr
, s
, num
);
282 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
283 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
288 /* this will write one too many if num is odd, but that doesn't matter */
289 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
301 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
302 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
307 left
= right
= x
= 0;
316 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
318 if (x
> width
) x
= width
;
325 else /* data bytes of data */
328 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
329 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
330 skip
= (skip
+ 1) & ~1;
331 if (x
+ num
> width
) num
= width
- x
;
334 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
335 if (info
->bmiHeader
.biBitCount
== 8)
336 memcpy( out_ptr
, in_bits
+ i
, num
);
341 const BYTE
*in_ptr
= in_bits
+ i
;
342 for ( ; num
; num
--, x
++)
346 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
350 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
354 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
366 if (bits
->free
) bits
->free( bits
);
368 bits
->ptr
= out_bits
;
369 bits
->is_copy
= TRUE
;
370 bits
->free
= free_heap_bits
;
375 if (run
) DeleteObject( run
);
376 if (*clip
) DeleteObject( *clip
);
377 HeapFree( GetProcessHeap(), 0, out_bits
);
383 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
384 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
385 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
386 const BITMAPINFO
*info
, UINT coloruse
, DWORD rop
)
388 DC
*dc
= get_nulldrv_dc( dev
);
394 /* make sure we have a real implementation for StretchBlt and PutImage */
395 if (GET_DC_PHYSDEV( dc
, pStretchBlt
) == dev
|| GET_DC_PHYSDEV( dc
, pPutImage
) == dev
)
398 height
= info
->bmiHeader
.biHeight
;
400 if (xSrc
== 0 && ySrc
== 0 && widthDst
== widthSrc
&& heightDst
== heightSrc
&&
401 info
->bmiHeader
.biCompression
== BI_RGB
)
403 /* Windows appears to have a fast case optimization
404 * that uses the wrong origin for top-down DIBs */
405 if (height
< 0 && heightSrc
< abs(height
)) ySrc
= abs(height
) - heightSrc
;
407 if (xDst
== 0 && yDst
== 0 && info
->bmiHeader
.biCompression
== BI_RGB
&& rop
== SRCCOPY
)
410 hBitmap
= GetCurrentObject( dev
->hdc
, OBJ_BITMAP
);
411 if (GetObjectW( hBitmap
, sizeof(bm
), &bm
) &&
412 bm
.bmWidth
== widthSrc
&& bm
.bmHeight
== heightSrc
&&
413 bm
.bmBitsPixel
== info
->bmiHeader
.biBitCount
&& bm
.bmPlanes
== 1)
416 return SetDIBits( dev
->hdc
, hBitmap
, 0, abs( height
), bits
, info
, coloruse
);
421 hdcMem
= CreateCompatibleDC( dev
->hdc
);
422 hBitmap
= CreateCompatibleBitmap( dev
->hdc
, info
->bmiHeader
.biWidth
, height
);
423 SelectObject( hdcMem
, hBitmap
);
424 if (coloruse
== DIB_PAL_COLORS
)
425 SelectPalette( hdcMem
, GetCurrentObject( dev
->hdc
, OBJ_PAL
), FALSE
);
427 if (info
->bmiHeader
.biCompression
== BI_RLE4
|| info
->bmiHeader
.biCompression
== BI_RLE8
)
429 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
430 * contain all the rectangle described in bmiHeader, but only part of it.
431 * This mean that those undescribed pixels must be left untouched.
432 * So, we first copy on a memory bitmap the current content of the
433 * destination rectangle, blit the DIB bits on top of it - hence leaving
434 * the gaps untouched -, and blitting the rectangle back.
435 * This insure that gaps are untouched on the destination rectangle
437 StretchBlt( hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
, widthSrc
, heightSrc
,
438 dev
->hdc
, xDst
, yDst
, widthDst
, heightDst
, rop
);
440 ret
= SetDIBits( hdcMem
, hBitmap
, 0, abs( height
), bits
, info
, coloruse
);
441 if (ret
) StretchBlt( dev
->hdc
, xDst
, yDst
, widthDst
, heightDst
,
442 hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
, widthSrc
, heightSrc
, rop
);
444 DeleteObject( hBitmap
);
448 /***********************************************************************
449 * StretchDIBits (GDI32.@)
451 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
452 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
453 const BITMAPINFO
*bmi
, UINT coloruse
, DWORD rop
)
455 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
456 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
461 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
463 SetLastError( ERROR_INVALID_PARAMETER
);
467 if ((dc
= get_dc_ptr( hdc
)))
469 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
471 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
472 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
473 release_dc_ptr( dc
);
479 /******************************************************************************
480 * SetDIBits [GDI32.@]
482 * Sets pixels in a bitmap using colors from DIB.
485 * hdc [I] Handle to device context
486 * hbitmap [I] Handle to bitmap
487 * startscan [I] Starting scan line
488 * lines [I] Number of scan lines
489 * bits [I] Array of bitmap bits
490 * info [I] Address of structure with data
491 * coloruse [I] Type of color indexes to use
494 * Success: Number of scan lines copied
497 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
498 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
501 DC
*dc
= get_dc_ptr( hdc
);
502 BOOL delete_hdc
= FALSE
;
505 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
506 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
507 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
508 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
511 struct gdi_image_bits src_bits
;
512 struct bitblt_coords src
, dst
;
513 INT src_to_dst_offset
;
515 const struct gdi_dc_funcs
*funcs
;
517 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
))
519 SetLastError( ERROR_INVALID_PARAMETER
);
523 src_bits
.ptr
= (void *)bits
;
524 src_bits
.is_copy
= FALSE
;
525 src_bits
.free
= NULL
;
526 src_bits
.param
= NULL
;
528 if (coloruse
== DIB_RGB_COLORS
&& !dc
)
530 hdc
= CreateCompatibleDC(0);
531 dc
= get_dc_ptr( hdc
);
539 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
541 release_dc_ptr( dc
);
542 if (delete_hdc
) DeleteDC(hdc
);
546 if (coloruse
== DIB_PAL_COLORS
)
547 if (!fill_color_table_from_palette( src_info
, dc
)) goto done
;
549 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
551 if (lines
== 0) goto done
;
552 else lines
= src_info
->bmiHeader
.biHeight
;
555 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
558 dst
.visrect
.left
= 0;
560 dst
.visrect
.right
= bitmap
->bitmap
.bmWidth
;
561 dst
.visrect
.bottom
= bitmap
->bitmap
.bmHeight
;
563 src
.visrect
.left
= 0;
565 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
566 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
568 if (src_info
->bmiHeader
.biHeight
> 0)
570 src_to_dst_offset
= -startscan
;
571 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
572 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
576 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
577 /* Unlike the bottom-up case, Windows doesn't limit lines. */
578 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
581 /* Hack to ensure we don't get the nulldrv if the bmp hasn't been selected
583 physdev
= GET_DC_PHYSDEV( dc
, pCreateBitmap
);
584 if (!BITMAP_SetOwnerDC( hbitmap
, physdev
)) goto done
;
586 funcs
= bitmap
->funcs
;
587 if (bitmap
->dib
) funcs
= dc
->dibdrv
.dev
.funcs
;
591 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
592 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
593 src
.visrect
= dst
.visrect
;
594 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
596 src
.x
= src
.visrect
.left
;
597 src
.y
= src
.visrect
.top
;
598 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
599 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
601 dst
.x
= dst
.visrect
.left
;
602 dst
.y
= dst
.visrect
.top
;
603 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
604 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
606 memcpy( dst_info
, src_info
, FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] ));
608 err
= funcs
->pPutImage( NULL
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
609 if (err
== ERROR_BAD_FORMAT
)
613 dst_info
->bmiHeader
.biWidth
= dst
.width
;
614 ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info
));
617 err
= convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, ptr
);
619 if (src_bits
.free
) src_bits
.free( &src_bits
);
621 src_bits
.is_copy
= TRUE
;
622 src_bits
.free
= free_heap_bits
;
624 err
= funcs
->pPutImage( NULL
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
627 else err
= ERROR_OUTOFMEMORY
;
632 if (src_bits
.free
) src_bits
.free( &src_bits
);
633 if (clip
) DeleteObject( clip
);
634 GDI_ReleaseObj( hbitmap
);
635 release_dc_ptr( dc
);
636 if (delete_hdc
) DeleteDC(hdc
);
641 /***********************************************************************
642 * SetDIBitsToDevice (GDI32.@)
644 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
645 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
646 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
649 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
650 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
655 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
657 SetLastError( ERROR_INVALID_PARAMETER
);
661 if ((dc
= get_dc_ptr( hdc
)))
663 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
665 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
666 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
667 release_dc_ptr( dc
);
672 /***********************************************************************
673 * SetDIBColorTable (GDI32.@)
675 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, CONST RGBQUAD
*colors
)
681 if (!(dc
= get_dc_ptr( hdc
))) return 0;
683 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
685 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBColorTable
);
687 /* Check if currently selected bitmap is a DIB */
688 if (bitmap
->color_table
)
690 if (startpos
< bitmap
->nb_colors
)
692 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
693 memcpy(bitmap
->color_table
+ startpos
, colors
, entries
* sizeof(RGBQUAD
));
697 GDI_ReleaseObj( dc
->hBitmap
);
698 physdev
->funcs
->pSetDIBColorTable( physdev
, startpos
, entries
, colors
);
700 release_dc_ptr( dc
);
705 /***********************************************************************
706 * GetDIBColorTable (GDI32.@)
708 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
714 if (!(dc
= get_dc_ptr( hdc
))) return 0;
716 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
718 /* Check if currently selected bitmap is a DIB */
719 if (bitmap
->color_table
)
721 if (startpos
< bitmap
->nb_colors
)
723 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
724 memcpy(colors
, bitmap
->color_table
+ startpos
, entries
* sizeof(RGBQUAD
));
728 GDI_ReleaseObj( dc
->hBitmap
);
730 release_dc_ptr( dc
);
734 static const RGBQUAD DefLogPaletteQuads
[20] = { /* Copy of Default Logical Palette */
735 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
736 { 0x00, 0x00, 0x00, 0x00 },
737 { 0x00, 0x00, 0x80, 0x00 },
738 { 0x00, 0x80, 0x00, 0x00 },
739 { 0x00, 0x80, 0x80, 0x00 },
740 { 0x80, 0x00, 0x00, 0x00 },
741 { 0x80, 0x00, 0x80, 0x00 },
742 { 0x80, 0x80, 0x00, 0x00 },
743 { 0xc0, 0xc0, 0xc0, 0x00 },
744 { 0xc0, 0xdc, 0xc0, 0x00 },
745 { 0xf0, 0xca, 0xa6, 0x00 },
746 { 0xf0, 0xfb, 0xff, 0x00 },
747 { 0xa4, 0xa0, 0xa0, 0x00 },
748 { 0x80, 0x80, 0x80, 0x00 },
749 { 0x00, 0x00, 0xff, 0x00 },
750 { 0x00, 0xff, 0x00, 0x00 },
751 { 0x00, 0xff, 0xff, 0x00 },
752 { 0xff, 0x00, 0x00, 0x00 },
753 { 0xff, 0x00, 0xff, 0x00 },
754 { 0xff, 0xff, 0x00, 0x00 },
755 { 0xff, 0xff, 0xff, 0x00 }
758 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
759 static const DWORD bit_fields_565
[3] = {0xf800, 0x07e0, 0x001f};
760 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
762 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
764 BITMAPINFOHEADER header
;
766 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
767 header
.biWidth
= bmp
->bitmap
.bmWidth
;
768 header
.biHeight
= bmp
->bitmap
.bmHeight
;
773 header
.biBitCount
= bmp
->dib
->dsBm
.bmBitsPixel
;
774 switch (bmp
->dib
->dsBm
.bmBitsPixel
)
778 header
.biCompression
= BI_BITFIELDS
;
781 header
.biCompression
= BI_RGB
;
787 header
.biCompression
= (bmp
->bitmap
.bmBitsPixel
> 8) ? BI_BITFIELDS
: BI_RGB
;
788 header
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
791 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
792 header
.biXPelsPerMeter
= 0;
793 header
.biYPelsPerMeter
= 0;
794 header
.biClrUsed
= 0;
795 header
.biClrImportant
= 0;
797 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
799 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
801 coreheader
->bcWidth
= header
.biWidth
;
802 coreheader
->bcHeight
= header
.biHeight
;
803 coreheader
->bcPlanes
= header
.biPlanes
;
804 coreheader
->bcBitCount
= header
.biBitCount
;
807 info
->bmiHeader
= header
;
809 return abs(bmp
->bitmap
.bmHeight
);
812 /************************************************************************
815 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
817 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
819 unsigned int colors
= get_dib_num_of_colors( src
);
820 RGBQUAD
*src_colors
= (RGBQUAD
*)((char *)src
+ src
->bmiHeader
.biSize
);
822 assert( src
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) );
824 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
826 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
827 if (coloruse
== DIB_PAL_COLORS
)
828 memcpy( core
->bmciColors
, src_colors
, colors
* sizeof(WORD
) );
832 for (i
= 0; i
< colors
; i
++)
834 core
->bmciColors
[i
].rgbtRed
= src_colors
[i
].rgbRed
;
835 core
->bmciColors
[i
].rgbtGreen
= src_colors
[i
].rgbGreen
;
836 core
->bmciColors
[i
].rgbtBlue
= src_colors
[i
].rgbBlue
;
842 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
843 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
845 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
846 /* bitfields are always at bmiColors even in larger structures */
847 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
850 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
853 if (coloruse
== DIB_PAL_COLORS
)
854 size
= colors
* sizeof(WORD
);
856 size
= colors
* sizeof(RGBQUAD
);
857 memcpy( colorptr
, src_colors
, size
);
862 static void fill_default_color_table( BITMAPINFO
*info
)
866 switch (info
->bmiHeader
.biBitCount
)
869 info
->bmiColors
[0].rgbRed
= info
->bmiColors
[0].rgbGreen
= info
->bmiColors
[0].rgbBlue
= 0;
870 info
->bmiColors
[0].rgbReserved
= 0;
871 info
->bmiColors
[1].rgbRed
= info
->bmiColors
[1].rgbGreen
= info
->bmiColors
[1].rgbBlue
= 0xff;
872 info
->bmiColors
[1].rgbReserved
= 0;
876 /* The EGA palette is the first and last 8 colours of the default palette
877 with the innermost pair swapped */
878 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 7 * sizeof(RGBQUAD
));
879 memcpy(info
->bmiColors
+ 7, DefLogPaletteQuads
+ 12, 1 * sizeof(RGBQUAD
));
880 memcpy(info
->bmiColors
+ 8, DefLogPaletteQuads
+ 7, 1 * sizeof(RGBQUAD
));
881 memcpy(info
->bmiColors
+ 9, DefLogPaletteQuads
+ 13, 7 * sizeof(RGBQUAD
));
885 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 10 * sizeof(RGBQUAD
));
886 memcpy(info
->bmiColors
+ 246, DefLogPaletteQuads
+ 10, 10 * sizeof(RGBQUAD
));
887 for (i
= 10; i
< 246; i
++)
889 info
->bmiColors
[i
].rgbRed
= (i
& 0x07) << 5;
890 info
->bmiColors
[i
].rgbGreen
= (i
& 0x38) << 2;
891 info
->bmiColors
[i
].rgbBlue
= i
& 0xc0;
892 info
->bmiColors
[i
].rgbReserved
= 0;
897 ERR("called with bitcount %d\n", info
->bmiHeader
.biBitCount
);
901 /******************************************************************************
902 * GetDIBits [GDI32.@]
904 * Retrieves bits of bitmap and copies to buffer.
907 * Success: Number of scan lines copied from bitmap
910 INT WINAPI
GetDIBits(
911 HDC hdc
, /* [in] Handle to device context */
912 HBITMAP hbitmap
, /* [in] Handle to bitmap */
913 UINT startscan
, /* [in] First scan line to set in dest bitmap */
914 UINT lines
, /* [in] Number of scan lines to copy */
915 LPVOID bits
, /* [out] Address of array for bitmap bits */
916 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
917 UINT coloruse
) /* [in] RGB or palette index */
921 int i
, dst_to_src_offset
, ret
= 0;
923 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
924 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
925 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
926 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
927 const struct gdi_dc_funcs
*funcs
;
928 struct gdi_image_bits src_bits
;
929 struct bitblt_coords src
, dst
;
930 BOOL empty_rect
= FALSE
;
932 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
933 own copy and transfer the colour info back at the end */
934 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
935 dst_info
->bmiHeader
.biClrUsed
= 0;
936 dst_info
->bmiHeader
.biClrImportant
= 0;
938 if (!(dc
= get_dc_ptr( hdc
)))
940 SetLastError( ERROR_INVALID_PARAMETER
);
944 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
946 release_dc_ptr( dc
);
951 if (bmp
->dib
) funcs
= dc
->dibdrv
.dev
.funcs
;
953 if (dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
955 ret
= fill_query_info( info
, bmp
);
959 src
.visrect
.left
= 0;
961 src
.visrect
.right
= bmp
->bitmap
.bmWidth
;
962 src
.visrect
.bottom
= bmp
->bitmap
.bmHeight
;
964 dst
.visrect
.left
= 0;
966 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
967 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
969 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
974 if (dst_info
->bmiHeader
.biHeight
> 0)
976 dst_to_src_offset
= -startscan
;
977 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
978 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
982 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
983 if (dst_to_src_offset
< 0)
985 dst_to_src_offset
= 0;
986 lines
= dst
.visrect
.bottom
- startscan
;
988 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
991 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
992 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
993 dst
.visrect
= src
.visrect
;
994 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
996 if (dst_info
->bmiHeader
.biHeight
> 0)
998 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1000 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1001 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1002 memset( bits
, 0, pad_bytes
);
1003 bits
= (char *)bits
+ pad_bytes
;
1008 if (dst
.visrect
.bottom
< lines
)
1010 int pad_lines
= lines
- dst
.visrect
.bottom
;
1011 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1012 int pad_bytes
= pad_lines
* stride
;
1013 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1017 if (empty_rect
) bits
= NULL
;
1019 src
.x
= src
.visrect
.left
;
1020 src
.y
= src
.visrect
.top
;
1021 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1022 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1027 err
= funcs
->pGetImage( NULL
, hbitmap
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1031 /* fill out the src colour table, if it needs one */
1032 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1034 fill_default_color_table( src_info
);
1035 src_info
->bmiHeader
.biClrUsed
= 1 << src_info
->bmiHeader
.biBitCount
;
1038 /* if the src and dst are the same depth, copy the colour info across */
1039 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1041 switch (src_info
->bmiHeader
.biBitCount
)
1044 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1046 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1047 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1051 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1053 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1054 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1058 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1059 copy_color_info( dst_info
, src_info
, coloruse
);
1061 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1063 if( coloruse
== DIB_PAL_COLORS
)
1065 if (!fill_color_table_from_palette( dst_info
, dc
)) goto done
;
1069 fill_default_color_table( dst_info
);
1075 if(dst_info
->bmiHeader
.biHeight
> 0)
1076 dst_info
->bmiHeader
.biHeight
= src
.height
;
1078 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1080 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1081 if (src_bits
.free
) src_bits
.free( &src_bits
);
1085 ret
= empty_rect
? FALSE
: TRUE
;
1087 if (coloruse
== DIB_PAL_COLORS
)
1089 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1090 int colors
= get_dib_num_of_colors( dst_info
);
1091 for (i
= 0; i
< colors
; i
++, index
++)
1095 copy_color_info( info
, dst_info
, coloruse
);
1098 release_dc_ptr( dc
);
1099 GDI_ReleaseObj( hbitmap
);
1104 /***********************************************************************
1105 * CreateDIBitmap (GDI32.@)
1107 * Creates a DDB (device dependent bitmap) from a DIB.
1108 * The DDB will have the same color depth as the reference DC.
1110 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1111 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1114 BITMAPINFOHEADER info
;
1118 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1119 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1120 if (info
.biWidth
< 0) return 0;
1122 /* Top-down DIBs have a negative height */
1123 height
= abs( info
.biHeight
);
1125 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1126 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1127 info
.biBitCount
, info
.biCompression
);
1130 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1132 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1136 if (init
& CBM_INIT
)
1138 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1140 DeleteObject( handle
);
1149 /* Copy/synthesize RGB palette from BITMAPINFO */
1150 static void DIB_CopyColorTable( DC
*dc
, BITMAPOBJ
*bmp
, WORD coloruse
, const BITMAPINFO
*info
)
1152 unsigned int colors
, i
;
1154 colors
= get_dib_num_of_colors( info
);
1155 if (!(bmp
->color_table
= HeapAlloc(GetProcessHeap(), 0, colors
* sizeof(RGBQUAD
) ))) return;
1156 bmp
->nb_colors
= colors
;
1158 if (coloruse
== DIB_RGB_COLORS
)
1160 memcpy( bmp
->color_table
, info
->bmiColors
, colors
* sizeof(RGBQUAD
));
1164 PALETTEENTRY entries
[256];
1165 const WORD
*index
= (const WORD
*)info
->bmiColors
;
1166 UINT count
= GetPaletteEntries( dc
->hPalette
, 0, colors
, entries
);
1168 for (i
= 0; i
< colors
; i
++, index
++)
1170 PALETTEENTRY
*entry
= &entries
[*index
% count
];
1171 bmp
->color_table
[i
].rgbRed
= entry
->peRed
;
1172 bmp
->color_table
[i
].rgbGreen
= entry
->peGreen
;
1173 bmp
->color_table
[i
].rgbBlue
= entry
->peBlue
;
1174 bmp
->color_table
[i
].rgbReserved
= 0;
1179 /***********************************************************************
1180 * CreateDIBSection (GDI32.@)
1182 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, CONST BITMAPINFO
*bmi
, UINT usage
,
1183 VOID
**bits
, HANDLE section
, DWORD offset
)
1185 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1186 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1189 BOOL bDesktopDC
= FALSE
;
1192 void *mapBits
= NULL
;
1194 if (bits
) *bits
= NULL
;
1195 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1196 if (info
->bmiHeader
.biPlanes
!= 1)
1198 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1199 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1202 if (!(dib
= HeapAlloc( GetProcessHeap(), 0, sizeof(*dib
) ))) return 0;
1204 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1205 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1206 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1207 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1208 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1210 dib
->dsBm
.bmType
= 0;
1211 dib
->dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1212 dib
->dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1213 dib
->dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1214 dib
->dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1215 dib
->dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1216 dib
->dsBm
.bmBits
= NULL
;
1217 dib
->dsBmih
= info
->bmiHeader
;
1219 /* set number of entries in bmi.bmiColors table */
1220 if( info
->bmiHeader
.biBitCount
<= 8 )
1221 dib
->dsBmih
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1223 /* set dsBitfields values */
1224 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1226 dib
->dsBmih
.biCompression
= BI_BITFIELDS
;
1227 dib
->dsBitfields
[0] = 0x7c00;
1228 dib
->dsBitfields
[1] = 0x03e0;
1229 dib
->dsBitfields
[2] = 0x001f;
1231 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1233 dib
->dsBitfields
[0] = *(const DWORD
*)bmi
->bmiColors
;
1234 dib
->dsBitfields
[1] = *((const DWORD
*)bmi
->bmiColors
+ 1);
1235 dib
->dsBitfields
[2] = *((const DWORD
*)bmi
->bmiColors
+ 2);
1236 if (!dib
->dsBitfields
[0] || !dib
->dsBitfields
[1] || !dib
->dsBitfields
[2]) goto error
;
1238 else dib
->dsBitfields
[0] = dib
->dsBitfields
[1] = dib
->dsBitfields
[2] = 0;
1240 /* get storage location for DIB bits */
1244 SYSTEM_INFO SystemInfo
;
1248 GetSystemInfo( &SystemInfo
);
1249 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1250 mapSize
= dib
->dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1251 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1252 if (mapBits
) dib
->dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1257 dib
->dsBm
.bmBits
= VirtualAlloc( NULL
, dib
->dsBmih
.biSizeImage
,
1258 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1260 dib
->dshSection
= section
;
1261 dib
->dsOffset
= offset
;
1263 if (!dib
->dsBm
.bmBits
)
1265 HeapFree( GetProcessHeap(), 0, dib
);
1269 /* If the reference hdc is null, take the desktop dc */
1272 hdc
= CreateCompatibleDC(0);
1276 if (!(dc
= get_dc_ptr( hdc
))) goto error
;
1278 /* create Device Dependent Bitmap and add DIB pointer */
1279 ret
= CreateBitmap( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmHeight
, 1,
1280 (info
->bmiHeader
.biBitCount
== 1) ? 1 : GetDeviceCaps(hdc
, BITSPIXEL
), NULL
);
1282 if (ret
&& ((bmp
= GDI_GetObjPtr(ret
, OBJ_BITMAP
))))
1284 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pCreateDIBSection
);
1286 bmp
->funcs
= physdev
->funcs
;
1287 /* create local copy of DIB palette */
1288 if (info
->bmiHeader
.biBitCount
<= 8) DIB_CopyColorTable( dc
, bmp
, usage
, info
);
1289 GDI_ReleaseObj( ret
);
1291 if (!physdev
->funcs
->pCreateDIBSection( physdev
, ret
, info
, usage
))
1293 DeleteObject( ret
);
1298 release_dc_ptr( dc
);
1299 if (bDesktopDC
) DeleteDC( hdc
);
1300 if (ret
&& bits
) *bits
= dib
->dsBm
.bmBits
;
1304 if (bDesktopDC
) DeleteDC( hdc
);
1305 if (section
) UnmapViewOfFile( mapBits
);
1306 else if (!offset
) VirtualFree( dib
->dsBm
.bmBits
, 0, MEM_RELEASE
);
1307 HeapFree( GetProcessHeap(), 0, dib
);