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 (dst
->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;
206 dst
->bmiHeader
.biClrUsed
= colors
;
211 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
213 PALETTEENTRY palEntry
[256];
214 HPALETTE palette
= GetCurrentObject( hdc
, OBJ_PAL
);
215 int i
, colors
= get_dib_num_of_colors( info
);
217 if (!palette
) return 0;
218 if (!colors
) return 0;
220 memset( palEntry
, 0, sizeof(palEntry
) );
221 if (!GetPaletteEntries( palette
, 0, colors
, palEntry
))
224 for (i
= 0; i
< colors
; i
++)
226 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
227 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
228 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
229 info
->bmiColors
[i
].rgbReserved
= 0;
235 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
237 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
238 const int bpp
= info
->bmiHeader
.biBitCount
;
241 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
243 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
246 static BOOL
build_rle_bitmap( const BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
250 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
252 BYTE skip
, num
, data
;
253 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
257 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
259 out_bits
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
) );
260 *clip
= CreateRectRgn( 0, 0, 0, 0 );
261 run
= CreateRectRgn( 0, 0, 0, 0 );
262 if (!out_bits
|| !*clip
|| !run
) goto fail
;
264 x
= left
= right
= 0;
267 while (i
< info
->bmiHeader
.biSizeImage
- 1)
270 data
= in_bits
[i
+ 1];
275 if (x
+ num
> width
) num
= width
- x
;
278 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
279 if (info
->bmiHeader
.biBitCount
== 8)
280 memset( out_ptr
, s
, num
);
285 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
286 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
291 /* this will write one too many if num is odd, but that doesn't matter */
292 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
304 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
305 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
310 left
= right
= x
= 0;
319 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
321 if (x
> width
) x
= width
;
328 else /* data bytes of data */
331 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
332 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
333 skip
= (skip
+ 1) & ~1;
334 if (x
+ num
> width
) num
= width
- x
;
337 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
338 if (info
->bmiHeader
.biBitCount
== 8)
339 memcpy( out_ptr
, in_bits
+ i
, num
);
344 const BYTE
*in_ptr
= in_bits
+ i
;
345 for ( ; num
; num
--, x
++)
349 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
353 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
357 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
369 if (bits
->free
) bits
->free( bits
);
371 bits
->ptr
= out_bits
;
372 bits
->is_copy
= TRUE
;
373 bits
->free
= free_heap_bits
;
378 if (run
) DeleteObject( run
);
379 if (*clip
) DeleteObject( *clip
);
380 HeapFree( GetProcessHeap(), 0, out_bits
);
386 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
387 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
388 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
389 BITMAPINFO
*info
, UINT coloruse
, DWORD rop
)
391 DC
*dc
= get_nulldrv_dc( dev
);
397 /* make sure we have a real implementation for StretchBlt and PutImage */
398 if (GET_DC_PHYSDEV( dc
, pStretchBlt
) == dev
|| GET_DC_PHYSDEV( dc
, pPutImage
) == dev
)
401 height
= info
->bmiHeader
.biHeight
;
403 if (xSrc
== 0 && ySrc
== 0 && widthDst
== widthSrc
&& heightDst
== heightSrc
&&
404 info
->bmiHeader
.biCompression
== BI_RGB
)
406 /* Windows appears to have a fast case optimization
407 * that uses the wrong origin for top-down DIBs */
408 if (height
< 0 && heightSrc
< abs(height
)) ySrc
= abs(height
) - heightSrc
;
410 if (xDst
== 0 && yDst
== 0 && info
->bmiHeader
.biCompression
== BI_RGB
&& rop
== SRCCOPY
)
413 hBitmap
= GetCurrentObject( dev
->hdc
, OBJ_BITMAP
);
414 if (GetObjectW( hBitmap
, sizeof(bm
), &bm
) &&
415 bm
.bmWidth
== widthSrc
&& bm
.bmHeight
== heightSrc
&&
416 bm
.bmBitsPixel
== info
->bmiHeader
.biBitCount
&& bm
.bmPlanes
== 1)
419 return SetDIBits( dev
->hdc
, hBitmap
, 0, abs( height
), bits
, info
, coloruse
);
424 hdcMem
= CreateCompatibleDC( dev
->hdc
);
425 hBitmap
= CreateCompatibleBitmap( dev
->hdc
, info
->bmiHeader
.biWidth
, height
);
426 SelectObject( hdcMem
, hBitmap
);
427 if (coloruse
== DIB_PAL_COLORS
)
428 SelectPalette( hdcMem
, GetCurrentObject( dev
->hdc
, OBJ_PAL
), FALSE
);
430 if (info
->bmiHeader
.biCompression
== BI_RLE4
|| info
->bmiHeader
.biCompression
== BI_RLE8
)
432 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
433 * contain all the rectangle described in bmiHeader, but only part of it.
434 * This mean that those undescribed pixels must be left untouched.
435 * So, we first copy on a memory bitmap the current content of the
436 * destination rectangle, blit the DIB bits on top of it - hence leaving
437 * the gaps untouched -, and blitting the rectangle back.
438 * This insure that gaps are untouched on the destination rectangle
440 StretchBlt( hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
, widthSrc
, heightSrc
,
441 dev
->hdc
, xDst
, yDst
, widthDst
, heightDst
, rop
);
443 ret
= SetDIBits( hdcMem
, hBitmap
, 0, abs( height
), bits
, info
, coloruse
);
444 if (ret
) StretchBlt( dev
->hdc
, xDst
, yDst
, widthDst
, heightDst
,
445 hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
, widthSrc
, heightSrc
, rop
);
447 DeleteObject( hBitmap
);
451 /***********************************************************************
452 * StretchDIBits (GDI32.@)
454 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
455 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
456 const BITMAPINFO
*bmi
, UINT coloruse
, DWORD rop
)
458 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
459 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
464 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
466 SetLastError( ERROR_INVALID_PARAMETER
);
470 if ((dc
= get_dc_ptr( hdc
)))
472 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
474 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
475 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
476 release_dc_ptr( dc
);
482 /******************************************************************************
483 * SetDIBits [GDI32.@]
485 * Sets pixels in a bitmap using colors from DIB.
488 * hdc [I] Handle to device context
489 * hbitmap [I] Handle to bitmap
490 * startscan [I] Starting scan line
491 * lines [I] Number of scan lines
492 * bits [I] Array of bitmap bits
493 * info [I] Address of structure with data
494 * coloruse [I] Type of color indexes to use
497 * Success: Number of scan lines copied
500 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
501 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
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_PAL_COLORS
&& !fill_color_table_from_palette( src_info
, hdc
)) return 0;
530 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
532 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
534 if (lines
== 0) goto done
;
535 else lines
= src_info
->bmiHeader
.biHeight
;
538 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
541 dst
.visrect
.left
= 0;
543 dst
.visrect
.right
= bitmap
->bitmap
.bmWidth
;
544 dst
.visrect
.bottom
= bitmap
->bitmap
.bmHeight
;
546 src
.visrect
.left
= 0;
548 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
549 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
551 if (src_info
->bmiHeader
.biHeight
> 0)
553 src_to_dst_offset
= -startscan
;
554 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
555 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
559 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
560 /* Unlike the bottom-up case, Windows doesn't limit lines. */
561 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
564 funcs
= get_bitmap_funcs( bitmap
);
568 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
569 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
570 src
.visrect
= dst
.visrect
;
571 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
573 src
.x
= src
.visrect
.left
;
574 src
.y
= src
.visrect
.top
;
575 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
576 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
578 dst
.x
= dst
.visrect
.left
;
579 dst
.y
= dst
.visrect
.top
;
580 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
581 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
583 memcpy( dst_info
, src_info
, FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] ));
585 err
= funcs
->pPutImage( NULL
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
586 if (err
== ERROR_BAD_FORMAT
)
590 dst_info
->bmiHeader
.biWidth
= dst
.width
;
591 ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info
));
594 err
= convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, ptr
);
595 if (src_bits
.free
) src_bits
.free( &src_bits
);
597 src_bits
.is_copy
= TRUE
;
598 src_bits
.free
= free_heap_bits
;
600 err
= funcs
->pPutImage( NULL
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
602 else err
= ERROR_OUTOFMEMORY
;
607 if (src_bits
.free
) src_bits
.free( &src_bits
);
608 if (clip
) DeleteObject( clip
);
609 GDI_ReleaseObj( hbitmap
);
614 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
615 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
616 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
618 DC
*dc
= get_nulldrv_dc( dev
);
619 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
620 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
621 struct bitblt_coords src
, dst
;
622 struct gdi_image_bits src_bits
;
630 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
631 height
= abs( src_info
->bmiHeader
.biHeight
);
633 src_bits
.ptr
= (void *)bits
;
634 src_bits
.is_copy
= FALSE
;
635 src_bits
.free
= NULL
;
637 if (!lines
) return 0;
638 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_palette( src_info
, dev
->hdc
)) return 0;
640 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
644 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
645 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
646 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
651 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
655 if (startscan
>= height
) return 0;
656 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
658 /* map src to top-down coordinates with startscan as origin */
660 src
.y
= startscan
+ lines
- (y_src
+ cy
);
667 /* get rid of unnecessary lines */
668 if (src
.y
>= lines
) return 0;
672 else if (src
.y
>= lines
) return lines
;
674 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
677 src
.visrect
.left
= src
.x
;
678 src
.visrect
.top
= src
.y
;
679 src
.visrect
.right
= src
.x
+ cx
;
680 src
.visrect
.bottom
= src
.y
+ cy
;
683 rect
.right
= src_info
->bmiHeader
.biWidth
;
684 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
685 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
693 LPtoDP( dev
->hdc
, &pt
, 1 );
698 if (GetLayout( dev
->hdc
) & LAYOUT_RTL
) dst
.x
-= cx
- 1;
700 dst
.visrect
.left
= dst
.x
;
701 dst
.visrect
.top
= dst
.y
;
702 dst
.visrect
.right
= dst
.x
+ cx
;
703 dst
.visrect
.bottom
= dst
.y
+ cy
;
704 if (get_clip_box( dc
, &rect
)) intersect_rect( &dst
.visrect
, &dst
.visrect
, &rect
);
706 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
707 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
708 src
.visrect
= dst
.visrect
= rect
;
709 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
710 if (is_rect_empty( &dst
.visrect
)) goto done
;
711 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
713 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
714 memcpy( dst_info
, src_info
, FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] ));
715 err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
716 if (err
== ERROR_BAD_FORMAT
)
720 dst_info
->bmiHeader
.biWidth
= src
.visrect
.right
- src
.visrect
.left
;
721 ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info
));
724 err
= convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, ptr
);
725 if (src_bits
.free
) src_bits
.free( &src_bits
);
727 src_bits
.is_copy
= TRUE
;
728 src_bits
.free
= free_heap_bits
;
729 if (!err
) err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
731 else err
= ERROR_OUTOFMEMORY
;
736 if (src_bits
.free
) src_bits
.free( &src_bits
);
737 if (clip
) DeleteObject( clip
);
741 /***********************************************************************
742 * SetDIBitsToDevice (GDI32.@)
744 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
745 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
746 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
749 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
750 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
755 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
757 SetLastError( ERROR_INVALID_PARAMETER
);
761 if ((dc
= get_dc_ptr( hdc
)))
763 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
765 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
766 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
767 release_dc_ptr( dc
);
772 /***********************************************************************
773 * SetDIBColorTable (GDI32.@)
775 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, CONST RGBQUAD
*colors
)
781 if (!(dc
= get_dc_ptr( hdc
))) return 0;
783 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
785 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBColorTable
);
787 /* Check if currently selected bitmap is a DIB */
788 if (bitmap
->color_table
)
790 if (startpos
< bitmap
->nb_colors
)
792 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
793 memcpy(bitmap
->color_table
+ startpos
, colors
, entries
* sizeof(RGBQUAD
));
797 GDI_ReleaseObj( dc
->hBitmap
);
798 physdev
->funcs
->pSetDIBColorTable( physdev
, startpos
, entries
, colors
);
800 release_dc_ptr( dc
);
805 /***********************************************************************
806 * GetDIBColorTable (GDI32.@)
808 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
814 if (!(dc
= get_dc_ptr( hdc
))) return 0;
816 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
818 /* Check if currently selected bitmap is a DIB */
819 if (bitmap
->color_table
)
821 if (startpos
< bitmap
->nb_colors
)
823 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
824 memcpy(colors
, bitmap
->color_table
+ startpos
, entries
* sizeof(RGBQUAD
));
828 GDI_ReleaseObj( dc
->hBitmap
);
830 release_dc_ptr( dc
);
834 static const RGBQUAD DefLogPaletteQuads
[20] = { /* Copy of Default Logical Palette */
835 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
836 { 0x00, 0x00, 0x00, 0x00 },
837 { 0x00, 0x00, 0x80, 0x00 },
838 { 0x00, 0x80, 0x00, 0x00 },
839 { 0x00, 0x80, 0x80, 0x00 },
840 { 0x80, 0x00, 0x00, 0x00 },
841 { 0x80, 0x00, 0x80, 0x00 },
842 { 0x80, 0x80, 0x00, 0x00 },
843 { 0xc0, 0xc0, 0xc0, 0x00 },
844 { 0xc0, 0xdc, 0xc0, 0x00 },
845 { 0xf0, 0xca, 0xa6, 0x00 },
846 { 0xf0, 0xfb, 0xff, 0x00 },
847 { 0xa4, 0xa0, 0xa0, 0x00 },
848 { 0x80, 0x80, 0x80, 0x00 },
849 { 0x00, 0x00, 0xff, 0x00 },
850 { 0x00, 0xff, 0x00, 0x00 },
851 { 0x00, 0xff, 0xff, 0x00 },
852 { 0xff, 0x00, 0x00, 0x00 },
853 { 0xff, 0x00, 0xff, 0x00 },
854 { 0xff, 0xff, 0x00, 0x00 },
855 { 0xff, 0xff, 0xff, 0x00 }
858 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
859 static const DWORD bit_fields_565
[3] = {0xf800, 0x07e0, 0x001f};
860 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
862 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
864 BITMAPINFOHEADER header
;
866 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
867 header
.biWidth
= bmp
->bitmap
.bmWidth
;
868 header
.biHeight
= bmp
->bitmap
.bmHeight
;
873 header
.biBitCount
= bmp
->dib
->dsBm
.bmBitsPixel
;
874 switch (bmp
->dib
->dsBm
.bmBitsPixel
)
878 header
.biCompression
= BI_BITFIELDS
;
881 header
.biCompression
= BI_RGB
;
887 header
.biCompression
= (bmp
->bitmap
.bmBitsPixel
> 8) ? BI_BITFIELDS
: BI_RGB
;
888 header
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
891 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
892 header
.biXPelsPerMeter
= 0;
893 header
.biYPelsPerMeter
= 0;
894 header
.biClrUsed
= 0;
895 header
.biClrImportant
= 0;
897 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
899 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
901 coreheader
->bcWidth
= header
.biWidth
;
902 coreheader
->bcHeight
= header
.biHeight
;
903 coreheader
->bcPlanes
= header
.biPlanes
;
904 coreheader
->bcBitCount
= header
.biBitCount
;
907 info
->bmiHeader
= header
;
909 return abs(bmp
->bitmap
.bmHeight
);
912 /************************************************************************
915 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
917 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
919 unsigned int colors
= get_dib_num_of_colors( src
);
920 RGBQUAD
*src_colors
= (RGBQUAD
*)((char *)src
+ src
->bmiHeader
.biSize
);
922 assert( src
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) );
924 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
926 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
927 if (coloruse
== DIB_PAL_COLORS
)
928 memcpy( core
->bmciColors
, src_colors
, colors
* sizeof(WORD
) );
932 for (i
= 0; i
< colors
; i
++)
934 core
->bmciColors
[i
].rgbtRed
= src_colors
[i
].rgbRed
;
935 core
->bmciColors
[i
].rgbtGreen
= src_colors
[i
].rgbGreen
;
936 core
->bmciColors
[i
].rgbtBlue
= src_colors
[i
].rgbBlue
;
942 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
943 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
945 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
946 /* bitfields are always at bmiColors even in larger structures */
947 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
950 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
953 if (coloruse
== DIB_PAL_COLORS
)
954 size
= colors
* sizeof(WORD
);
956 size
= colors
* sizeof(RGBQUAD
);
957 memcpy( colorptr
, src_colors
, size
);
962 static void fill_default_color_table( BITMAPINFO
*info
)
966 switch (info
->bmiHeader
.biBitCount
)
969 info
->bmiColors
[0].rgbRed
= info
->bmiColors
[0].rgbGreen
= info
->bmiColors
[0].rgbBlue
= 0;
970 info
->bmiColors
[0].rgbReserved
= 0;
971 info
->bmiColors
[1].rgbRed
= info
->bmiColors
[1].rgbGreen
= info
->bmiColors
[1].rgbBlue
= 0xff;
972 info
->bmiColors
[1].rgbReserved
= 0;
976 /* The EGA palette is the first and last 8 colours of the default palette
977 with the innermost pair swapped */
978 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 7 * sizeof(RGBQUAD
));
979 memcpy(info
->bmiColors
+ 7, DefLogPaletteQuads
+ 12, 1 * sizeof(RGBQUAD
));
980 memcpy(info
->bmiColors
+ 8, DefLogPaletteQuads
+ 7, 1 * sizeof(RGBQUAD
));
981 memcpy(info
->bmiColors
+ 9, DefLogPaletteQuads
+ 13, 7 * sizeof(RGBQUAD
));
985 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 10 * sizeof(RGBQUAD
));
986 memcpy(info
->bmiColors
+ 246, DefLogPaletteQuads
+ 10, 10 * sizeof(RGBQUAD
));
987 for (i
= 10; i
< 246; i
++)
989 info
->bmiColors
[i
].rgbRed
= (i
& 0x07) << 5;
990 info
->bmiColors
[i
].rgbGreen
= (i
& 0x38) << 2;
991 info
->bmiColors
[i
].rgbBlue
= i
& 0xc0;
992 info
->bmiColors
[i
].rgbReserved
= 0;
997 ERR("called with bitcount %d\n", info
->bmiHeader
.biBitCount
);
999 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1002 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1004 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1005 info
->bmiHeader
.biWidth
= bmp
->bitmap
.bmWidth
;
1006 info
->bmiHeader
.biHeight
= -bmp
->bitmap
.bmHeight
;
1007 info
->bmiHeader
.biPlanes
= 1;
1008 info
->bmiHeader
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
1009 info
->bmiHeader
.biCompression
= BI_RGB
;
1010 info
->bmiHeader
.biXPelsPerMeter
= 0;
1011 info
->bmiHeader
.biYPelsPerMeter
= 0;
1012 info
->bmiHeader
.biClrUsed
= 0;
1013 info
->bmiHeader
.biClrImportant
= 0;
1014 if (info
->bmiHeader
.biBitCount
<= 8) fill_default_color_table( info
);
1018 /******************************************************************************
1019 * GetDIBits [GDI32.@]
1021 * Retrieves bits of bitmap and copies to buffer.
1024 * Success: Number of scan lines copied from bitmap
1027 INT WINAPI
GetDIBits(
1028 HDC hdc
, /* [in] Handle to device context */
1029 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1030 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1031 UINT lines
, /* [in] Number of scan lines to copy */
1032 LPVOID bits
, /* [out] Address of array for bitmap bits */
1033 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1034 UINT coloruse
) /* [in] RGB or palette index */
1038 int i
, dst_to_src_offset
, ret
= 0;
1040 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1041 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1042 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1043 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1044 const struct gdi_dc_funcs
*funcs
;
1045 struct gdi_image_bits src_bits
;
1046 struct bitblt_coords src
, dst
;
1047 BOOL empty_rect
= FALSE
;
1049 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1050 own copy and transfer the colour info back at the end */
1051 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1053 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1055 dst_info
->bmiHeader
.biClrUsed
= 0;
1056 dst_info
->bmiHeader
.biClrImportant
= 0;
1058 if (!(dc
= get_dc_ptr( hdc
)))
1060 SetLastError( ERROR_INVALID_PARAMETER
);
1064 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1066 release_dc_ptr( dc
);
1070 funcs
= get_bitmap_funcs( bmp
);
1072 src
.visrect
.left
= 0;
1073 src
.visrect
.top
= 0;
1074 src
.visrect
.right
= bmp
->bitmap
.bmWidth
;
1075 src
.visrect
.bottom
= bmp
->bitmap
.bmHeight
;
1077 dst
.visrect
.left
= 0;
1078 dst
.visrect
.top
= 0;
1079 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1080 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1082 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1085 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1087 ret
= fill_query_info( info
, bmp
);
1091 /* validate parameters */
1093 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1094 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1096 switch (dst_info
->bmiHeader
.biCompression
)
1099 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1100 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1101 if (bits
) goto done
; /* can't retrieve compressed bits */
1104 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1105 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1106 if (bits
) goto done
; /* can't retrieve compressed bits */
1109 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1112 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1113 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1114 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1115 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1116 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1117 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1118 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1126 if (dst_info
->bmiHeader
.biHeight
> 0)
1128 dst_to_src_offset
= -startscan
;
1129 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1130 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1134 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1135 if (dst_to_src_offset
< 0)
1137 dst_to_src_offset
= 0;
1138 lines
= dst
.visrect
.bottom
- startscan
;
1140 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1143 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1144 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1145 dst
.visrect
= src
.visrect
;
1146 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1148 if (dst_info
->bmiHeader
.biHeight
> 0)
1150 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1152 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1153 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1154 memset( bits
, 0, pad_bytes
);
1155 bits
= (char *)bits
+ pad_bytes
;
1160 if (dst
.visrect
.bottom
< lines
)
1162 int pad_lines
= lines
- dst
.visrect
.bottom
;
1163 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1164 int pad_bytes
= pad_lines
* stride
;
1165 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1169 if (empty_rect
) bits
= NULL
;
1171 src
.x
= src
.visrect
.left
;
1172 src
.y
= src
.visrect
.top
;
1173 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1174 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1179 err
= funcs
->pGetImage( NULL
, hbitmap
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1183 /* fill out the src colour table, if it needs one */
1184 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1185 fill_default_color_table( src_info
);
1187 /* if the src and dst are the same depth, copy the colour info across */
1188 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1190 switch (src_info
->bmiHeader
.biBitCount
)
1193 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1195 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1196 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1200 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1202 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1203 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1207 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1208 copy_color_info( dst_info
, src_info
, coloruse
);
1210 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1212 if( coloruse
== DIB_PAL_COLORS
)
1214 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1218 fill_default_color_table( dst_info
);
1224 if(dst_info
->bmiHeader
.biHeight
> 0)
1225 dst_info
->bmiHeader
.biHeight
= src
.height
;
1227 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1229 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
);
1230 if (src_bits
.free
) src_bits
.free( &src_bits
);
1234 ret
= empty_rect
? FALSE
: TRUE
;
1236 if (coloruse
== DIB_PAL_COLORS
)
1238 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1239 int colors
= get_dib_num_of_colors( dst_info
);
1240 for (i
= 0; i
< colors
; i
++, index
++)
1244 copy_color_info( info
, dst_info
, coloruse
);
1247 release_dc_ptr( dc
);
1248 GDI_ReleaseObj( hbitmap
);
1253 /***********************************************************************
1254 * CreateDIBitmap (GDI32.@)
1256 * Creates a DDB (device dependent bitmap) from a DIB.
1257 * The DDB will have the same color depth as the reference DC.
1259 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1260 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1263 BITMAPINFOHEADER info
;
1267 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1268 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1269 if (info
.biWidth
< 0) return 0;
1271 /* Top-down DIBs have a negative height */
1272 height
= abs( info
.biHeight
);
1274 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1275 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1276 info
.biBitCount
, info
.biCompression
);
1279 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1281 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1285 if (init
& CBM_INIT
)
1287 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1289 DeleteObject( handle
);
1298 /* Copy/synthesize RGB palette from BITMAPINFO */
1299 static void DIB_CopyColorTable( DC
*dc
, BITMAPOBJ
*bmp
, WORD coloruse
, const BITMAPINFO
*info
)
1301 unsigned int colors
, i
;
1303 colors
= get_dib_num_of_colors( info
);
1304 if (!(bmp
->color_table
= HeapAlloc(GetProcessHeap(), 0, colors
* sizeof(RGBQUAD
) ))) return;
1305 bmp
->nb_colors
= colors
;
1307 if (coloruse
== DIB_RGB_COLORS
)
1309 memcpy( bmp
->color_table
, info
->bmiColors
, colors
* sizeof(RGBQUAD
));
1313 PALETTEENTRY entries
[256];
1314 const WORD
*index
= (const WORD
*)info
->bmiColors
;
1315 UINT count
= GetPaletteEntries( dc
->hPalette
, 0, colors
, entries
);
1317 for (i
= 0; i
< colors
; i
++, index
++)
1319 PALETTEENTRY
*entry
= &entries
[*index
% count
];
1320 bmp
->color_table
[i
].rgbRed
= entry
->peRed
;
1321 bmp
->color_table
[i
].rgbGreen
= entry
->peGreen
;
1322 bmp
->color_table
[i
].rgbBlue
= entry
->peBlue
;
1323 bmp
->color_table
[i
].rgbReserved
= 0;
1328 /***********************************************************************
1329 * CreateDIBSection (GDI32.@)
1331 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, CONST BITMAPINFO
*bmi
, UINT usage
,
1332 VOID
**bits
, HANDLE section
, DWORD offset
)
1334 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1335 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1338 BOOL bDesktopDC
= FALSE
;
1341 void *mapBits
= NULL
;
1343 if (bits
) *bits
= NULL
;
1344 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1345 if (info
->bmiHeader
.biPlanes
!= 1)
1347 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1348 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1351 if (!(dib
= HeapAlloc( GetProcessHeap(), 0, sizeof(*dib
) ))) return 0;
1353 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1354 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1355 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1356 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1357 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1359 dib
->dsBm
.bmType
= 0;
1360 dib
->dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1361 dib
->dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1362 dib
->dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1363 dib
->dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1364 dib
->dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1365 dib
->dsBm
.bmBits
= NULL
;
1366 dib
->dsBmih
= info
->bmiHeader
;
1368 /* set number of entries in bmi.bmiColors table */
1369 if( info
->bmiHeader
.biBitCount
<= 8 )
1370 dib
->dsBmih
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1372 /* set dsBitfields values */
1373 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1375 dib
->dsBmih
.biCompression
= BI_BITFIELDS
;
1376 dib
->dsBitfields
[0] = 0x7c00;
1377 dib
->dsBitfields
[1] = 0x03e0;
1378 dib
->dsBitfields
[2] = 0x001f;
1380 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1382 dib
->dsBitfields
[0] = *(const DWORD
*)bmi
->bmiColors
;
1383 dib
->dsBitfields
[1] = *((const DWORD
*)bmi
->bmiColors
+ 1);
1384 dib
->dsBitfields
[2] = *((const DWORD
*)bmi
->bmiColors
+ 2);
1385 if (!dib
->dsBitfields
[0] || !dib
->dsBitfields
[1] || !dib
->dsBitfields
[2]) goto error
;
1387 else dib
->dsBitfields
[0] = dib
->dsBitfields
[1] = dib
->dsBitfields
[2] = 0;
1389 /* get storage location for DIB bits */
1393 SYSTEM_INFO SystemInfo
;
1397 GetSystemInfo( &SystemInfo
);
1398 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1399 mapSize
= dib
->dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1400 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1401 if (mapBits
) dib
->dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1406 dib
->dsBm
.bmBits
= VirtualAlloc( NULL
, dib
->dsBmih
.biSizeImage
,
1407 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1409 dib
->dshSection
= section
;
1410 dib
->dsOffset
= offset
;
1412 if (!dib
->dsBm
.bmBits
)
1414 HeapFree( GetProcessHeap(), 0, dib
);
1418 /* If the reference hdc is null, take the desktop dc */
1421 hdc
= CreateCompatibleDC(0);
1425 if (!(dc
= get_dc_ptr( hdc
))) goto error
;
1427 /* create Device Dependent Bitmap and add DIB pointer */
1428 ret
= CreateBitmap( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmHeight
, 1,
1429 (info
->bmiHeader
.biBitCount
== 1) ? 1 : GetDeviceCaps(hdc
, BITSPIXEL
), NULL
);
1431 if (ret
&& ((bmp
= GDI_GetObjPtr(ret
, OBJ_BITMAP
))))
1433 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pCreateDIBSection
);
1435 bmp
->funcs
= physdev
->funcs
;
1436 /* create local copy of DIB palette */
1437 if (info
->bmiHeader
.biBitCount
<= 8) DIB_CopyColorTable( dc
, bmp
, usage
, info
);
1438 GDI_ReleaseObj( ret
);
1440 if (!physdev
->funcs
->pCreateDIBSection( physdev
, ret
, info
, usage
))
1442 DeleteObject( ret
);
1447 release_dc_ptr( dc
);
1448 if (bDesktopDC
) DeleteDC( hdc
);
1449 if (ret
&& bits
) *bits
= dib
->dsBm
.bmBits
;
1453 if (bDesktopDC
) DeleteDC( hdc
);
1454 if (section
) UnmapViewOfFile( mapBits
);
1455 else if (!offset
) VirtualFree( dib
->dsBm
.bmBits
, 0, MEM_RELEASE
);
1456 HeapFree( GetProcessHeap(), 0, dib
);