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),
32 or use the internal function DIB_GetBitmapInfo.
35 * The palettes are stored in different formats:
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
46 If biCompression is BI_BITFIELDS, the color masks are at the same position
47 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48 the new headers have structure members for the masks.
51 * You should never access the color table using the bmiColors member,
52 because the passed structure may have one of the extended headers
53 mentioned above. Use this to calculate the location:
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
60 Search for "Bitmap Structures" in MSDN
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap
);
76 /***********************************************************************
79 * Return the size of the bitmap info structure including color table.
81 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
83 unsigned int colors
, size
, masks
= 0;
85 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
87 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
88 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
89 return sizeof(BITMAPCOREHEADER
) + colors
*
90 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
92 else /* assume BITMAPINFOHEADER */
94 colors
= get_dib_num_of_colors( info
);
95 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
96 size
= max( info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) );
97 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
102 /***********************************************************************
105 * Get the info from a bitmap header.
106 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
108 int DIB_GetBitmapInfo( const BITMAPINFOHEADER
*header
, LONG
*width
,
109 LONG
*height
, WORD
*planes
, WORD
*bpp
, DWORD
*compr
, DWORD
*size
)
111 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
113 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)header
;
114 *width
= core
->bcWidth
;
115 *height
= core
->bcHeight
;
116 *planes
= core
->bcPlanes
;
117 *bpp
= core
->bcBitCount
;
122 if (header
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
124 *width
= header
->biWidth
;
125 *height
= header
->biHeight
;
126 *planes
= header
->biPlanes
;
127 *bpp
= header
->biBitCount
;
128 *compr
= header
->biCompression
;
129 *size
= header
->biSizeImage
;
132 ERR("(%d): unknown/wrong size for header\n", header
->biSize
);
136 /*******************************************************************************************
137 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
139 static BOOL
bitmapinfo_from_user_bitmapinfo( BITMAPINFO
*dst
, const BITMAPINFO
*info
, UINT coloruse
)
144 void *src_colors
= (char *)info
+ info
->bmiHeader
.biSize
;
146 int bitmap_type
= DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
, &planes
, &bpp
, &compr
, &size
);
148 if (bitmap_type
== -1) return FALSE
;
150 if (bitmap_type
== 1)
152 dst
->bmiHeader
= info
->bmiHeader
;
153 dst
->bmiHeader
.biSize
= sizeof(dst
->bmiHeader
);
155 colors
= get_dib_num_of_colors( dst
);
157 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
158 /* bitfields are always at bmiColors even in larger structures */
159 memcpy( dst
->bmiColors
, info
->bmiColors
, 3 * sizeof(DWORD
) );
164 if (coloruse
== DIB_PAL_COLORS
)
165 size
= colors
* sizeof(WORD
);
167 size
= colors
* sizeof(RGBQUAD
);
168 memcpy( dst
->bmiColors
, src_colors
, size
);
173 dst
->bmiHeader
.biSize
= sizeof(dst
->bmiHeader
);
174 dst
->bmiHeader
.biWidth
= width
;
175 dst
->bmiHeader
.biHeight
= height
;
176 dst
->bmiHeader
.biPlanes
= planes
;
177 dst
->bmiHeader
.biBitCount
= bpp
;
178 dst
->bmiHeader
.biCompression
= compr
;
179 dst
->bmiHeader
.biSizeImage
= size
;
180 dst
->bmiHeader
.biXPelsPerMeter
= 0;
181 dst
->bmiHeader
.biYPelsPerMeter
= 0;
182 dst
->bmiHeader
.biClrUsed
= 0;
183 dst
->bmiHeader
.biClrImportant
= 0;
185 colors
= get_dib_num_of_colors( dst
);
189 if (coloruse
== DIB_PAL_COLORS
)
190 memcpy( dst
->bmiColors
, src_colors
, colors
* sizeof(WORD
) );
194 RGBTRIPLE
*triple
= (RGBTRIPLE
*)src_colors
;
195 for (i
= 0; i
< colors
; i
++)
197 dst
->bmiColors
[i
].rgbRed
= triple
[i
].rgbtRed
;
198 dst
->bmiColors
[i
].rgbGreen
= triple
[i
].rgbtGreen
;
199 dst
->bmiColors
[i
].rgbBlue
= triple
[i
].rgbtBlue
;
200 dst
->bmiColors
[i
].rgbReserved
= 0;
209 static int fill_color_table_from_palette( BITMAPINFO
*info
, DC
*dc
)
211 PALETTEENTRY palEntry
[256];
212 int i
, colors
= get_dib_num_of_colors( info
);
214 if (!colors
) return 0;
216 memset( palEntry
, 0, sizeof(palEntry
) );
217 if (!GetPaletteEntries( dc
->hPalette
, 0, colors
, palEntry
))
220 for (i
= 0; i
< colors
; i
++)
222 info
->bmiColors
[i
].rgbRed
= palEntry
[i
].peRed
;
223 info
->bmiColors
[i
].rgbGreen
= palEntry
[i
].peGreen
;
224 info
->bmiColors
[i
].rgbBlue
= palEntry
[i
].peBlue
;
225 info
->bmiColors
[i
].rgbReserved
= 0;
231 static void *get_pixel_ptr( const BITMAPINFO
*info
, void *bits
, int x
, int y
)
233 const int width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
234 const int bpp
= info
->bmiHeader
.biBitCount
;
237 return (char *)bits
+ (height
- y
- 1) * get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
239 return (char *)bits
+ y
* get_dib_stride( width
, bpp
) + x
* bpp
/ 8;
242 static BOOL
build_rle_bitmap( const BITMAPINFO
*info
, struct gdi_image_bits
*bits
, HRGN
*clip
)
246 int x
, y
, width
= info
->bmiHeader
.biWidth
, height
= info
->bmiHeader
.biHeight
;
248 BYTE skip
, num
, data
;
249 BYTE
*out_bits
, *in_bits
= bits
->ptr
;
253 assert( info
->bmiHeader
.biBitCount
== 4 || info
->bmiHeader
.biBitCount
== 8 );
255 out_bits
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
) );
256 *clip
= CreateRectRgn( 0, 0, 0, 0 );
257 run
= CreateRectRgn( 0, 0, 0, 0 );
258 if (!out_bits
|| !*clip
|| !run
) goto fail
;
260 x
= left
= right
= 0;
263 while (i
< info
->bmiHeader
.biSizeImage
- 1)
266 data
= in_bits
[i
+ 1];
271 if (x
+ num
> width
) num
= width
- x
;
274 BYTE s
= data
, *out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
275 if (info
->bmiHeader
.biBitCount
== 8)
276 memset( out_ptr
, s
, num
);
281 s
= ((s
>> 4) & 0x0f) | ((s
<< 4) & 0xf0);
282 *out_ptr
= (*out_ptr
& 0xf0) | (s
& 0x0f);
287 /* this will write one too many if num is odd, but that doesn't matter */
288 if (num
) memset( out_ptr
, s
, (num
+ 1) / 2 );
300 SetRectRgn( run
, left
, y
, right
, y
+ 1 );
301 CombineRgn( *clip
, run
, *clip
, RGN_OR
);
306 left
= right
= x
= 0;
315 if (i
>= info
->bmiHeader
.biSizeImage
- 1) goto done
;
317 if (x
> width
) x
= width
;
324 else /* data bytes of data */
327 skip
= (num
* info
->bmiHeader
.biBitCount
+ 7) / 8;
328 if (skip
> info
->bmiHeader
.biSizeImage
- i
) goto done
;
329 skip
= (skip
+ 1) & ~1;
330 if (x
+ num
> width
) num
= width
- x
;
333 BYTE
*out_ptr
= get_pixel_ptr( info
, out_bits
, x
, y
);
334 if (info
->bmiHeader
.biBitCount
== 8)
335 memcpy( out_ptr
, in_bits
+ i
, num
);
340 const BYTE
*in_ptr
= in_bits
+ i
;
341 for ( ; num
; num
--, x
++)
345 *out_ptr
= (*out_ptr
& 0xf0) | ((*in_ptr
>> 4) & 0x0f);
349 *out_ptr
= (*in_ptr
++ << 4) & 0xf0;
353 memcpy( out_ptr
, in_bits
+ i
, (num
+ 1) / 2);
365 if (bits
->free
) bits
->free( bits
);
367 bits
->ptr
= out_bits
;
368 bits
->is_copy
= TRUE
;
369 bits
->free
= free_heap_bits
;
374 if (run
) DeleteObject( run
);
375 if (*clip
) DeleteObject( *clip
);
376 HeapFree( GetProcessHeap(), 0, out_bits
);
382 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
383 INT
nulldrv_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
384 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
385 const BITMAPINFO
*info
, UINT coloruse
, DWORD rop
)
387 DC
*dc
= get_nulldrv_dc( dev
);
395 /* make sure we have a real implementation for StretchBlt and PutImage */
396 if (GET_DC_PHYSDEV( dc
, pStretchBlt
) == dev
|| GET_DC_PHYSDEV( dc
, pPutImage
) == dev
)
399 if (DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
, &planes
, &bpp
, &compr
, &size
) == -1)
402 if (width
< 0) return 0;
404 if (xSrc
== 0 && ySrc
== 0 && widthDst
== widthSrc
&& heightDst
== heightSrc
&&
405 info
->bmiHeader
.biCompression
== BI_RGB
)
407 /* Windows appears to have a fast case optimization
408 * that uses the wrong origin for top-down DIBs */
409 if (height
< 0 && heightSrc
< abs(height
)) ySrc
= abs(height
) - heightSrc
;
411 if (xDst
== 0 && yDst
== 0 && info
->bmiHeader
.biCompression
== BI_RGB
&& rop
== SRCCOPY
)
414 hBitmap
= GetCurrentObject( dev
->hdc
, OBJ_BITMAP
);
415 if (GetObjectW( hBitmap
, sizeof(bm
), &bm
) &&
416 bm
.bmWidth
== widthSrc
&& bm
.bmHeight
== heightSrc
&&
417 bm
.bmBitsPixel
== bpp
&& bm
.bmPlanes
== planes
)
420 return SetDIBits( dev
->hdc
, hBitmap
, 0, abs( height
), bits
, info
, coloruse
);
425 hdcMem
= CreateCompatibleDC( dev
->hdc
);
426 hBitmap
= CreateCompatibleBitmap( dev
->hdc
, width
, height
);
427 SelectObject( hdcMem
, hBitmap
);
428 if (coloruse
== DIB_PAL_COLORS
)
429 SelectPalette( hdcMem
, GetCurrentObject( dev
->hdc
, OBJ_PAL
), FALSE
);
431 if (info
->bmiHeader
.biCompression
== BI_RLE4
|| info
->bmiHeader
.biCompression
== BI_RLE8
)
433 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
434 * contain all the rectangle described in bmiHeader, but only part of it.
435 * This mean that those undescribed pixels must be left untouched.
436 * So, we first copy on a memory bitmap the current content of the
437 * destination rectangle, blit the DIB bits on top of it - hence leaving
438 * the gaps untouched -, and blitting the rectangle back.
439 * This insure that gaps are untouched on the destination rectangle
441 StretchBlt( hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
, widthSrc
, heightSrc
,
442 dev
->hdc
, xDst
, yDst
, widthDst
, heightDst
, rop
);
444 ret
= SetDIBits( hdcMem
, hBitmap
, 0, abs( height
), bits
, info
, coloruse
);
445 if (ret
) StretchBlt( dev
->hdc
, xDst
, yDst
, widthDst
, heightDst
,
446 hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
, widthSrc
, heightSrc
, rop
);
448 DeleteObject( hBitmap
);
452 /***********************************************************************
453 * StretchDIBits (GDI32.@)
455 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
456 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
457 const BITMAPINFO
*info
, UINT coloruse
, DWORD rop
)
462 if (!bits
|| !info
) return 0;
464 if ((dc
= get_dc_ptr( hdc
)))
466 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pStretchDIBits
);
468 ret
= physdev
->funcs
->pStretchDIBits( physdev
, xDst
, yDst
, widthDst
, heightDst
,
469 xSrc
, ySrc
, widthSrc
, heightSrc
, bits
, info
, coloruse
, rop
);
470 release_dc_ptr( dc
);
476 /******************************************************************************
477 * SetDIBits [GDI32.@]
479 * Sets pixels in a bitmap using colors from DIB.
482 * hdc [I] Handle to device context
483 * hbitmap [I] Handle to bitmap
484 * startscan [I] Starting scan line
485 * lines [I] Number of scan lines
486 * bits [I] Array of bitmap bits
487 * info [I] Address of structure with data
488 * coloruse [I] Type of color indexes to use
491 * Success: Number of scan lines copied
494 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
495 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
498 DC
*dc
= get_dc_ptr( hdc
);
499 BOOL delete_hdc
= FALSE
;
502 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
503 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
504 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
505 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
508 struct gdi_image_bits src_bits
;
509 struct bitblt_coords src
, dst
;
510 INT src_to_dst_offset
;
513 src_bits
.ptr
= (void *)bits
;
514 src_bits
.is_copy
= FALSE
;
515 src_bits
.free
= NULL
;
516 src_bits
.param
= NULL
;
518 if (coloruse
== DIB_RGB_COLORS
&& !dc
)
520 hdc
= CreateCompatibleDC(0);
521 dc
= get_dc_ptr( hdc
);
529 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
531 release_dc_ptr( dc
);
532 if (delete_hdc
) DeleteDC(hdc
);
536 if (!bitmapinfo_from_user_bitmapinfo( src_info
, info
, coloruse
)) goto done
;
538 if (coloruse
== DIB_PAL_COLORS
)
539 if (!fill_color_table_from_palette( src_info
, dc
)) goto done
;
541 if (src_info
->bmiHeader
.biCompression
== BI_RLE4
|| src_info
->bmiHeader
.biCompression
== BI_RLE8
)
543 if ( src_info
->bmiHeader
.biHeight
< 0 ||
544 (src_info
->bmiHeader
.biCompression
== BI_RLE4
&& src_info
->bmiHeader
.biBitCount
!= 4) ||
545 (src_info
->bmiHeader
.biCompression
== BI_RLE8
&& src_info
->bmiHeader
.biBitCount
!= 8) )
547 SetLastError( ERROR_INVALID_PARAMETER
);
551 if (lines
== 0) goto done
;
552 else lines
= src_info
->bmiHeader
.biHeight
;
555 if (!build_rle_bitmap( src_info
, &src_bits
, &clip
)) goto done
;
558 dst
.visrect
.left
= 0;
560 dst
.visrect
.right
= bitmap
->bitmap
.bmWidth
;
561 dst
.visrect
.bottom
= bitmap
->bitmap
.bmHeight
;
563 src
.visrect
.left
= 0;
565 src
.visrect
.right
= src_info
->bmiHeader
.biWidth
;
566 src
.visrect
.bottom
= abs( src_info
->bmiHeader
.biHeight
);
568 if (src_info
->bmiHeader
.biHeight
> 0)
570 src_to_dst_offset
= -startscan
;
571 lines
= min( lines
, src
.visrect
.bottom
- startscan
);
572 if (lines
< src
.visrect
.bottom
) src
.visrect
.top
= src
.visrect
.bottom
- lines
;
576 src_to_dst_offset
= src
.visrect
.bottom
- lines
- startscan
;
577 /* Unlike the bottom-up case, Windows doesn't limit lines. */
578 if (lines
< src
.visrect
.bottom
) src
.visrect
.bottom
= lines
;
581 physdev
= GET_DC_PHYSDEV( dc
, pPutImage
);
582 if (!BITMAP_SetOwnerDC( hbitmap
, physdev
)) goto done
;
586 offset_rect( &src
.visrect
, 0, src_to_dst_offset
);
587 if (!intersect_rect( &dst
.visrect
, &src
.visrect
, &dst
.visrect
)) goto done
;
588 src
.visrect
= dst
.visrect
;
589 offset_rect( &src
.visrect
, 0, -src_to_dst_offset
);
591 src
.x
= src
.visrect
.left
;
592 src
.y
= src
.visrect
.top
;
593 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
594 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
596 dst
.x
= dst
.visrect
.left
;
597 dst
.y
= dst
.visrect
.top
;
598 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
599 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
601 memcpy( dst_info
, src_info
, FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] ));
603 err
= physdev
->funcs
->pPutImage( physdev
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
604 if (err
== ERROR_BAD_FORMAT
)
608 dst_info
->bmiHeader
.biWidth
= dst
.width
;
609 ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info
));
612 err
= convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
.visrect
, dst_info
, ptr
);
614 if (src_bits
.free
) src_bits
.free( &src_bits
);
616 src_bits
.is_copy
= TRUE
;
617 src_bits
.free
= free_heap_bits
;
619 err
= physdev
->funcs
->pPutImage( physdev
, hbitmap
, clip
, dst_info
, &src_bits
, &src
, &dst
, 0 );
622 else err
= ERROR_OUTOFMEMORY
;
627 if (src_bits
.free
) src_bits
.free( &src_bits
);
628 if (clip
) DeleteObject( clip
);
629 GDI_ReleaseObj( hbitmap
);
630 release_dc_ptr( dc
);
631 if (delete_hdc
) DeleteDC(hdc
);
636 /***********************************************************************
637 * SetDIBitsToDevice (GDI32.@)
639 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
640 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
641 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
649 if ((dc
= get_dc_ptr( hdc
)))
651 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBitsToDevice
);
653 ret
= physdev
->funcs
->pSetDIBitsToDevice( physdev
, xDest
, yDest
, cx
, cy
, xSrc
,
654 ySrc
, startscan
, lines
, bits
, info
, coloruse
);
655 release_dc_ptr( dc
);
660 /***********************************************************************
661 * SetDIBColorTable (GDI32.@)
663 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, CONST RGBQUAD
*colors
)
669 if (!(dc
= get_dc_ptr( hdc
))) return 0;
671 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
673 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetDIBColorTable
);
675 /* Check if currently selected bitmap is a DIB */
676 if (bitmap
->color_table
)
678 if (startpos
< bitmap
->nb_colors
)
680 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
681 memcpy(bitmap
->color_table
+ startpos
, colors
, entries
* sizeof(RGBQUAD
));
685 GDI_ReleaseObj( dc
->hBitmap
);
686 physdev
->funcs
->pSetDIBColorTable( physdev
, startpos
, entries
, colors
);
688 release_dc_ptr( dc
);
693 /***********************************************************************
694 * GetDIBColorTable (GDI32.@)
696 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
702 if (!(dc
= get_dc_ptr( hdc
))) return 0;
704 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
706 /* Check if currently selected bitmap is a DIB */
707 if (bitmap
->color_table
)
709 if (startpos
< bitmap
->nb_colors
)
711 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
712 memcpy(colors
, bitmap
->color_table
+ startpos
, entries
* sizeof(RGBQUAD
));
716 GDI_ReleaseObj( dc
->hBitmap
);
718 release_dc_ptr( dc
);
722 static const RGBQUAD DefLogPaletteQuads
[20] = { /* Copy of Default Logical Palette */
723 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
724 { 0x00, 0x00, 0x00, 0x00 },
725 { 0x00, 0x00, 0x80, 0x00 },
726 { 0x00, 0x80, 0x00, 0x00 },
727 { 0x00, 0x80, 0x80, 0x00 },
728 { 0x80, 0x00, 0x00, 0x00 },
729 { 0x80, 0x00, 0x80, 0x00 },
730 { 0x80, 0x80, 0x00, 0x00 },
731 { 0xc0, 0xc0, 0xc0, 0x00 },
732 { 0xc0, 0xdc, 0xc0, 0x00 },
733 { 0xf0, 0xca, 0xa6, 0x00 },
734 { 0xf0, 0xfb, 0xff, 0x00 },
735 { 0xa4, 0xa0, 0xa0, 0x00 },
736 { 0x80, 0x80, 0x80, 0x00 },
737 { 0x00, 0x00, 0xff, 0x00 },
738 { 0x00, 0xff, 0x00, 0x00 },
739 { 0x00, 0xff, 0xff, 0x00 },
740 { 0xff, 0x00, 0x00, 0x00 },
741 { 0xff, 0x00, 0xff, 0x00 },
742 { 0xff, 0xff, 0x00, 0x00 },
743 { 0xff, 0xff, 0xff, 0x00 }
746 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
747 static const DWORD bit_fields_565
[3] = {0xf800, 0x07e0, 0x001f};
748 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
750 static int fill_query_info( BITMAPINFO
*info
, BITMAPOBJ
*bmp
)
752 BITMAPINFOHEADER header
;
754 header
.biSize
= info
->bmiHeader
.biSize
; /* Ensure we don't overwrite the original size when we copy back */
755 header
.biWidth
= bmp
->bitmap
.bmWidth
;
756 header
.biHeight
= bmp
->bitmap
.bmHeight
;
761 header
.biBitCount
= bmp
->dib
->dsBm
.bmBitsPixel
;
762 switch (bmp
->dib
->dsBm
.bmBitsPixel
)
766 header
.biCompression
= BI_BITFIELDS
;
769 header
.biCompression
= BI_RGB
;
775 header
.biCompression
= (bmp
->bitmap
.bmBitsPixel
> 8) ? BI_BITFIELDS
: BI_RGB
;
776 header
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
779 header
.biSizeImage
= get_dib_image_size( (BITMAPINFO
*)&header
);
780 header
.biXPelsPerMeter
= 0;
781 header
.biYPelsPerMeter
= 0;
782 header
.biClrUsed
= 0;
783 header
.biClrImportant
= 0;
785 if ( info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
) )
787 BITMAPCOREHEADER
*coreheader
= (BITMAPCOREHEADER
*)info
;
789 coreheader
->bcWidth
= header
.biWidth
;
790 coreheader
->bcHeight
= header
.biHeight
;
791 coreheader
->bcPlanes
= header
.biPlanes
;
792 coreheader
->bcBitCount
= header
.biBitCount
;
795 info
->bmiHeader
= header
;
797 return abs(bmp
->bitmap
.bmHeight
);
800 /************************************************************************
803 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
805 static void copy_color_info(BITMAPINFO
*dst
, const BITMAPINFO
*src
, UINT coloruse
)
807 unsigned int colors
= get_dib_num_of_colors( src
);
808 RGBQUAD
*src_colors
= (RGBQUAD
*)((char *)src
+ src
->bmiHeader
.biSize
);
810 assert( src
->bmiHeader
.biSize
>= sizeof(BITMAPINFOHEADER
) );
812 if (dst
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
814 BITMAPCOREINFO
*core
= (BITMAPCOREINFO
*)dst
;
815 if (coloruse
== DIB_PAL_COLORS
)
816 memcpy( core
->bmciColors
, src_colors
, colors
* sizeof(WORD
) );
820 for (i
= 0; i
< colors
; i
++)
822 core
->bmciColors
[i
].rgbtRed
= src_colors
[i
].rgbRed
;
823 core
->bmciColors
[i
].rgbtGreen
= src_colors
[i
].rgbGreen
;
824 core
->bmciColors
[i
].rgbtBlue
= src_colors
[i
].rgbBlue
;
830 dst
->bmiHeader
.biClrUsed
= src
->bmiHeader
.biClrUsed
;
831 dst
->bmiHeader
.biSizeImage
= src
->bmiHeader
.biSizeImage
;
833 if (src
->bmiHeader
.biCompression
== BI_BITFIELDS
)
834 /* bitfields are always at bmiColors even in larger structures */
835 memcpy( dst
->bmiColors
, src
->bmiColors
, 3 * sizeof(DWORD
) );
838 void *colorptr
= (char *)dst
+ dst
->bmiHeader
.biSize
;
841 if (coloruse
== DIB_PAL_COLORS
)
842 size
= colors
* sizeof(WORD
);
844 size
= colors
* sizeof(RGBQUAD
);
845 memcpy( colorptr
, src_colors
, size
);
850 static void fill_default_color_table( BITMAPINFO
*info
)
854 switch (info
->bmiHeader
.biBitCount
)
857 info
->bmiColors
[0].rgbRed
= info
->bmiColors
[0].rgbGreen
= info
->bmiColors
[0].rgbBlue
= 0;
858 info
->bmiColors
[0].rgbReserved
= 0;
859 info
->bmiColors
[1].rgbRed
= info
->bmiColors
[1].rgbGreen
= info
->bmiColors
[1].rgbBlue
= 0xff;
860 info
->bmiColors
[1].rgbReserved
= 0;
864 /* The EGA palette is the first and last 8 colours of the default palette
865 with the innermost pair swapped */
866 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 7 * sizeof(RGBQUAD
));
867 memcpy(info
->bmiColors
+ 7, DefLogPaletteQuads
+ 12, 1 * sizeof(RGBQUAD
));
868 memcpy(info
->bmiColors
+ 8, DefLogPaletteQuads
+ 7, 1 * sizeof(RGBQUAD
));
869 memcpy(info
->bmiColors
+ 9, DefLogPaletteQuads
+ 13, 7 * sizeof(RGBQUAD
));
873 memcpy(info
->bmiColors
, DefLogPaletteQuads
, 10 * sizeof(RGBQUAD
));
874 memcpy(info
->bmiColors
+ 246, DefLogPaletteQuads
+ 10, 10 * sizeof(RGBQUAD
));
875 for (i
= 10; i
< 246; i
++)
877 info
->bmiColors
[i
].rgbRed
= (i
& 0x07) << 5;
878 info
->bmiColors
[i
].rgbGreen
= (i
& 0x38) << 2;
879 info
->bmiColors
[i
].rgbBlue
= i
& 0xc0;
880 info
->bmiColors
[i
].rgbReserved
= 0;
885 ERR("called with bitcount %d\n", info
->bmiHeader
.biBitCount
);
889 /******************************************************************************
890 * GetDIBits [GDI32.@]
892 * Retrieves bits of bitmap and copies to buffer.
895 * Success: Number of scan lines copied from bitmap
898 INT WINAPI
GetDIBits(
899 HDC hdc
, /* [in] Handle to device context */
900 HBITMAP hbitmap
, /* [in] Handle to bitmap */
901 UINT startscan
, /* [in] First scan line to set in dest bitmap */
902 UINT lines
, /* [in] Number of scan lines to copy */
903 LPVOID bits
, /* [out] Address of array for bitmap bits */
904 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
905 UINT coloruse
) /* [in] RGB or palette index */
915 char dst_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
916 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_bmibuf
;
917 unsigned int colors
= 0;
921 bitmap_type
= DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
, &planes
, &bpp
, &compr
, &size
);
922 if (bitmap_type
== -1)
924 ERR("Invalid bitmap format\n");
927 if (!(dc
= get_dc_ptr( hdc
)))
929 SetLastError( ERROR_INVALID_PARAMETER
);
933 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
935 release_dc_ptr( dc
);
940 if (bpp
== 0) /* query bitmap info only */
942 lines
= fill_query_info( info
, bmp
);
946 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
947 own copy and transfer the colour info back at the end */
949 dst_info
->bmiHeader
.biSize
= sizeof(dst_info
->bmiHeader
);
950 dst_info
->bmiHeader
.biWidth
= width
;
951 dst_info
->bmiHeader
.biHeight
= height
;
952 dst_info
->bmiHeader
.biPlanes
= planes
;
953 dst_info
->bmiHeader
.biBitCount
= bpp
;
954 dst_info
->bmiHeader
.biCompression
= compr
;
955 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
956 dst_info
->bmiHeader
.biXPelsPerMeter
= 0;
957 dst_info
->bmiHeader
.biYPelsPerMeter
= 0;
958 dst_info
->bmiHeader
.biClrUsed
= 0;
959 dst_info
->bmiHeader
.biClrImportant
= 0;
969 /* If the bitmap object is a dib section at the
970 same color depth then get the color map from it */
971 if (bmp
->dib
&& bpp
== bmp
->dib
->dsBm
.bmBitsPixel
&& coloruse
== DIB_RGB_COLORS
)
973 colors
= min( colors
, bmp
->nb_colors
);
974 if (colors
!= 1 << bpp
) dst_info
->bmiHeader
.biClrUsed
= colors
;
975 memcpy( dst_info
->bmiColors
, bmp
->color_table
, colors
* sizeof(RGBQUAD
) );
978 /* For color DDBs in native depth (mono DDBs always have a black/white palette):
979 Generate the color map from the selected palette. In the DIB_PAL_COLORS
980 case we'll fix up the indices after the format conversion. */
981 else if ( (bpp
> 1 && bpp
== bmp
->bitmap
.bmBitsPixel
) || coloruse
== DIB_PAL_COLORS
)
983 if (!fill_color_table_from_palette( dst_info
, dc
))
990 fill_default_color_table( dst_info
);
995 if (dst_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
996 memcpy( dst_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1000 if (dst_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1004 if (bmp
->dib
->dsBmih
.biCompression
== BI_BITFIELDS
&& bmp
->dib
->dsBmih
.biBitCount
== bpp
)
1005 memcpy( dst_info
->bmiColors
, bmp
->dib
->dsBitfields
, 3 * sizeof(DWORD
) );
1007 memcpy( dst_info
->bmiColors
, bit_fields_555
, sizeof(bit_fields_555
) );
1010 memcpy( dst_info
->bmiColors
, bit_fields_565
, sizeof(bit_fields_565
) );
1016 if (dst_info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1018 if (bmp
->dib
&& bmp
->dib
->dsBmih
.biCompression
== BI_BITFIELDS
&& bmp
->dib
->dsBmih
.biBitCount
== bpp
)
1019 memcpy( dst_info
->bmiColors
, bmp
->dib
->dsBitfields
, 3 * sizeof(DWORD
) );
1021 memcpy( dst_info
->bmiColors
, bit_fields_888
, sizeof(bit_fields_888
) );
1028 char src_bmibuf
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1029 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_bmibuf
;
1030 struct gdi_image_bits src_bits
;
1031 struct bitblt_coords src
, dst
;
1033 int dst_to_src_offset
;
1036 src
.visrect
.left
= 0;
1037 src
.visrect
.top
= 0;
1038 src
.visrect
.right
= bmp
->bitmap
.bmWidth
;
1039 src
.visrect
.bottom
= bmp
->bitmap
.bmHeight
;
1041 dst
.visrect
.left
= 0;
1042 dst
.visrect
.top
= 0;
1043 dst
.visrect
.right
= dst_info
->bmiHeader
.biWidth
;
1044 dst
.visrect
.bottom
= abs( dst_info
->bmiHeader
.biHeight
);
1046 if (startscan
>= dst
.visrect
.bottom
)
1048 lines
= 1; /* yes, this is strange */
1052 if (dst_info
->bmiHeader
.biHeight
> 0)
1054 dst_to_src_offset
= -startscan
;
1055 lines
= min( lines
, dst
.visrect
.bottom
- startscan
);
1056 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.top
= dst
.visrect
.bottom
- lines
;
1060 dst_to_src_offset
= dst
.visrect
.bottom
- lines
- startscan
;
1061 if (dst_to_src_offset
< 0)
1063 dst_to_src_offset
= 0;
1064 lines
= dst
.visrect
.bottom
- startscan
;
1066 if (lines
< dst
.visrect
.bottom
) dst
.visrect
.bottom
= lines
;
1069 offset_rect( &dst
.visrect
, 0, dst_to_src_offset
);
1070 empty_rect
= !intersect_rect( &src
.visrect
, &src
.visrect
, &dst
.visrect
);
1071 dst
.visrect
= src
.visrect
;
1072 offset_rect( &dst
.visrect
, 0, -dst_to_src_offset
);
1074 if (dst_info
->bmiHeader
.biHeight
> 0)
1076 if (dst
.visrect
.bottom
< dst_info
->bmiHeader
.biHeight
)
1078 int pad_lines
= min( dst_info
->bmiHeader
.biHeight
- dst
.visrect
.bottom
, lines
);
1079 int pad_bytes
= pad_lines
* get_dib_stride( width
, bpp
);
1080 memset( bits
, 0, pad_bytes
);
1081 bits
= (char *)bits
+ pad_bytes
;
1086 if (dst
.visrect
.bottom
< lines
)
1088 int pad_lines
= lines
- dst
.visrect
.bottom
, stride
= get_dib_stride( width
, bpp
);
1089 int pad_bytes
= pad_lines
* stride
;
1090 memset( (char *)bits
+ dst
.visrect
.bottom
* stride
, 0, pad_bytes
);
1100 src
.x
= src
.visrect
.left
;
1101 src
.y
= src
.visrect
.top
;
1102 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1103 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1107 err
= bmp
->funcs
->pGetImage( NULL
, hbitmap
, src_info
, &src_bits
, &src
);
1115 if (src_info
->bmiHeader
.biBitCount
<= 8 && src_info
->bmiHeader
.biClrUsed
== 0)
1118 memcpy( src_info
->bmiColors
, bmp
->color_table
, bmp
->nb_colors
* sizeof(RGBQUAD
) );
1120 fill_default_color_table( src_info
);
1123 if(dst_info
->bmiHeader
.biHeight
> 0)
1124 dst_info
->bmiHeader
.biHeight
= src
.height
;
1126 dst_info
->bmiHeader
.biHeight
= -src
.height
;
1128 convert_bitmapinfo( src_info
, src_bits
.ptr
, &src
.visrect
, dst_info
, bits
);
1129 if (src_bits
.free
) src_bits
.free( &src_bits
);
1131 else lines
= abs(height
);
1134 if (coloruse
== DIB_PAL_COLORS
)
1136 WORD
*index
= (WORD
*)dst_info
->bmiColors
;
1137 for (i
= 0; i
< colors
; i
++, index
++)
1141 copy_color_info( info
, dst_info
, coloruse
);
1144 release_dc_ptr( dc
);
1145 GDI_ReleaseObj( hbitmap
);
1150 /***********************************************************************
1151 * CreateDIBitmap (GDI32.@)
1153 * Creates a DDB (device dependent bitmap) from a DIB.
1154 * The DDB will have the same color depth as the reference DC.
1156 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1157 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1166 if (!header
) return 0;
1168 if (DIB_GetBitmapInfo( header
, &width
, &height
, &planes
, &bpp
, &compr
, &size
) == -1) return 0;
1172 TRACE("Bitmap has a negative width\n");
1176 /* Top-down DIBs have a negative height */
1177 if (height
< 0) height
= -height
;
1179 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1180 hdc
, header
, init
, bits
, data
, coloruse
, width
, height
, bpp
, compr
);
1183 handle
= CreateBitmap( width
, height
, 1, 1, NULL
);
1185 handle
= CreateCompatibleBitmap( hdc
, width
, height
);
1189 if (init
& CBM_INIT
)
1191 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1193 DeleteObject( handle
);
1202 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1203 static void DIB_CopyColorTable( DC
*dc
, BITMAPOBJ
*bmp
, WORD coloruse
, const BITMAPINFO
*info
)
1205 RGBQUAD
*colorTable
;
1206 unsigned int colors
, i
;
1207 BOOL core_info
= info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
);
1211 colors
= 1 << ((const BITMAPCOREINFO
*) info
)->bmciHeader
.bcBitCount
;
1215 colors
= get_dib_num_of_colors( info
);
1219 ERR("called with >256 colors!\n");
1223 if (!(colorTable
= HeapAlloc(GetProcessHeap(), 0, colors
* sizeof(RGBQUAD
) ))) return;
1225 if(coloruse
== DIB_RGB_COLORS
)
1229 /* Convert RGBTRIPLEs to RGBQUADs */
1230 for (i
=0; i
< colors
; i
++)
1232 colorTable
[i
].rgbRed
= ((const BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtRed
;
1233 colorTable
[i
].rgbGreen
= ((const BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtGreen
;
1234 colorTable
[i
].rgbBlue
= ((const BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtBlue
;
1235 colorTable
[i
].rgbReserved
= 0;
1240 memcpy(colorTable
, (const BYTE
*) info
+ (WORD
) info
->bmiHeader
.biSize
, colors
* sizeof(RGBQUAD
));
1245 PALETTEENTRY entries
[256];
1246 const WORD
*index
= (const WORD
*) ((const BYTE
*) info
+ (WORD
) info
->bmiHeader
.biSize
);
1247 UINT count
= GetPaletteEntries( dc
->hPalette
, 0, colors
, entries
);
1249 for (i
= 0; i
< colors
; i
++, index
++)
1251 PALETTEENTRY
*entry
= &entries
[*index
% count
];
1252 colorTable
[i
].rgbRed
= entry
->peRed
;
1253 colorTable
[i
].rgbGreen
= entry
->peGreen
;
1254 colorTable
[i
].rgbBlue
= entry
->peBlue
;
1255 colorTable
[i
].rgbReserved
= 0;
1258 bmp
->color_table
= colorTable
;
1259 bmp
->nb_colors
= colors
;
1262 /***********************************************************************
1263 * CreateDIBSection (GDI32.@)
1265 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, CONST BITMAPINFO
*bmi
, UINT usage
,
1266 VOID
**bits
, HANDLE section
, DWORD offset
)
1270 BOOL bDesktopDC
= FALSE
;
1276 DWORD compression
, sizeImage
;
1277 void *mapBits
= NULL
;
1280 if(bits
) *bits
= NULL
;
1284 if (((bitmap_type
= DIB_GetBitmapInfo( &bmi
->bmiHeader
, &width
, &height
,
1285 &planes
, &bpp
, &compression
, &sizeImage
)) == -1))
1292 if (compression
== BI_BITFIELDS
) break;
1298 if (compression
== BI_RGB
) break;
1301 WARN( "invalid %u bpp compression %u\n", bpp
, compression
);
1305 if (!(dib
= HeapAlloc( GetProcessHeap(), 0, sizeof(*dib
) ))) return 0;
1307 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1308 width
, height
, planes
, bpp
, compression
== BI_BITFIELDS
? "BI_BITFIELDS" : "BI_RGB",
1309 sizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1311 dib
->dsBm
.bmType
= 0;
1312 dib
->dsBm
.bmWidth
= width
;
1313 dib
->dsBm
.bmHeight
= height
>= 0 ? height
: -height
;
1314 dib
->dsBm
.bmWidthBytes
= get_dib_stride( width
, bpp
);
1315 dib
->dsBm
.bmPlanes
= planes
;
1316 dib
->dsBm
.bmBitsPixel
= bpp
;
1317 dib
->dsBm
.bmBits
= NULL
;
1319 if (!bitmap_type
) /* core header */
1321 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1322 dib
->dsBmih
.biSize
= sizeof(BITMAPINFOHEADER
);
1323 dib
->dsBmih
.biWidth
= width
;
1324 dib
->dsBmih
.biHeight
= height
;
1325 dib
->dsBmih
.biPlanes
= planes
;
1326 dib
->dsBmih
.biBitCount
= bpp
;
1327 dib
->dsBmih
.biCompression
= compression
;
1328 dib
->dsBmih
.biXPelsPerMeter
= 0;
1329 dib
->dsBmih
.biYPelsPerMeter
= 0;
1330 dib
->dsBmih
.biClrUsed
= 0;
1331 dib
->dsBmih
.biClrImportant
= 0;
1335 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1336 dib
->dsBmih
= bmi
->bmiHeader
;
1337 dib
->dsBmih
.biSize
= sizeof(BITMAPINFOHEADER
);
1340 /* set number of entries in bmi.bmiColors table */
1342 dib
->dsBmih
.biClrUsed
= 1 << bpp
;
1344 dib
->dsBmih
.biSizeImage
= dib
->dsBm
.bmWidthBytes
* dib
->dsBm
.bmHeight
;
1346 /* set dsBitfields values */
1347 dib
->dsBitfields
[0] = dib
->dsBitfields
[1] = dib
->dsBitfields
[2] = 0;
1349 if((bpp
== 15 || bpp
== 16) && compression
== BI_RGB
)
1351 /* In this case Windows changes biCompression to BI_BITFIELDS,
1352 however for now we won't do this, as there are a lot
1353 of places where BI_BITFIELDS is currently unsupported. */
1355 /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
1356 dib
->dsBitfields
[0] = 0x7c00;
1357 dib
->dsBitfields
[1] = 0x03e0;
1358 dib
->dsBitfields
[2] = 0x001f;
1360 else if(compression
== BI_BITFIELDS
)
1362 dib
->dsBitfields
[0] = *(const DWORD
*)bmi
->bmiColors
;
1363 dib
->dsBitfields
[1] = *((const DWORD
*)bmi
->bmiColors
+ 1);
1364 dib
->dsBitfields
[2] = *((const DWORD
*)bmi
->bmiColors
+ 2);
1367 /* get storage location for DIB bits */
1371 SYSTEM_INFO SystemInfo
;
1375 GetSystemInfo( &SystemInfo
);
1376 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1377 mapSize
= dib
->dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1378 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1379 if (mapBits
) dib
->dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1384 dib
->dsBm
.bmBits
= VirtualAlloc( NULL
, dib
->dsBmih
.biSizeImage
,
1385 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1387 dib
->dshSection
= section
;
1388 dib
->dsOffset
= offset
;
1390 if (!dib
->dsBm
.bmBits
)
1392 HeapFree( GetProcessHeap(), 0, dib
);
1396 /* If the reference hdc is null, take the desktop dc */
1399 hdc
= CreateCompatibleDC(0);
1403 if (!(dc
= get_dc_ptr( hdc
))) goto error
;
1405 /* create Device Dependent Bitmap and add DIB pointer */
1406 ret
= CreateBitmap( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmHeight
, 1,
1407 (bpp
== 1) ? 1 : GetDeviceCaps(hdc
, BITSPIXEL
), NULL
);
1409 if (ret
&& ((bmp
= GDI_GetObjPtr(ret
, OBJ_BITMAP
))))
1411 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pCreateDIBSection
);
1413 bmp
->funcs
= physdev
->funcs
;
1414 /* create local copy of DIB palette */
1415 if (bpp
<= 8) DIB_CopyColorTable( dc
, bmp
, usage
, bmi
);
1416 GDI_ReleaseObj( ret
);
1418 if (!physdev
->funcs
->pCreateDIBSection( physdev
, ret
, bmi
, usage
))
1420 DeleteObject( ret
);
1425 release_dc_ptr( dc
);
1426 if (bDesktopDC
) DeleteDC( hdc
);
1427 if (ret
&& bits
) *bits
= dib
->dsBm
.bmBits
;
1431 if (bDesktopDC
) DeleteDC( hdc
);
1432 if (section
) UnmapViewOfFile( mapBits
);
1433 else if (!offset
) VirtualFree( dib
->dsBm
.bmBits
, 0, MEM_RELEASE
);
1434 HeapFree( GetProcessHeap(), 0, dib
);