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 BOOL
fill_color_table_from_pal_colors( BITMAPINFO
*info
, HDC hdc
)
250 PALETTEENTRY entries
[256];
253 const WORD
*index
= (const WORD
*)info
->bmiColors
;
254 int i
, count
, colors
= info
->bmiHeader
.biClrUsed
;
256 if (!colors
) return TRUE
;
257 if (!(palette
= GetCurrentObject( hdc
, OBJ_PAL
))) return FALSE
;
258 if (!(count
= GetPaletteEntries( palette
, 0, colors
, entries
))) return FALSE
;
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 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
268 memcpy( info
->bmiColors
, table
, colors
* sizeof(RGBQUAD
) );
269 memset( info
->bmiColors
+ colors
, 0, (info
->bmiHeader
.biClrUsed
- colors
) * sizeof(RGBQUAD
) );
273 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
275 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
276 const int bpp
= info
->bmiHeader
.biBitCount
;
279 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
281 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
284 static BOOL
build_rle_bitmap( const BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
288 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
290 BYTE skip
, num
, data
;
291 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
293 if (clip
) *clip
= NULL
;
295 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
297 out_bits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, get_dib_image_size( info
) );
298 if (!out_bits
) goto fail
;
302 *clip
= CreateRectRgn( 0, 0, 0, 0 );
303 run
= CreateRectRgn( 0, 0, 0, 0 );
304 if (!*clip
|| !run
) goto fail
;
307 x
= left
= right
= 0;
310 while (i
< info
->bmiHeader
.biSizeImage
- 1)
313 data
= in_bits
[i
+ 1];
318 if (x
+ num
> width
) num
= width
- x
;
321 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
322 if (info
->bmiHeader
.biBitCount
== 8)
323 memset( out_ptr
, s
, num
);
328 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
329 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
334 /* this will write one too many if num is odd, but that doesn't matter */
335 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
345 if(left
!= right
&& clip
)
347 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
348 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
353 left
= right
= x
= 0;
362 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
364 if (x
> width
) x
= width
;
371 else /* data bytes of data */
374 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
375 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
376 skip
= (skip
+ 1) & ~1;
377 if (x
+ num
> width
) num
= width
- x
;
380 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
381 if (info
->bmiHeader
.biBitCount
== 8)
382 memcpy( out_ptr
, in_bits
+ i
, num
);
387 const BYTE
*in_ptr
= in_bits
+ i
;
388 for ( ; num
; num
--, x
++)
392 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
396 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
400 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
411 if (run
) DeleteObject( run
);
412 if (bits
->free
) bits
->free( bits
);
414 bits
->ptr
= out_bits
;
415 bits
->is_copy
= TRUE
;
416 bits
->free
= free_heap_bits
;
421 if (run
) DeleteObject( run
);
422 if (clip
&& *clip
) DeleteObject( *clip
);
423 HeapFree( GetProcessHeap(), 0, out_bits
);
429 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
430 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
431 BITMAPINFO
*src_info
, UINT coloruse
, DWORD rop
)
433 DC
*dc
= get_nulldrv_dc( dev
);
434 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
435 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
436 struct bitblt_coords src
, dst
;
437 struct gdi_image_bits src_bits
;
441 INT height
= abs( src_info
->bmiHeader
.biHeight
);
442 BOOL top_down
= src_info
->bmiHeader
.biHeight
< 0, non_stretch_from_origin
= FALSE
;
445 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst
, yDst
, widthDst
, heightDst
,
446 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
448 src_bits
.ptr
= (void*)bits
;
449 src_bits
.is_copy
= FALSE
;
450 src_bits
.free
= NULL
;
452 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
456 rect
.right
= xDst
+ widthDst
;
457 rect
.bottom
= yDst
+ heightDst
;
458 LPtoDP( dc
->hSelf
, (POINT
*)&rect
, 2 );
461 dst
.width
= rect
.right
- rect
.left
;
462 dst
.height
= rect
.bottom
- rect
.top
;
464 if (dc
->layout
& LAYOUT_RTL
&& rop
& NOMIRRORBITMAP
)
467 dst
.width
= -dst
.width
;
469 rop
&= ~NOMIRRORBITMAP
;
472 src
.width
= widthSrc
;
474 src
.height
= heightSrc
;
476 if (src
.x
== 0 && src
.y
== 0 && src
.width
== dst
.width
&& src
.height
== dst
.height
)
477 non_stretch_from_origin
= TRUE
;
479 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
481 BOOL want_clip
= non_stretch_from_origin
&& (rop
== SRCCOPY
);
482 if (!build_rle_bitmap( src_info
, &src_bits
, want_clip
? &clip
: NULL
)) return 0;
485 if (rop
!= SRCCOPY
|| non_stretch_from_origin
)
487 if (dst
.width
== 1 && src
.width
> 1) src
.width
--;
488 if (dst
.height
== 1 && src
.height
> 1) src
.height
--;
493 if (dst
.width
< 0 && dst
.width
== src
.width
)
495 /* This is off-by-one, but that's what Windows does */
498 dst
.width
= -dst
.width
;
499 src
.width
= -src
.width
;
501 if (dst
.height
< 0 && dst
.height
== src
.height
)
505 dst
.height
= -dst
.height
;
506 src
.height
= -src
.height
;
510 if (!top_down
|| (rop
== SRCCOPY
&& !non_stretch_from_origin
)) src
.y
= height
- src
.y
- src
.height
;
512 if (src
.y
>= height
&& src
.y
+ src
.height
+ 1 < height
)
514 else if (src
.y
> 0 && src
.y
+ src
.height
+ 1 < 0)
515 src
.y
= -src
.height
- 1;
517 get_bounding_rect( &rect
, src
.x
, src
.y
, src
.width
, src
.height
);
519 src
.visrect
.left
= 0;
520 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
522 src
.visrect
.bottom
= height
;
523 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
)) goto done
;
525 get_bounding_rect( &rect
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
527 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
529 if (!intersect_vis_rectangles( &dst
, &src
)) goto done
;
531 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
533 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
534 copy_bitmapinfo( dst_info
, src_info
);
535 err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
536 if (err
== ERROR_BAD_FORMAT
)
538 /* 1-bpp destination without a color table requires a fake 1-entry table
539 * that contains only the background color */
540 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_info
->bmiHeader
.biClrUsed
)
542 COLORREF color
= GetBkColor( dev
->hdc
);
543 dst_info
->bmiColors
[0].rgbRed
= GetRValue( color
);
544 dst_info
->bmiColors
[0].rgbGreen
= GetGValue( color
);
545 dst_info
->bmiColors
[0].rgbBlue
= GetBValue( color
);
546 dst_info
->bmiColors
[0].rgbReserved
= 0;
547 dst_info
->bmiHeader
.biClrUsed
= 1;
550 if (!(err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
, FALSE
)))
552 /* get rid of the fake 1-bpp table */
553 if (dst_info
->bmiHeader
.biClrUsed
== 1) dst_info
->bmiHeader
.biClrUsed
= 0;
554 err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, rop
);
558 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
)
560 copy_bitmapinfo( src_info
, dst_info
);
561 err
= stretch_bits( src_info
, &src
, dst_info
, &dst
, &src_bits
, GetStretchBltMode( dev
->hdc
) );
562 if (!err
) err
= dev
->funcs
->pPutImage( dev
, 0, NULL
, dst_info
, &src_bits
, &src
, &dst
, rop
);
565 else if (rop
== SRCCOPY
) ret
= height
;
566 else ret
= src_info
->bmiHeader
.biHeight
;
569 if (src_bits
.free
) src_bits
.free( &src_bits
);
570 if (clip
) DeleteObject( clip
);
574 /***********************************************************************
575 * StretchDIBits (GDI32.@)
577 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
578 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
579 const BITMAPINFO
*bmi
, UINT coloruse
, DWORD rop
)
581 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
582 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
587 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
589 SetLastError( ERROR_INVALID_PARAMETER
);
593 if ((dc
= get_dc_ptr( hdc
)))
595 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
597 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
598 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
599 release_dc_ptr( dc
);
605 /******************************************************************************
606 * SetDIBits [GDI32.@]
608 * Sets pixels in a bitmap using colors from DIB.
611 * hdc [I] Handle to device context
612 * hbitmap [I] Handle to bitmap
613 * startscan [I] Starting scan line
614 * lines [I] Number of scan lines
615 * bits [I] Array of bitmap bits
616 * info [I] Address of structure with data
617 * coloruse [I] Type of color indexes to use
620 * Success: Number of scan lines copied
623 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
624 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
628 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
629 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
630 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
631 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
634 struct gdi_image_bits src_bits
;
635 struct bitblt_coords src
, dst
;
636 INT src_to_dst_offset
;
638 const struct gdi_dc_funcs
*funcs
;
640 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
, TRUE
))
642 SetLastError( ERROR_INVALID_PARAMETER
);
645 if (src_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
647 DWORD
*masks
= (DWORD
*)src_info
->bmiColors
;
648 if (!masks
[0] || !masks
[1] || !masks
[2])
650 SetLastError( ERROR_INVALID_PARAMETER
);
655 src_bits
.ptr
= (void *)bits
;
656 src_bits
.is_copy
= FALSE
;
657 src_bits
.free
= NULL
;
658 src_bits
.param
= NULL
;
660 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, hdc
)) return 0;
662 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
))) return 0;
664 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
666 if (lines
== 0) goto done
;
667 else lines
= src_info
->bmiHeader
.biHeight
;
670 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
673 dst
.visrect
.left
= 0;
675 dst
.visrect
.right
= bitmap
->bitmap
.bmWidth
;
676 dst
.visrect
.bottom
= bitmap
->bitmap
.bmHeight
;
678 src
.visrect
.left
= 0;
680 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
681 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
683 if (src_info
->bmiHeader
.biHeight
> 0)
685 src_to_dst_offset
= -startscan
;
686 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
687 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
691 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
692 /* Unlike the bottom-up case, Windows doesn't limit lines. */
693 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
696 funcs
= get_bitmap_funcs( bitmap
);
700 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
701 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
702 src
.visrect
= dst
.visrect
;
703 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
705 src
.x
= src
.visrect
.left
;
706 src
.y
= src
.visrect
.top
;
707 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
708 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
710 dst
.x
= dst
.visrect
.left
;
711 dst
.y
= dst
.visrect
.top
;
712 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
713 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
715 copy_bitmapinfo( dst_info
, src_info
);
717 err
= funcs
->pPutImage( NULL
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
718 if (err
== ERROR_BAD_FORMAT
)
720 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
, FALSE
);
721 if (!err
) err
= funcs
->pPutImage( NULL
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
726 if (src_bits
.free
) src_bits
.free( &src_bits
);
727 if (clip
) DeleteObject( clip
);
728 GDI_ReleaseObj( hbitmap
);
733 INT
nulldrv_SetDIBitsToDevice( PHYSDEV dev
, INT x_dst
, INT y_dst
, DWORD cx
, DWORD cy
,
734 INT x_src
, INT y_src
, UINT startscan
, UINT lines
,
735 const void *bits
, BITMAPINFO
*src_info
, UINT coloruse
)
737 DC
*dc
= get_nulldrv_dc( dev
);
738 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
739 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
740 struct bitblt_coords src
, dst
;
741 struct gdi_image_bits src_bits
;
749 top_down
= (src_info
->bmiHeader
.biHeight
< 0);
750 height
= abs( src_info
->bmiHeader
.biHeight
);
752 src_bits
.ptr
= (void *)bits
;
753 src_bits
.is_copy
= FALSE
;
754 src_bits
.free
= NULL
;
756 if (!lines
) return 0;
757 if (coloruse
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( src_info
, dev
->hdc
)) return 0;
759 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
763 src_info
->bmiHeader
.biWidth
= x_src
+ cx
;
764 src_info
->bmiHeader
.biHeight
= y_src
+ cy
;
765 if (src_info
->bmiHeader
.biWidth
<= 0 || src_info
->bmiHeader
.biHeight
<= 0) return 0;
770 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) return 0;
774 if (startscan
>= height
) return 0;
775 if (!top_down
&& lines
> height
- startscan
) lines
= height
- startscan
;
777 /* map src to top-down coordinates with startscan as origin */
779 src
.y
= startscan
+ lines
- (y_src
+ cy
);
786 /* get rid of unnecessary lines */
787 if (src
.y
>= lines
) return 0;
791 else if (src
.y
>= lines
) return lines
;
793 src_info
->bmiHeader
.biHeight
= top_down
? -lines
: lines
;
796 src
.visrect
.left
= src
.x
;
797 src
.visrect
.top
= src
.y
;
798 src
.visrect
.right
= src
.x
+ cx
;
799 src
.visrect
.bottom
= src
.y
+ cy
;
802 rect
.right
= src_info
->bmiHeader
.biWidth
;
803 rect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
804 if (!intersect_rect( &src
.visrect
, &src
.visrect
, &rect
))
812 LPtoDP( dev
->hdc
, &pt
, 1 );
817 if (GetLayout( dev
->hdc
) & LAYOUT_RTL
) dst
.x
-= cx
- 1;
821 rect
.right
= dst
.x
+ cx
;
822 rect
.bottom
= dst
.y
+ cy
;
823 if (!clip_visrect( dc
, &dst
.visrect
, &rect
)) goto done
;
825 offset_rect( &src
.visrect
, dst
.x
- src
.x
, dst
.y
- src
.y
);
826 intersect_rect( &rect
, &src
.visrect
, &dst
.visrect
);
827 src
.visrect
= dst
.visrect
= rect
;
828 offset_rect( &src
.visrect
, src
.x
- dst
.x
, src
.y
- dst
.y
);
829 if (is_rect_empty( &dst
.visrect
)) goto done
;
830 if (clip
) OffsetRgn( clip
, dst
.x
- src
.x
, dst
.y
- src
.y
);
832 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
833 copy_bitmapinfo( dst_info
, src_info
);
834 err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
835 if (err
== ERROR_BAD_FORMAT
)
837 err
= convert_bits( src_info
, &src
, dst_info
, &src_bits
, FALSE
);
838 if (!err
) err
= dev
->funcs
->pPutImage( dev
, 0, clip
, dst_info
, &src_bits
, &src
, &dst
, SRCCOPY
);
843 if (src_bits
.free
) src_bits
.free( &src_bits
);
844 if (clip
) DeleteObject( clip
);
848 /***********************************************************************
849 * SetDIBitsToDevice (GDI32.@)
851 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
852 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
853 UINT lines
, LPCVOID bits
, const BITMAPINFO
*bmi
,
856 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
857 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
862 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, coloruse
, TRUE
))
864 SetLastError( ERROR_INVALID_PARAMETER
);
868 if ((dc
= get_dc_ptr( hdc
)))
870 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
872 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
873 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
874 release_dc_ptr( dc
);
879 /***********************************************************************
880 * SetDIBColorTable (GDI32.@)
882 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, CONST RGBQUAD
*colors
)
888 if (!(dc
= get_dc_ptr( hdc
))) return 0;
890 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
892 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBColorTable
);
894 /* Check if currently selected bitmap is a DIB */
895 if (bitmap
->color_table
)
897 if (startpos
< bitmap
->nb_colors
)
899 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
900 memcpy(bitmap
->color_table
+ startpos
, colors
, entries
* sizeof(RGBQUAD
));
904 GDI_ReleaseObj( dc
->hBitmap
);
905 physdev
->funcs
->pSetDIBColorTable( physdev
, startpos
, entries
, colors
);
907 release_dc_ptr( dc
);
912 /***********************************************************************
913 * GetDIBColorTable (GDI32.@)
915 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
921 if (!(dc
= get_dc_ptr( hdc
))) return 0;
923 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
925 /* Check if currently selected bitmap is a DIB */
926 if (bitmap
->color_table
)
928 if (startpos
< bitmap
->nb_colors
)
930 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
931 memcpy(colors
, bitmap
->color_table
+ startpos
, entries
* sizeof(RGBQUAD
));
935 GDI_ReleaseObj( dc
->hBitmap
);
937 release_dc_ptr( dc
);
941 static const RGBQUAD DefLogPaletteQuads
[20] = { /* Copy of Default Logical Palette */
942 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
943 { 0x00, 0x00, 0x00, 0x00 },
944 { 0x00, 0x00, 0x80, 0x00 },
945 { 0x00, 0x80, 0x00, 0x00 },
946 { 0x00, 0x80, 0x80, 0x00 },
947 { 0x80, 0x00, 0x00, 0x00 },
948 { 0x80, 0x00, 0x80, 0x00 },
949 { 0x80, 0x80, 0x00, 0x00 },
950 { 0xc0, 0xc0, 0xc0, 0x00 },
951 { 0xc0, 0xdc, 0xc0, 0x00 },
952 { 0xf0, 0xca, 0xa6, 0x00 },
953 { 0xf0, 0xfb, 0xff, 0x00 },
954 { 0xa4, 0xa0, 0xa0, 0x00 },
955 { 0x80, 0x80, 0x80, 0x00 },
956 { 0x00, 0x00, 0xff, 0x00 },
957 { 0x00, 0xff, 0x00, 0x00 },
958 { 0x00, 0xff, 0xff, 0x00 },
959 { 0xff, 0x00, 0x00, 0x00 },
960 { 0xff, 0x00, 0xff, 0x00 },
961 { 0xff, 0xff, 0x00, 0x00 },
962 { 0xff, 0xff, 0xff, 0x00 }
965 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
966 static const DWORD bit_fields_565
[3] = {0xf800, 0x07e0, 0x001f};
967 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
969 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
971 BITMAPINFOHEADER header
;
973 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
974 header
.biWidth
= bmp
->bitmap
.bmWidth
;
975 header
.biHeight
= bmp
->bitmap
.bmHeight
;
980 header
.biBitCount
= bmp
->dib
->dsBm
.bmBitsPixel
;
981 switch (bmp
->dib
->dsBm
.bmBitsPixel
)
985 header
.biCompression
= BI_BITFIELDS
;
988 header
.biCompression
= BI_RGB
;
994 header
.biCompression
= (bmp
->bitmap
.bmBitsPixel
> 8) ? BI_BITFIELDS
: BI_RGB
;
995 header
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
998 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
999 header
.biXPelsPerMeter
= 0;
1000 header
.biYPelsPerMeter
= 0;
1001 header
.biClrUsed
= 0;
1002 header
.biClrImportant
= 0;
1004 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
1006 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
1008 coreheader
->bcWidth
= header
.biWidth
;
1009 coreheader
->bcHeight
= header
.biHeight
;
1010 coreheader
->bcPlanes
= header
.biPlanes
;
1011 coreheader
->bcBitCount
= header
.biBitCount
;
1014 info
->bmiHeader
= header
;
1016 return abs(bmp
->bitmap
.bmHeight
);
1019 /************************************************************************
1022 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1024 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
1026 unsigned int colors
= get_dib_num_of_colors( src
);
1027 RGBQUAD
*src_colors
= (RGBQUAD
*)((char *)src
+ src
->bmiHeader
.biSize
);
1029 assert( src
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) );
1031 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
1033 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
1034 if (coloruse
== DIB_PAL_COLORS
)
1035 memcpy( core
->bmciColors
, src_colors
, colors
* sizeof(WORD
) );
1039 for (i
= 0; i
< colors
; i
++)
1041 core
->bmciColors
[i
].rgbtRed
= src_colors
[i
].rgbRed
;
1042 core
->bmciColors
[i
].rgbtGreen
= src_colors
[i
].rgbGreen
;
1043 core
->bmciColors
[i
].rgbtBlue
= src_colors
[i
].rgbBlue
;
1049 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
1050 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
1052 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1053 /* bitfields are always at bmiColors even in larger structures */
1054 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
1057 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
1060 if (coloruse
== DIB_PAL_COLORS
)
1061 size
= colors
* sizeof(WORD
);
1063 size
= colors
* sizeof(RGBQUAD
);
1064 memcpy( colorptr
, src_colors
, size
);
1069 void fill_default_color_table( BITMAPINFO
*info
)
1073 switch (info
->bmiHeader
.biBitCount
)
1076 info
->bmiColors
[0].rgbRed
= info
->bmiColors
[0].rgbGreen
= info
->bmiColors
[0].rgbBlue
= 0;
1077 info
->bmiColors
[0].rgbReserved
= 0;
1078 info
->bmiColors
[1].rgbRed
= info
->bmiColors
[1].rgbGreen
= info
->bmiColors
[1].rgbBlue
= 0xff;
1079 info
->bmiColors
[1].rgbReserved
= 0;
1083 /* The EGA palette is the first and last 8 colours of the default palette
1084 with the innermost pair swapped */
1085 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 7 * sizeof(RGBQUAD
));
1086 memcpy(info
->bmiColors
+ 7, DefLogPaletteQuads
+ 12, 1 * sizeof(RGBQUAD
));
1087 memcpy(info
->bmiColors
+ 8, DefLogPaletteQuads
+ 7, 1 * sizeof(RGBQUAD
));
1088 memcpy(info
->bmiColors
+ 9, DefLogPaletteQuads
+ 13, 7 * sizeof(RGBQUAD
));
1092 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 10 * sizeof(RGBQUAD
));
1093 memcpy(info
->bmiColors
+ 246, DefLogPaletteQuads
+ 10, 10 * sizeof(RGBQUAD
));
1094 for (i
= 10; i
< 246; i
++)
1096 info
->bmiColors
[i
].rgbRed
= (i
& 0x07) << 5;
1097 info
->bmiColors
[i
].rgbGreen
= (i
& 0x38) << 2;
1098 info
->bmiColors
[i
].rgbBlue
= i
& 0xc0;
1099 info
->bmiColors
[i
].rgbReserved
= 0;
1104 ERR("called with bitcount %d\n", info
->bmiHeader
.biBitCount
);
1106 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1109 void get_ddb_bitmapinfo( BITMAPOBJ
*bmp
, BITMAPINFO
*info
)
1111 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1112 info
->bmiHeader
.biWidth
= bmp
->bitmap
.bmWidth
;
1113 info
->bmiHeader
.biHeight
= -bmp
->bitmap
.bmHeight
;
1114 info
->bmiHeader
.biPlanes
= 1;
1115 info
->bmiHeader
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
1116 info
->bmiHeader
.biCompression
= BI_RGB
;
1117 info
->bmiHeader
.biXPelsPerMeter
= 0;
1118 info
->bmiHeader
.biYPelsPerMeter
= 0;
1119 info
->bmiHeader
.biClrUsed
= 0;
1120 info
->bmiHeader
.biClrImportant
= 0;
1121 if (info
->bmiHeader
.biBitCount
<= 8) fill_default_color_table( info
);
1124 BITMAPINFO
*copy_packed_dib( const BITMAPINFO
*src_info
, UINT usage
)
1126 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1127 BITMAPINFO
*ret
, *info
= (BITMAPINFO
*)buffer
;
1128 int info_size
, image_size
;
1130 if (!bitmapinfo_from_user_bitmapinfo( info
, src_info
, usage
, FALSE
)) return NULL
;
1132 info_size
= bitmap_info_size( info
, usage
);
1133 image_size
= get_dib_image_size( info
);
1134 if ((ret
= HeapAlloc( GetProcessHeap(), 0, info_size
+ image_size
)))
1136 memcpy( ret
, info
, info_size
);
1137 memcpy( (char *)ret
+ info_size
, (char *)src_info
+ bitmap_info_size(src_info
,usage
), image_size
);
1142 /******************************************************************************
1143 * GetDIBits [GDI32.@]
1145 * Retrieves bits of bitmap and copies to buffer.
1148 * Success: Number of scan lines copied from bitmap
1151 INT WINAPI
GetDIBits(
1152 HDC hdc
, /* [in] Handle to device context */
1153 HBITMAP hbitmap
, /* [in] Handle to bitmap */
1154 UINT startscan
, /* [in] First scan line to set in dest bitmap */
1155 UINT lines
, /* [in] Number of scan lines to copy */
1156 LPVOID bits
, /* [out] Address of array for bitmap bits */
1157 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
1158 UINT coloruse
) /* [in] RGB or palette index */
1162 int i
, dst_to_src_offset
, ret
= 0;
1164 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1165 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
1166 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1167 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1168 const struct gdi_dc_funcs
*funcs
;
1169 struct gdi_image_bits src_bits
;
1170 struct bitblt_coords src
, dst
;
1171 BOOL empty_rect
= FALSE
;
1173 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1174 own copy and transfer the colour info back at the end */
1175 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info
->bmiHeader
, &info
->bmiHeader
)) return 0;
1177 (dst_info
->bmiHeader
.biCompression
== BI_JPEG
|| dst_info
->bmiHeader
.biCompression
== BI_PNG
))
1179 dst_info
->bmiHeader
.biClrUsed
= 0;
1180 dst_info
->bmiHeader
.biClrImportant
= 0;
1182 if (!(dc
= get_dc_ptr( hdc
)))
1184 SetLastError( ERROR_INVALID_PARAMETER
);
1188 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
1190 release_dc_ptr( dc
);
1194 funcs
= get_bitmap_funcs( bmp
);
1196 src
.visrect
.left
= 0;
1197 src
.visrect
.top
= 0;
1198 src
.visrect
.right
= bmp
->bitmap
.bmWidth
;
1199 src
.visrect
.bottom
= bmp
->bitmap
.bmHeight
;
1201 dst
.visrect
.left
= 0;
1202 dst
.visrect
.top
= 0;
1203 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1204 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1206 if (lines
== 0 || startscan
>= dst
.visrect
.bottom
)
1209 if (!bits
&& dst_info
->bmiHeader
.biBitCount
== 0) /* query bitmap info only */
1211 ret
= fill_query_info( info
, bmp
);
1215 /* validate parameters */
1217 if (dst_info
->bmiHeader
.biWidth
<= 0) goto done
;
1218 if (dst_info
->bmiHeader
.biHeight
== 0) goto done
;
1220 switch (dst_info
->bmiHeader
.biCompression
)
1223 if (dst_info
->bmiHeader
.biBitCount
!= 4) goto done
;
1224 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1225 if (bits
) goto done
; /* can't retrieve compressed bits */
1228 if (dst_info
->bmiHeader
.biBitCount
!= 8) goto done
;
1229 if (dst_info
->bmiHeader
.biHeight
< 0) goto done
;
1230 if (bits
) goto done
; /* can't retrieve compressed bits */
1233 if (dst_info
->bmiHeader
.biBitCount
!= 16 && dst_info
->bmiHeader
.biBitCount
!= 32) goto done
;
1236 if (lines
&& !dst_info
->bmiHeader
.biPlanes
) goto done
;
1237 if (dst_info
->bmiHeader
.biBitCount
== 1) break;
1238 if (dst_info
->bmiHeader
.biBitCount
== 4) break;
1239 if (dst_info
->bmiHeader
.biBitCount
== 8) break;
1240 if (dst_info
->bmiHeader
.biBitCount
== 16) break;
1241 if (dst_info
->bmiHeader
.biBitCount
== 24) break;
1242 if (dst_info
->bmiHeader
.biBitCount
== 32) break;
1250 if (dst_info
->bmiHeader
.biHeight
> 0)
1252 dst_to_src_offset
= -startscan
;
1253 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1254 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1258 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1259 if (dst_to_src_offset
< 0)
1261 dst_to_src_offset
= 0;
1262 lines
= dst
.visrect
.bottom
- startscan
;
1264 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1267 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1268 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1269 dst
.visrect
= src
.visrect
;
1270 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1272 if (dst_info
->bmiHeader
.biHeight
> 0)
1274 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1276 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1277 int pad_bytes
= pad_lines
* get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1278 memset( bits
, 0, pad_bytes
);
1279 bits
= (char *)bits
+ pad_bytes
;
1284 if (dst
.visrect
.bottom
< lines
)
1286 int pad_lines
= lines
- dst
.visrect
.bottom
;
1287 int stride
= get_dib_stride( dst_info
->bmiHeader
.biWidth
, dst_info
->bmiHeader
.biBitCount
);
1288 int pad_bytes
= pad_lines
* stride
;
1289 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1293 if (empty_rect
) bits
= NULL
;
1295 src
.x
= src
.visrect
.left
;
1296 src
.y
= src
.visrect
.top
;
1297 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1298 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1303 err
= funcs
->pGetImage( NULL
, hbitmap
, src_info
, bits
? &src_bits
: NULL
, bits
? &src
: NULL
);
1307 /* fill out the src colour table, if it needs one */
1308 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1309 fill_default_color_table( src_info
);
1311 /* if the src and dst are the same depth, copy the colour info across */
1312 if (dst_info
->bmiHeader
.biBitCount
== src_info
->bmiHeader
.biBitCount
&& coloruse
== DIB_RGB_COLORS
)
1314 switch (src_info
->bmiHeader
.biBitCount
)
1317 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1319 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1320 memcpy( src_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1324 if (src_info
->bmiHeader
.biCompression
== BI_RGB
)
1326 src_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1327 memcpy( src_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1331 src_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
1332 copy_color_info( dst_info
, src_info
, coloruse
);
1334 else if (dst_info
->bmiHeader
.biBitCount
<= 8) /* otherwise construct a default colour table for the dst, if needed */
1336 if( coloruse
== DIB_PAL_COLORS
)
1338 if (!fill_color_table_from_palette( dst_info
, hdc
)) goto done
;
1342 fill_default_color_table( dst_info
);
1348 if(dst_info
->bmiHeader
.biHeight
> 0)
1349 dst_info
->bmiHeader
.biHeight
= src
.height
;
1351 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1353 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
, dst_info
, bits
, FALSE
);
1354 if (src_bits
.free
) src_bits
.free( &src_bits
);
1358 ret
= empty_rect
? FALSE
: TRUE
;
1360 if (coloruse
== DIB_PAL_COLORS
)
1362 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1363 int colors
= get_dib_num_of_colors( dst_info
);
1364 for (i
= 0; i
< colors
; i
++, index
++)
1368 dst_info
->bmiHeader
.biClrUsed
= 0;
1369 copy_color_info( info
, dst_info
, coloruse
);
1372 release_dc_ptr( dc
);
1373 GDI_ReleaseObj( hbitmap
);
1378 /***********************************************************************
1379 * CreateDIBitmap (GDI32.@)
1381 * Creates a DDB (device dependent bitmap) from a DIB.
1382 * The DDB will have the same color depth as the reference DC.
1384 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1385 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1388 BITMAPINFOHEADER info
;
1392 if (!bitmapinfoheader_from_user_bitmapinfo( &info
, header
)) return 0;
1393 if (info
.biCompression
== BI_JPEG
|| info
.biCompression
== BI_PNG
) return 0;
1394 if (info
.biWidth
< 0) return 0;
1396 /* Top-down DIBs have a negative height */
1397 height
= abs( info
.biHeight
);
1399 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1400 hdc
, header
, init
, bits
, data
, coloruse
, info
.biWidth
, info
.biHeight
,
1401 info
.biBitCount
, info
.biCompression
);
1404 handle
= CreateBitmap( info
.biWidth
, height
, 1, 1, NULL
);
1406 handle
= CreateCompatibleBitmap( hdc
, info
.biWidth
, height
);
1410 if (init
& CBM_INIT
)
1412 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1414 DeleteObject( handle
);
1424 /***********************************************************************
1425 * CreateDIBSection (GDI32.@)
1427 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, CONST BITMAPINFO
*bmi
, UINT usage
,
1428 VOID
**bits
, HANDLE section
, DWORD offset
)
1430 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1431 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1434 BOOL bDesktopDC
= FALSE
;
1437 RGBQUAD
*color_table
= NULL
;
1438 void *mapBits
= NULL
;
1440 if (bits
) *bits
= NULL
;
1441 if (!bitmapinfo_from_user_bitmapinfo( info
, bmi
, usage
, FALSE
)) return 0;
1442 if (info
->bmiHeader
.biPlanes
!= 1)
1444 if (info
->bmiHeader
.biPlanes
* info
->bmiHeader
.biBitCount
> 16) return 0;
1445 WARN( "%u planes not properly supported\n", info
->bmiHeader
.biPlanes
);
1448 if (!(dib
= HeapAlloc( GetProcessHeap(), 0, sizeof(*dib
) ))) return 0;
1450 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1451 info
->bmiHeader
.biWidth
, info
->bmiHeader
.biHeight
,
1452 info
->bmiHeader
.biPlanes
, info
->bmiHeader
.biBitCount
,
1453 info
->bmiHeader
.biCompression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1454 info
->bmiHeader
.biSizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1456 dib
->dsBm
.bmType
= 0;
1457 dib
->dsBm
.bmWidth
= info
->bmiHeader
.biWidth
;
1458 dib
->dsBm
.bmHeight
= abs( info
->bmiHeader
.biHeight
);
1459 dib
->dsBm
.bmWidthBytes
= get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
);
1460 dib
->dsBm
.bmPlanes
= info
->bmiHeader
.biPlanes
;
1461 dib
->dsBm
.bmBitsPixel
= info
->bmiHeader
.biBitCount
;
1462 dib
->dsBm
.bmBits
= NULL
;
1463 dib
->dsBmih
= info
->bmiHeader
;
1465 if (info
->bmiHeader
.biBitCount
<= 8) /* build the color table */
1467 if (usage
== DIB_PAL_COLORS
&& !fill_color_table_from_pal_colors( info
, hdc
))
1469 dib
->dsBmih
.biClrUsed
= info
->bmiHeader
.biClrUsed
;
1470 if (!(color_table
= HeapAlloc( GetProcessHeap(), 0, dib
->dsBmih
.biClrUsed
* sizeof(RGBQUAD
) )))
1472 memcpy( color_table
, info
->bmiColors
, dib
->dsBmih
.biClrUsed
* sizeof(RGBQUAD
) );
1475 /* set dsBitfields values */
1476 if (info
->bmiHeader
.biBitCount
== 16 && info
->bmiHeader
.biCompression
== BI_RGB
)
1478 dib
->dsBmih
.biCompression
= BI_BITFIELDS
;
1479 dib
->dsBitfields
[0] = 0x7c00;
1480 dib
->dsBitfields
[1] = 0x03e0;
1481 dib
->dsBitfields
[2] = 0x001f;
1483 else if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1485 if (usage
== DIB_PAL_COLORS
) goto error
;
1486 dib
->dsBitfields
[0] = *(const DWORD
*)info
->bmiColors
;
1487 dib
->dsBitfields
[1] = *((const DWORD
*)info
->bmiColors
+ 1);
1488 dib
->dsBitfields
[2] = *((const DWORD
*)info
->bmiColors
+ 2);
1489 if (!dib
->dsBitfields
[0] || !dib
->dsBitfields
[1] || !dib
->dsBitfields
[2]) goto error
;
1491 else dib
->dsBitfields
[0] = dib
->dsBitfields
[1] = dib
->dsBitfields
[2] = 0;
1493 /* get storage location for DIB bits */
1497 SYSTEM_INFO SystemInfo
;
1501 GetSystemInfo( &SystemInfo
);
1502 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1503 mapSize
= dib
->dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1504 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1505 if (mapBits
) dib
->dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1510 dib
->dsBm
.bmBits
= VirtualAlloc( NULL
, dib
->dsBmih
.biSizeImage
,
1511 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1513 dib
->dshSection
= section
;
1514 dib
->dsOffset
= offset
;
1516 if (!dib
->dsBm
.bmBits
) goto error
;
1518 /* If the reference hdc is null, take the desktop dc */
1521 hdc
= CreateCompatibleDC(0);
1525 if (!(dc
= get_dc_ptr( hdc
))) goto error
;
1527 /* create Device Dependent Bitmap and add DIB pointer */
1528 ret
= CreateBitmap( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmHeight
, 1,
1529 (info
->bmiHeader
.biBitCount
== 1) ? 1 : GetDeviceCaps(hdc
, BITSPIXEL
), NULL
);
1531 if (ret
&& ((bmp
= GDI_GetObjPtr(ret
, OBJ_BITMAP
))))
1533 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pCreateDIBSection
);
1535 bmp
->funcs
= physdev
->funcs
;
1536 bmp
->color_table
= color_table
;
1537 bmp
->nb_colors
= dib
->dsBmih
.biClrUsed
;
1538 GDI_ReleaseObj( ret
);
1540 if (!physdev
->funcs
->pCreateDIBSection( physdev
, ret
, info
, usage
))
1542 DeleteObject( ret
);
1547 release_dc_ptr( dc
);
1548 if (bDesktopDC
) DeleteDC( hdc
);
1549 if (ret
&& bits
) *bits
= dib
->dsBm
.bmBits
;
1553 if (bDesktopDC
) DeleteDC( hdc
);
1554 if (section
) UnmapViewOfFile( mapBits
);
1555 else if (!offset
) VirtualFree( dib
->dsBm
.bmBits
, 0, MEM_RELEASE
);
1556 HeapFree( GetProcessHeap(), 0, color_table
);
1557 HeapFree( GetProcessHeap(), 0, dib
);