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
)
176 if (!bitmapinfoheader_from_user_bitmapinfo( &dst
->bmiHeader
, &info
->bmiHeader
)) return FALSE
;
177 if (!is_valid_dib_format( &dst
->bmiHeader
, allow_compression
)) return FALSE
;
179 src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
181 if (dst
->bmiHeader
.biCompression
== BI_BITFIELDS
)
183 /* bitfields are always at bmiColors even in larger structures */
184 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
185 dst
->bmiHeader
.biClrUsed
= 0;
187 else if (dst
->bmiHeader
.biBitCount
<= 8)
189 unsigned int colors
= dst
->bmiHeader
.biClrUsed
;
190 unsigned int max_colors
= 1 << dst
->bmiHeader
.biBitCount
;
192 if (!colors
) colors
= max_colors
;
193 else colors
= min( colors
, max_colors
);
195 if (coloruse
== DIB_PAL_COLORS
)
197 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
200 else if (info
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
))
202 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(RGBQUAD
) );
207 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
208 for (i
= 0; i
< colors
; i
++)
210 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
211 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
212 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
213 dst
->bmiColors
[i
].rgbReserved
= 0;
216 memset( dst
->bmiColors
+ colors
, 0, (max_colors
- colors
) * sizeof(RGBQUAD
) );
217 dst
->bmiHeader
.biClrUsed
= max_colors
;
219 else dst
->bmiHeader
.biClrUsed
= 0;
224 static int fill_color_table_from_palette( BITMAPINFO
*info
, HDC hdc
)
226 PALETTEENTRY palEntry
[256];
227 HPALETTE palette
= GetCurrentObject( hdc
, OBJ_PAL
);
228 int i
, colors
= get_dib_num_of_colors( info
);
230 if (!palette
) return 0;
231 if (!colors
) return 0;
233 memset( palEntry
, 0, sizeof(palEntry
) );
234 if (!GetPaletteEntries( palette
, 0, colors
, palEntry
))
237 for (i
= 0; i
< colors
; i
++)
239 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
240 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
241 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
242 info
->bmiColors
[i
].rgbReserved
= 0;
248 int fill_color_table_from_pal_colors( HDC hdc
, const BITMAPINFO
*info
, RGBQUAD
*color_table
)
250 PALETTEENTRY entries
[256];
253 const WORD
*index
= (const WORD
*)info
->bmiColors
;
254 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
256 if (!colors
) return 0;
257 if (!(palette
= GetCurrentObject( hdc
, OBJ_PAL
))) return 0;
258 if (!(count
= GetPaletteEntries( palette
, 0, colors
, entries
))) return 0;
260 for (i
= 0; i
< colors
; i
++, index
++)
262 table
[i
].rgbRed
= entries
[*index
% count
].peRed
;
263 table
[i
].rgbGreen
= entries
[*index
% count
].peGreen
;
264 table
[i
].rgbBlue
= entries
[*index
% count
].peBlue
;
265 table
[i
].rgbReserved
= 0;
267 memcpy( color_table
, table
, colors
* sizeof(RGBQUAD
) );
268 memset( color_table
+ colors
, 0, ((1 << info
->bmiHeader
.biBitCount
) - colors
) * sizeof(RGBQUAD
) );
272 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
274 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
275 const int bpp
= info
->bmiHeader
.biBitCount
;
278 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
280 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
283 static BOOL
build_rle_bitmap( const BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
287 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
289 BYTE skip
, num
, data
;
290 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
292 if (clip
) *clip
= NULL
;
294 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
296 out_bits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, get_dib_image_size( info
) );
297 if (!out_bits
) goto fail
;
301 *clip
= CreateRectRgn( 0, 0, 0, 0 );
302 run
= CreateRectRgn( 0, 0, 0, 0 );
303 if (!*clip
|| !run
) goto fail
;
306 x
= left
= right
= 0;
309 while (i
< info
->bmiHeader
.biSizeImage
- 1)
312 data
= in_bits
[i
+ 1];
317 if (x
+ num
> width
) num
= width
- x
;
320 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
321 if (info
->bmiHeader
.biBitCount
== 8)
322 memset( out_ptr
, s
, num
);
327 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
328 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
333 /* this will write one too many if num is odd, but that doesn't matter */
334 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
344 if(left
!= right
&& clip
)
346 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
347 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
352 left
= right
= x
= 0;
361 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
363 if (x
> width
) x
= width
;
370 else /* data bytes of data */
373 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
374 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
375 skip
= (skip
+ 1) & ~1;
376 if (x
+ num
> width
) num
= width
- x
;
379 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
380 if (info
->bmiHeader
.biBitCount
== 8)
381 memcpy( out_ptr
, in_bits
+ i
, num
);
386 const BYTE
*in_ptr
= in_bits
+ i
;
387 for ( ; num
; num
--, x
++)
391 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
395 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
399 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
410 if (run
) DeleteObject( run
);
411 if (bits
->free
) bits
->free( bits
);
413 bits
->ptr
= out_bits
;
414 bits
->is_copy
= TRUE
;
415 bits
->free
= free_heap_bits
;
420 if (run
) DeleteObject( run
);
421 if (clip
&& *clip
) DeleteObject( *clip
);
422 HeapFree( GetProcessHeap(), 0, out_bits
);
428 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
429 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
430 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
432 DC
*dc
= get_nulldrv_dc( dev
);
433 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
434 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
435 struct bitblt_coords src
, dst
;
436 struct gdi_image_bits src_bits
;
440 INT height
= abs( src_info
->bmiHeader
.biHeight
);
441 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
444 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
445 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
447 src_bits
.ptr
= (void*)bits
;
448 src_bits
.is_copy
= FALSE
;
449 src_bits
.free
= NULL
;
451 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_palette( src_info
, dev
->hdc
)) return 0;
455 rect
.right
= xDst
+ widthDst
;
456 rect
.bottom
= yDst
+ heightDst
;
457 LPtoDP( dc
->hSelf
, (POINT
*)&rect
, 2 );
460 dst
.width
= rect
.right
- rect
.left
;
461 dst
.height
= rect
.bottom
- rect
.top
;
463 if (dc
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
466 dst
.width
= -dst
.width
;
468 rop
&= ~NOMIRRORBITMAP
;
471 src
.width
= widthSrc
;
473 src
.height
= heightSrc
;
475 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
476 non_stretch_from_origin
= TRUE
;
478 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
480 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
481 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
484 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
486 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
487 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
492 if (dst
.width
< 0 && dst
.width
== src
.width
)
494 /* This is off-by-one, but that's what Windows does */
497 dst
.width
= -dst
.width
;
498 src
.width
= -src
.width
;
500 if (dst
.height
< 0 && dst
.height
== src
.height
)
504 dst
.height
= -dst
.height
;
505 src
.height
= -src
.height
;
509 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
511 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
513 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
514 src
.y
= -src
.height
- 1;
516 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
518 src
.visrect
.left
= 0;
519 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
521 src
.visrect
.bottom
= height
;
522 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
524 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
526 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
528 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
530 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
532 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
533 copy_bitmapinfo( dst_info
, src_info
);
534 err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
535 if (err
== ERROR_BAD_FORMAT
)
537 /* 1-bpp destination without a color table requires a fake 1-entry table
538 * that contains only the background color */
539 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_info
->bmiHeader
.biClrUsed
)
541 COLORREF color
= GetBkColor( dev
->hdc
);
542 dst_info
->bmiColors
[0].rgbRed
= GetRValue( color
);
543 dst_info
->bmiColors
[0].rgbGreen
= GetGValue( color
);
544 dst_info
->bmiColors
[0].rgbBlue
= GetBValue( color
);
545 dst_info
->bmiColors
[0].rgbReserved
= 0;
546 dst_info
->bmiHeader
.biClrUsed
= 1;
549 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
, FALSE
)))
551 /* get rid of the fake 1-bpp table */
552 if (dst_info
->bmiHeader
.biClrUsed
== 1) dst_info
->bmiHeader
.biClrUsed
= 0;
553 err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
557 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
559 copy_bitmapinfo( src_info
, dst_info
);
560 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, GetStretchBltMode( dev
->hdc
) );
561 if (!err
) err
= dev
->funcs
->pPutImage( dev
, 0, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
564 else if (rop
== SRCCOPY
) ret
= height
;
565 else ret
= src_info
->bmiHeader
.biHeight
;
568 if (src_bits
.free
) src_bits
.free( &src_bits
);
569 if (clip
) DeleteObject( clip
);
573 /***********************************************************************
574 * StretchDIBits (GDI32.@)
576 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
577 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
578 const BITMAPINFO
*bmi
, UINT coloruse
, DWORD rop
)
580 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
581 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
586 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
588 SetLastError( ERROR_INVALID_PARAMETER
);
592 if ((dc
= get_dc_ptr( hdc
)))
594 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
596 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
597 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
598 release_dc_ptr( dc
);
604 /******************************************************************************
605 * SetDIBits [GDI32.@]
607 * Sets pixels in a bitmap using colors from DIB.
610 * hdc [I] Handle to device context
611 * hbitmap [I] Handle to bitmap
612 * startscan [I] Starting scan line
613 * lines [I] Number of scan lines
614 * bits [I] Array of bitmap bits
615 * info [I] Address of structure with data
616 * coloruse [I] Type of color indexes to use
619 * Success: Number of scan lines copied
622 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
623 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
627 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
628 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
629 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
630 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
633 struct gdi_image_bits src_bits
;
634 struct bitblt_coords src
, dst
;
635 INT src_to_dst_offset
;
637 const struct gdi_dc_funcs
*funcs
;
639 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
))
641 SetLastError( ERROR_INVALID_PARAMETER
);
644 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
646 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
647 if (!masks
[0] || !masks
[1] || !masks
[2])
649 SetLastError( ERROR_INVALID_PARAMETER
);
654 src_bits
.ptr
= (void *)bits
;
655 src_bits
.is_copy
= FALSE
;
656 src_bits
.free
= NULL
;
657 src_bits
.param
= NULL
;
659 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_palette( src_info
, hdc
)) return 0;
661 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
663 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
665 if (lines
== 0) goto done
;
666 else lines
= src_info
->bmiHeader
.biHeight
;
669 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
672 dst
.visrect
.left
= 0;
674 dst
.visrect
.right
= bitmap
->bitmap
.bmWidth
;
675 dst
.visrect
.bottom
= bitmap
->bitmap
.bmHeight
;
677 src
.visrect
.left
= 0;
679 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
680 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
682 if (src_info
->bmiHeader
.biHeight
> 0)
684 src_to_dst_offset
= -startscan
;
685 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
686 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
690 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
691 /* Unlike the bottom-up case, Windows doesn't limit lines. */
692 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
695 funcs
= get_bitmap_funcs( bitmap
);
699 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
700 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
701 src
.visrect
= dst
.visrect
;
702 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
704 src
.x
= src
.visrect
.left
;
705 src
.y
= src
.visrect
.top
;
706 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
707 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
709 dst
.x
= dst
.visrect
.left
;
710 dst
.y
= dst
.visrect
.top
;
711 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
712 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
714 copy_bitmapinfo( dst_info
, src_info
);
716 err
= funcs
->pPutImage( NULL
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
717 if (err
== ERROR_BAD_FORMAT
)
719 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
, FALSE
);
720 if (!err
) err
= funcs
->pPutImage( NULL
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
725 if (src_bits
.free
) src_bits
.free( &src_bits
);
726 if (clip
) DeleteObject( clip
);
727 GDI_ReleaseObj( hbitmap
);
732 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
733 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
734 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
736 DC
*dc
= get_nulldrv_dc( dev
);
737 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
738 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
739 struct bitblt_coords src
, dst
;
740 struct gdi_image_bits src_bits
;
748 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
749 height
= abs( src_info
->bmiHeader
.biHeight
);
751 src_bits
.ptr
= (void *)bits
;
752 src_bits
.is_copy
= FALSE
;
753 src_bits
.free
= NULL
;
755 if (!lines
) return 0;
756 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_palette( src_info
, dev
->hdc
)) return 0;
758 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
762 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
763 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
764 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
769 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
773 if (startscan
>= height
) return 0;
774 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
776 /* map src to top-down coordinates with startscan as origin */
778 src
.y
= startscan
+ lines
- (y_src
+ cy
);
785 /* get rid of unnecessary lines */
786 if (src
.y
>= lines
) return 0;
790 else if (src
.y
>= lines
) return lines
;
792 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
795 src
.visrect
.left
= src
.x
;
796 src
.visrect
.top
= src
.y
;
797 src
.visrect
.right
= src
.x
+ cx
;
798 src
.visrect
.bottom
= src
.y
+ cy
;
801 rect
.right
= src_info
->bmiHeader
.biWidth
;
802 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
803 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
811 LPtoDP( dev
->hdc
, &pt
, 1 );
816 if (GetLayout( dev
->hdc
) & LAYOUT_RTL
) dst
.x
-= cx
- 1;
820 rect
.right
= dst
.x
+ cx
;
821 rect
.bottom
= dst
.y
+ cy
;
822 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
824 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
825 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
826 src
.visrect
= dst
.visrect
= rect
;
827 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
828 if (is_rect_empty( &dst
.visrect
)) goto done
;
829 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
831 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
832 copy_bitmapinfo( dst_info
, src_info
);
833 err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
834 if (err
== ERROR_BAD_FORMAT
)
836 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
, FALSE
);
837 if (!err
) err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
842 if (src_bits
.free
) src_bits
.free( &src_bits
);
843 if (clip
) DeleteObject( clip
);
847 /***********************************************************************
848 * SetDIBitsToDevice (GDI32.@)
850 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
851 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
852 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
855 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
856 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
861 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
863 SetLastError( ERROR_INVALID_PARAMETER
);
867 if ((dc
= get_dc_ptr( hdc
)))
869 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
871 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
872 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
873 release_dc_ptr( dc
);
878 /***********************************************************************
879 * SetDIBColorTable (GDI32.@)
881 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, CONST RGBQUAD
*colors
)
887 if (!(dc
= get_dc_ptr( hdc
))) return 0;
889 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
891 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBColorTable
);
893 /* Check if currently selected bitmap is a DIB */
894 if (bitmap
->color_table
)
896 if (startpos
< bitmap
->nb_colors
)
898 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
899 memcpy(bitmap
->color_table
+ startpos
, colors
, entries
* sizeof(RGBQUAD
));
903 GDI_ReleaseObj( dc
->hBitmap
);
904 physdev
->funcs
->pSetDIBColorTable( physdev
, startpos
, entries
, colors
);
906 release_dc_ptr( dc
);
911 /***********************************************************************
912 * GetDIBColorTable (GDI32.@)
914 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
920 if (!(dc
= get_dc_ptr( hdc
))) return 0;
922 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
924 /* Check if currently selected bitmap is a DIB */
925 if (bitmap
->color_table
)
927 if (startpos
< bitmap
->nb_colors
)
929 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
930 memcpy(colors
, bitmap
->color_table
+ startpos
, entries
* sizeof(RGBQUAD
));
934 GDI_ReleaseObj( dc
->hBitmap
);
936 release_dc_ptr( dc
);
940 static const RGBQUAD DefLogPaletteQuads
[20] = { /* Copy of Default Logical Palette */
941 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
942 { 0x00, 0x00, 0x00, 0x00 },
943 { 0x00, 0x00, 0x80, 0x00 },
944 { 0x00, 0x80, 0x00, 0x00 },
945 { 0x00, 0x80, 0x80, 0x00 },
946 { 0x80, 0x00, 0x00, 0x00 },
947 { 0x80, 0x00, 0x80, 0x00 },
948 { 0x80, 0x80, 0x00, 0x00 },
949 { 0xc0, 0xc0, 0xc0, 0x00 },
950 { 0xc0, 0xdc, 0xc0, 0x00 },
951 { 0xf0, 0xca, 0xa6, 0x00 },
952 { 0xf0, 0xfb, 0xff, 0x00 },
953 { 0xa4, 0xa0, 0xa0, 0x00 },
954 { 0x80, 0x80, 0x80, 0x00 },
955 { 0x00, 0x00, 0xff, 0x00 },
956 { 0x00, 0xff, 0x00, 0x00 },
957 { 0x00, 0xff, 0xff, 0x00 },
958 { 0xff, 0x00, 0x00, 0x00 },
959 { 0xff, 0x00, 0xff, 0x00 },
960 { 0xff, 0xff, 0x00, 0x00 },
961 { 0xff, 0xff, 0xff, 0x00 }
964 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
965 static const DWORD bit_fields_565
[3] = {0xf800, 0x07e0, 0x001f};
966 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
968 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
970 BITMAPINFOHEADER header
;
972 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
973 header
.biWidth
= bmp
->bitmap
.bmWidth
;
974 header
.biHeight
= bmp
->bitmap
.bmHeight
;
979 header
.biBitCount
= bmp
->dib
->dsBm
.bmBitsPixel
;
980 switch (bmp
->dib
->dsBm
.bmBitsPixel
)
984 header
.biCompression
= BI_BITFIELDS
;
987 header
.biCompression
= BI_RGB
;
993 header
.biCompression
= (bmp
->bitmap
.bmBitsPixel
> 8) ? BI_BITFIELDS
: BI_RGB
;
994 header
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
997 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
998 header
.biXPelsPerMeter
= 0;
999 header
.biYPelsPerMeter
= 0;
1000 header
.biClrUsed
= 0;
1001 header
.biClrImportant
= 0;
1003 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
1005 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
1007 coreheader
->bcWidth
= header
.biWidth
;
1008 coreheader
->bcHeight
= header
.biHeight
;
1009 coreheader
->bcPlanes
= header
.biPlanes
;
1010 coreheader
->bcBitCount
= header
.biBitCount
;
1013 info
->bmiHeader
= header
;
1015 return abs(bmp
->bitmap
.bmHeight
);
1018 /************************************************************************
1021 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1023 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1025 unsigned int colors
= get_dib_num_of_colors( src
);
1026 RGBQUAD
*src_colors
= (RGBQUAD
*)((char *)src
+ src
->bmiHeader
.biSize
);
1028 assert( src
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) );
1030 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1032 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1033 if (coloruse
== DIB_PAL_COLORS
)
1034 memcpy( core
->bmciColors
, src_colors
, colors
* sizeof(WORD
) );
1038 for (i
= 0; i
< colors
; i
++)
1040 core
->bmciColors
[i
].rgbtRed
= src_colors
[i
].rgbRed
;
1041 core
->bmciColors
[i
].rgbtGreen
= src_colors
[i
].rgbGreen
;
1042 core
->bmciColors
[i
].rgbtBlue
= src_colors
[i
].rgbBlue
;
1048 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1049 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
1051 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1052 /* bitfields are always at bmiColors even in larger structures */
1053 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1056 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1059 if (coloruse
== DIB_PAL_COLORS
)
1060 size
= colors
* sizeof(WORD
);
1062 size
= colors
* sizeof(RGBQUAD
);
1063 memcpy( colorptr
, src_colors
, size
);
1068 void fill_default_color_table( BITMAPINFO
*info
)
1072 switch (info
->bmiHeader
.biBitCount
)
1075 info
->bmiColors
[0].rgbRed
= info
->bmiColors
[0].rgbGreen
= info
->bmiColors
[0].rgbBlue
= 0;
1076 info
->bmiColors
[0].rgbReserved
= 0;
1077 info
->bmiColors
[1].rgbRed
= info
->bmiColors
[1].rgbGreen
= info
->bmiColors
[1].rgbBlue
= 0xff;
1078 info
->bmiColors
[1].rgbReserved
= 0;
1082 /* The EGA palette is the first and last 8 colours of the default palette
1083 with the innermost pair swapped */
1084 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 7 * sizeof(RGBQUAD
));
1085 memcpy(info
->bmiColors
+ 7, DefLogPaletteQuads
+ 12, 1 * sizeof(RGBQUAD
));
1086 memcpy(info
->bmiColors
+ 8, DefLogPaletteQuads
+ 7, 1 * sizeof(RGBQUAD
));
1087 memcpy(info
->bmiColors
+ 9, DefLogPaletteQuads
+ 13, 7 * sizeof(RGBQUAD
));
1091 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 10 * sizeof(RGBQUAD
));
1092 memcpy(info
->bmiColors
+ 246, DefLogPaletteQuads
+ 10, 10 * sizeof(RGBQUAD
));
1093 for (i
= 10; i
< 246; i
++)
1095 info
->bmiColors
[i
].rgbRed
= (i
& 0x07) << 5;
1096 info
->bmiColors
[i
].rgbGreen
= (i
& 0x38) << 2;
1097 info
->bmiColors
[i
].rgbBlue
= i
& 0xc0;
1098 info
->bmiColors
[i
].rgbReserved
= 0;
1103 ERR("called with bitcount %d\n", info
->bmiHeader
.biBitCount
);
1105 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1108 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1110 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1111 info
->bmiHeader
.biWidth
= bmp
->bitmap
.bmWidth
;
1112 info
->bmiHeader
.biHeight
= -bmp
->bitmap
.bmHeight
;
1113 info
->bmiHeader
.biPlanes
= 1;
1114 info
->bmiHeader
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
1115 info
->bmiHeader
.biCompression
= BI_RGB
;
1116 info
->bmiHeader
.biXPelsPerMeter
= 0;
1117 info
->bmiHeader
.biYPelsPerMeter
= 0;
1118 info
->bmiHeader
.biClrUsed
= 0;
1119 info
->bmiHeader
.biClrImportant
= 0;
1120 if (info
->bmiHeader
.biBitCount
<= 8) fill_default_color_table( info
);
1123 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1125 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1126 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1127 int info_size
, image_size
;
1129 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1131 info_size
= bitmap_info_size( info
, usage
);
1132 image_size
= get_dib_image_size( info
);
1133 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ image_size
)))
1135 memcpy( ret
, info
, info_size
);
1136 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size(src_info
,usage
), image_size
);
1141 /******************************************************************************
1142 * GetDIBits [GDI32.@]
1144 * Retrieves bits of bitmap and copies to buffer.
1147 * Success: Number of scan lines copied from bitmap
1150 INT WINAPI
GetDIBits(
1151 HDC hdc
, /* [in] Handle to device context */
1152 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1153 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1154 UINT lines
, /* [in] Number of scan lines to copy */
1155 LPVOID bits
, /* [out] Address of array for bitmap bits */
1156 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1157 UINT coloruse
) /* [in] RGB or palette index */
1161 int i
, dst_to_src_offset
, ret
= 0;
1163 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1164 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1165 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1166 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1167 const struct gdi_dc_funcs
*funcs
;
1168 struct gdi_image_bits src_bits
;
1169 struct bitblt_coords src
, dst
;
1170 BOOL empty_rect
= FALSE
;
1172 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1173 own copy and transfer the colour info back at the end */
1174 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1176 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1178 dst_info
->bmiHeader
.biClrUsed
= 0;
1179 dst_info
->bmiHeader
.biClrImportant
= 0;
1181 if (!(dc
= get_dc_ptr( hdc
)))
1183 SetLastError( ERROR_INVALID_PARAMETER
);
1187 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1189 release_dc_ptr( dc
);
1193 funcs
= get_bitmap_funcs( bmp
);
1195 src
.visrect
.left
= 0;
1196 src
.visrect
.top
= 0;
1197 src
.visrect
.right
= bmp
->bitmap
.bmWidth
;
1198 src
.visrect
.bottom
= bmp
->bitmap
.bmHeight
;
1200 dst
.visrect
.left
= 0;
1201 dst
.visrect
.top
= 0;
1202 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1203 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1205 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1208 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1210 ret
= fill_query_info( info
, bmp
);
1214 /* validate parameters */
1216 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1217 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1219 switch (dst_info
->bmiHeader
.biCompression
)
1222 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1223 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1224 if (bits
) goto done
; /* can't retrieve compressed bits */
1227 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1228 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1229 if (bits
) goto done
; /* can't retrieve compressed bits */
1232 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1235 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1236 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1237 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1238 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1239 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1240 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1241 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1249 if (dst_info
->bmiHeader
.biHeight
> 0)
1251 dst_to_src_offset
= -startscan
;
1252 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1253 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1257 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1258 if (dst_to_src_offset
< 0)
1260 dst_to_src_offset
= 0;
1261 lines
= dst
.visrect
.bottom
- startscan
;
1263 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1266 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1267 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1268 dst
.visrect
= src
.visrect
;
1269 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1271 if (dst_info
->bmiHeader
.biHeight
> 0)
1273 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1275 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1276 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1277 memset( bits
, 0, pad_bytes
);
1278 bits
= (char *)bits
+ pad_bytes
;
1283 if (dst
.visrect
.bottom
< lines
)
1285 int pad_lines
= lines
- dst
.visrect
.bottom
;
1286 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1287 int pad_bytes
= pad_lines
* stride
;
1288 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1292 if (empty_rect
) bits
= NULL
;
1294 src
.x
= src
.visrect
.left
;
1295 src
.y
= src
.visrect
.top
;
1296 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1297 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1302 err
= funcs
->pGetImage( NULL
, hbitmap
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1306 /* fill out the src colour table, if it needs one */
1307 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1308 fill_default_color_table( src_info
);
1310 /* if the src and dst are the same depth, copy the colour info across */
1311 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1313 switch (src_info
->bmiHeader
.biBitCount
)
1316 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1318 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1319 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1323 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1325 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1326 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1330 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1331 copy_color_info( dst_info
, src_info
, coloruse
);
1333 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1335 if( coloruse
== DIB_PAL_COLORS
)
1337 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1341 fill_default_color_table( dst_info
);
1347 if(dst_info
->bmiHeader
.biHeight
> 0)
1348 dst_info
->bmiHeader
.biHeight
= src
.height
;
1350 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1352 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
, FALSE
);
1353 if (src_bits
.free
) src_bits
.free( &src_bits
);
1357 ret
= empty_rect
? FALSE
: TRUE
;
1359 if (coloruse
== DIB_PAL_COLORS
)
1361 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1362 int colors
= get_dib_num_of_colors( dst_info
);
1363 for (i
= 0; i
< colors
; i
++, index
++)
1367 dst_info
->bmiHeader
.biClrUsed
= 0;
1368 copy_color_info( info
, dst_info
, coloruse
);
1371 release_dc_ptr( dc
);
1372 GDI_ReleaseObj( hbitmap
);
1377 /***********************************************************************
1378 * CreateDIBitmap (GDI32.@)
1380 * Creates a DDB (device dependent bitmap) from a DIB.
1381 * The DDB will have the same color depth as the reference DC.
1383 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1384 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1387 BITMAPINFOHEADER info
;
1391 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1392 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1393 if (info
.biWidth
< 0) return 0;
1395 /* Top-down DIBs have a negative height */
1396 height
= abs( info
.biHeight
);
1398 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1399 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1400 info
.biBitCount
, info
.biCompression
);
1403 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1405 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1409 if (init
& CBM_INIT
)
1411 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1413 DeleteObject( handle
);
1423 /***********************************************************************
1424 * CreateDIBSection (GDI32.@)
1426 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, CONST BITMAPINFO
*bmi
, UINT usage
,
1427 VOID
**bits
, HANDLE section
, DWORD offset
)
1429 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1430 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1433 BOOL bDesktopDC
= FALSE
;
1436 RGBQUAD
*color_table
= NULL
;
1437 void *mapBits
= NULL
;
1439 if (bits
) *bits
= NULL
;
1440 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1441 if (info
->bmiHeader
.biPlanes
!= 1)
1443 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1444 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1447 if (!(dib
= HeapAlloc( GetProcessHeap(), 0, sizeof(*dib
) ))) return 0;
1449 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1450 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1451 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1452 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1453 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1455 dib
->dsBm
.bmType
= 0;
1456 dib
->dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1457 dib
->dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1458 dib
->dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1459 dib
->dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1460 dib
->dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1461 dib
->dsBm
.bmBits
= NULL
;
1462 dib
->dsBmih
= info
->bmiHeader
;
1464 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1466 unsigned int colors
= 1 << info
->bmiHeader
.biBitCount
;
1468 if (!(color_table
= HeapAlloc( GetProcessHeap(), 0, colors
* sizeof(RGBQUAD
) )))
1470 HeapFree( GetProcessHeap(), 0, dib
);
1473 if (usage
== DIB_RGB_COLORS
)
1474 memcpy( color_table
, info
->bmiColors
, colors
* sizeof(RGBQUAD
) );
1476 fill_color_table_from_pal_colors( hdc
, info
, color_table
);
1478 dib
->dsBmih
.biClrUsed
= colors
;
1481 /* set dsBitfields values */
1482 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1484 dib
->dsBmih
.biCompression
= BI_BITFIELDS
;
1485 dib
->dsBitfields
[0] = 0x7c00;
1486 dib
->dsBitfields
[1] = 0x03e0;
1487 dib
->dsBitfields
[2] = 0x001f;
1489 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1491 dib
->dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1492 dib
->dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1493 dib
->dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1494 if (!dib
->dsBitfields
[0] || !dib
->dsBitfields
[1] || !dib
->dsBitfields
[2]) goto error
;
1496 else dib
->dsBitfields
[0] = dib
->dsBitfields
[1] = dib
->dsBitfields
[2] = 0;
1498 /* get storage location for DIB bits */
1502 SYSTEM_INFO SystemInfo
;
1506 GetSystemInfo( &SystemInfo
);
1507 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1508 mapSize
= dib
->dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1509 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1510 if (mapBits
) dib
->dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1515 dib
->dsBm
.bmBits
= VirtualAlloc( NULL
, dib
->dsBmih
.biSizeImage
,
1516 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1518 dib
->dshSection
= section
;
1519 dib
->dsOffset
= offset
;
1521 if (!dib
->dsBm
.bmBits
)
1523 HeapFree( GetProcessHeap(), 0, color_table
);
1524 HeapFree( GetProcessHeap(), 0, dib
);
1528 /* If the reference hdc is null, take the desktop dc */
1531 hdc
= CreateCompatibleDC(0);
1535 if (!(dc
= get_dc_ptr( hdc
))) goto error
;
1537 /* create Device Dependent Bitmap and add DIB pointer */
1538 ret
= CreateBitmap( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmHeight
, 1,
1539 (info
->bmiHeader
.biBitCount
== 1) ? 1 : GetDeviceCaps(hdc
, BITSPIXEL
), NULL
);
1541 if (ret
&& ((bmp
= GDI_GetObjPtr(ret
, OBJ_BITMAP
))))
1543 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pCreateDIBSection
);
1545 bmp
->funcs
= physdev
->funcs
;
1546 bmp
->color_table
= color_table
;
1547 bmp
->nb_colors
= dib
->dsBmih
.biClrUsed
;
1548 GDI_ReleaseObj( ret
);
1550 if (!physdev
->funcs
->pCreateDIBSection( physdev
, ret
, info
, usage
))
1552 DeleteObject( ret
);
1557 release_dc_ptr( dc
);
1558 if (bDesktopDC
) DeleteDC( hdc
);
1559 if (ret
&& bits
) *bits
= dib
->dsBm
.bmBits
;
1563 if (bDesktopDC
) DeleteDC( hdc
);
1564 if (section
) UnmapViewOfFile( mapBits
);
1565 else if (!offset
) VirtualFree( dib
->dsBm
.bmBits
, 0, MEM_RELEASE
);
1566 HeapFree( GetProcessHeap(), 0, color_table
);
1567 HeapFree( GetProcessHeap(), 0, dib
);