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
);
77 Some of the following helper functions are duplicated in
81 /***********************************************************************
82 * DIB_GetDIBWidthBytes
84 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
86 int DIB_GetDIBWidthBytes( int width
, int depth
)
92 case 1: words
= (width
+ 31) / 32; break;
93 case 4: words
= (width
+ 7) / 8; break;
94 case 8: words
= (width
+ 3) / 4; break;
96 case 16: words
= (width
+ 1) / 2; break;
97 case 24: words
= (width
* 3 + 3)/4; break;
100 WARN("(%d): Unsupported depth\n", depth
);
108 /***********************************************************************
109 * DIB_GetDIBImageBytes
111 * Return the number of bytes used to hold the image in a DIB bitmap.
113 int DIB_GetDIBImageBytes( int width
, int height
, int depth
)
115 return DIB_GetDIBWidthBytes( width
, depth
) * abs( height
);
119 /***********************************************************************
122 * Return the size of the bitmap info structure including color table.
124 int bitmap_info_size( const BITMAPINFO
* info
, WORD coloruse
)
126 int colors
, masks
= 0;
128 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
130 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
131 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
132 return sizeof(BITMAPCOREHEADER
) + colors
*
133 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
135 else /* assume BITMAPINFOHEADER */
137 colors
= info
->bmiHeader
.biClrUsed
;
138 if (colors
> 256) colors
= 256;
139 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
140 colors
= 1 << info
->bmiHeader
.biBitCount
;
141 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
142 return sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
) + colors
*
143 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
148 /***********************************************************************
151 * Get the info from a bitmap header.
152 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
154 int DIB_GetBitmapInfo( const BITMAPINFOHEADER
*header
, LONG
*width
,
155 LONG
*height
, WORD
*planes
, WORD
*bpp
, DWORD
*compr
, DWORD
*size
)
157 if (header
->biSize
== sizeof(BITMAPCOREHEADER
))
159 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)header
;
160 *width
= core
->bcWidth
;
161 *height
= core
->bcHeight
;
162 *planes
= core
->bcPlanes
;
163 *bpp
= core
->bcBitCount
;
168 if (header
->biSize
>= sizeof(BITMAPINFOHEADER
)) /* assume BITMAPINFOHEADER */
170 *width
= header
->biWidth
;
171 *height
= header
->biHeight
;
172 *planes
= header
->biPlanes
;
173 *bpp
= header
->biBitCount
;
174 *compr
= header
->biCompression
;
175 *size
= header
->biSizeImage
;
178 ERR("(%d): unknown/wrong size for header\n", header
->biSize
);
183 /***********************************************************************
184 * StretchDIBits (GDI32.@)
186 INT WINAPI
StretchDIBits(HDC hdc
, INT xDst
, INT yDst
, INT widthDst
,
187 INT heightDst
, INT xSrc
, INT ySrc
, INT widthSrc
,
188 INT heightSrc
, const void *bits
,
189 const BITMAPINFO
*info
, UINT wUsage
, DWORD dwRop
)
197 if (!(dc
= get_dc_ptr( hdc
))) return 0;
199 if(dc
->funcs
->pStretchDIBits
)
202 ret
= dc
->funcs
->pStretchDIBits(dc
->physDev
, xDst
, yDst
, widthDst
,
203 heightDst
, xSrc
, ySrc
, widthSrc
,
204 heightSrc
, bits
, info
, wUsage
, dwRop
);
205 release_dc_ptr( dc
);
207 else /* use StretchBlt */
214 BOOL fastpath
= FALSE
;
216 release_dc_ptr( dc
);
218 if (DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
, &planes
, &bpp
, &compr
, &size
) == -1)
220 ERR("Invalid bitmap\n");
226 ERR("Bitmap has a negative width\n");
230 hBitmap
= GetCurrentObject(hdc
, OBJ_BITMAP
);
232 if (xDst
== 0 && yDst
== 0 && xSrc
== 0 && ySrc
== 0 &&
233 widthDst
== widthSrc
&& heightDst
== heightSrc
&&
234 info
->bmiHeader
.biCompression
== BI_RGB
&&
238 if ((bmp
= GDI_GetObjPtr( hBitmap
, OBJ_BITMAP
)))
240 if (bmp
->bitmap
.bmBitsPixel
== bpp
&&
241 bmp
->bitmap
.bmWidth
== widthSrc
&&
242 bmp
->bitmap
.bmHeight
== heightSrc
&&
243 bmp
->bitmap
.bmPlanes
== planes
)
245 GDI_ReleaseObj( hBitmap
);
252 TRACE("using fast path\n");
253 ret
= SetDIBits( hdc
, hBitmap
, 0, height
, bits
, info
, wUsage
);
257 /* slow path - need to use StretchBlt */
259 HPALETTE hpal
= NULL
;
262 hdcMem
= CreateCompatibleDC( hdc
);
263 hBitmap
= CreateCompatibleBitmap(hdc
, width
, height
);
264 hOldBitmap
= SelectObject( hdcMem
, hBitmap
);
265 if(wUsage
== DIB_PAL_COLORS
)
267 hpal
= GetCurrentObject(hdc
, OBJ_PAL
);
268 hpal
= SelectPalette(hdcMem
, hpal
, FALSE
);
271 if (info
->bmiHeader
.biCompression
== BI_RLE4
||
272 info
->bmiHeader
.biCompression
== BI_RLE8
) {
274 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
275 * contain all the rectangle described in bmiHeader, but only part of it.
276 * This mean that those undescribed pixels must be left untouched.
277 * So, we first copy on a memory bitmap the current content of the
278 * destination rectangle, blit the DIB bits on top of it - hence leaving
279 * the gaps untouched -, and blitting the rectangle back.
280 * This insure that gaps are untouched on the destination rectangle
281 * Not doing so leads to trashed images (the gaps contain what was on the
282 * memory bitmap => generally black or garbage)
283 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
284 * another speed vs correctness issue. Anyway, if speed is needed, then the
285 * pStretchDIBits function shall be implemented.
289 /* copy existing bitmap from destination dc */
290 StretchBlt( hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
,
291 widthSrc
, heightSrc
, hdc
, xDst
, yDst
, widthDst
, heightDst
,
295 ret
= SetDIBits(hdcMem
, hBitmap
, 0, height
, bits
, info
, wUsage
);
297 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
298 left (negative biHeight) */
299 if (ret
) StretchBlt( hdc
, xDst
, yDst
, widthDst
, heightDst
,
300 hdcMem
, xSrc
, abs(height
) - heightSrc
- ySrc
,
301 widthSrc
, heightSrc
, dwRop
);
303 SelectPalette(hdcMem
, hpal
, FALSE
);
304 SelectObject( hdcMem
, hOldBitmap
);
306 DeleteObject( hBitmap
);
313 /******************************************************************************
314 * SetDIBits [GDI32.@]
316 * Sets pixels in a bitmap using colors from DIB.
319 * hdc [I] Handle to device context
320 * hbitmap [I] Handle to bitmap
321 * startscan [I] Starting scan line
322 * lines [I] Number of scan lines
323 * bits [I] Array of bitmap bits
324 * info [I] Address of structure with data
325 * coloruse [I] Type of color indexes to use
328 * Success: Number of scan lines copied
331 INT WINAPI
SetDIBits( HDC hdc
, HBITMAP hbitmap
, UINT startscan
,
332 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
339 if (!(dc
= get_dc_ptr( hdc
)))
341 if (coloruse
== DIB_RGB_COLORS
) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
347 if (!(bitmap
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
349 release_dc_ptr( dc
);
353 if (!bitmap
->funcs
&& !BITMAP_SetOwnerDC( hbitmap
, dc
)) goto done
;
358 if (bitmap
->funcs
!= dc
->funcs
)
359 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap
, hdc
);
360 else if (dc
->funcs
->pSetDIBits
)
361 result
= dc
->funcs
->pSetDIBits( dc
->physDev
, hbitmap
, startscan
, lines
,
362 bits
, info
, coloruse
);
366 GDI_ReleaseObj( hbitmap
);
367 release_dc_ptr( dc
);
372 /***********************************************************************
373 * SetDIBitsToDevice (GDI32.@)
375 INT WINAPI
SetDIBitsToDevice(HDC hdc
, INT xDest
, INT yDest
, DWORD cx
,
376 DWORD cy
, INT xSrc
, INT ySrc
, UINT startscan
,
377 UINT lines
, LPCVOID bits
, const BITMAPINFO
*info
,
385 if (!(dc
= get_dc_ptr( hdc
))) return 0;
387 if(dc
->funcs
->pSetDIBitsToDevice
)
390 ret
= dc
->funcs
->pSetDIBitsToDevice( dc
->physDev
, xDest
, yDest
, cx
, cy
, xSrc
,
391 ySrc
, startscan
, lines
, bits
,
395 FIXME("unimplemented on hdc %p\n", hdc
);
399 release_dc_ptr( dc
);
403 /***********************************************************************
404 * SetDIBColorTable (GDI32.@)
406 UINT WINAPI
SetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, CONST RGBQUAD
*colors
)
412 if (!(dc
= get_dc_ptr( hdc
))) return 0;
414 if ((bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
)))
416 /* Check if currently selected bitmap is a DIB */
417 if (bitmap
->color_table
)
419 if (startpos
< bitmap
->nb_colors
)
421 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
422 memcpy(bitmap
->color_table
+ startpos
, colors
, entries
* sizeof(RGBQUAD
));
426 GDI_ReleaseObj( dc
->hBitmap
);
429 if (dc
->funcs
->pSetDIBColorTable
)
430 dc
->funcs
->pSetDIBColorTable(dc
->physDev
, startpos
, entries
, colors
);
432 release_dc_ptr( dc
);
437 /***********************************************************************
438 * GetDIBColorTable (GDI32.@)
440 UINT WINAPI
GetDIBColorTable( HDC hdc
, UINT startpos
, UINT entries
, RGBQUAD
*colors
)
445 if (!(dc
= get_dc_ptr( hdc
))) return 0;
447 if (dc
->funcs
->pGetDIBColorTable
)
448 result
= dc
->funcs
->pGetDIBColorTable(dc
->physDev
, startpos
, entries
, colors
);
451 BITMAPOBJ
*bitmap
= GDI_GetObjPtr( dc
->hBitmap
, OBJ_BITMAP
);
454 /* Check if currently selected bitmap is a DIB */
455 if (bitmap
->color_table
)
457 if (startpos
< bitmap
->nb_colors
)
459 if (startpos
+ entries
> bitmap
->nb_colors
) entries
= bitmap
->nb_colors
- startpos
;
460 memcpy(colors
, bitmap
->color_table
+ startpos
, entries
* sizeof(RGBQUAD
));
464 GDI_ReleaseObj( dc
->hBitmap
);
467 release_dc_ptr( dc
);
471 /* FIXME the following two structs should be combined with __sysPalTemplate in
472 objects/color.c - this should happen after de-X11-ing both of these
474 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
477 static const RGBQUAD EGAColorsQuads
[16] = {
478 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
479 { 0x00, 0x00, 0x00, 0x00 },
480 { 0x00, 0x00, 0x80, 0x00 },
481 { 0x00, 0x80, 0x00, 0x00 },
482 { 0x00, 0x80, 0x80, 0x00 },
483 { 0x80, 0x00, 0x00, 0x00 },
484 { 0x80, 0x00, 0x80, 0x00 },
485 { 0x80, 0x80, 0x00, 0x00 },
486 { 0x80, 0x80, 0x80, 0x00 },
487 { 0xc0, 0xc0, 0xc0, 0x00 },
488 { 0x00, 0x00, 0xff, 0x00 },
489 { 0x00, 0xff, 0x00, 0x00 },
490 { 0x00, 0xff, 0xff, 0x00 },
491 { 0xff, 0x00, 0x00, 0x00 },
492 { 0xff, 0x00, 0xff, 0x00 },
493 { 0xff, 0xff, 0x00, 0x00 },
494 { 0xff, 0xff, 0xff, 0x00 }
497 static const RGBTRIPLE EGAColorsTriples
[16] = {
498 /* rgbBlue, rgbGreen, rgbRed */
499 { 0x00, 0x00, 0x00 },
500 { 0x00, 0x00, 0x80 },
501 { 0x00, 0x80, 0x00 },
502 { 0x00, 0x80, 0x80 },
503 { 0x80, 0x00, 0x00 },
504 { 0x80, 0x00, 0x80 },
505 { 0x80, 0x80, 0x00 },
506 { 0x80, 0x80, 0x80 },
507 { 0xc0, 0xc0, 0xc0 },
508 { 0x00, 0x00, 0xff },
509 { 0x00, 0xff, 0x00 },
510 { 0x00, 0xff, 0xff },
511 { 0xff, 0x00, 0x00 } ,
512 { 0xff, 0x00, 0xff },
513 { 0xff, 0xff, 0x00 },
517 static const RGBQUAD DefLogPaletteQuads
[20] = { /* Copy of Default Logical Palette */
518 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
519 { 0x00, 0x00, 0x00, 0x00 },
520 { 0x00, 0x00, 0x80, 0x00 },
521 { 0x00, 0x80, 0x00, 0x00 },
522 { 0x00, 0x80, 0x80, 0x00 },
523 { 0x80, 0x00, 0x00, 0x00 },
524 { 0x80, 0x00, 0x80, 0x00 },
525 { 0x80, 0x80, 0x00, 0x00 },
526 { 0xc0, 0xc0, 0xc0, 0x00 },
527 { 0xc0, 0xdc, 0xc0, 0x00 },
528 { 0xf0, 0xca, 0xa6, 0x00 },
529 { 0xf0, 0xfb, 0xff, 0x00 },
530 { 0xa4, 0xa0, 0xa0, 0x00 },
531 { 0x80, 0x80, 0x80, 0x00 },
532 { 0x00, 0x00, 0xf0, 0x00 },
533 { 0x00, 0xff, 0x00, 0x00 },
534 { 0x00, 0xff, 0xff, 0x00 },
535 { 0xff, 0x00, 0x00, 0x00 },
536 { 0xff, 0x00, 0xff, 0x00 },
537 { 0xff, 0xff, 0x00, 0x00 },
538 { 0xff, 0xff, 0xff, 0x00 }
541 static const RGBTRIPLE DefLogPaletteTriples
[20] = { /* Copy of Default Logical Palette */
542 /* rgbBlue, rgbGreen, rgbRed */
543 { 0x00, 0x00, 0x00 },
544 { 0x00, 0x00, 0x80 },
545 { 0x00, 0x80, 0x00 },
546 { 0x00, 0x80, 0x80 },
547 { 0x80, 0x00, 0x00 },
548 { 0x80, 0x00, 0x80 },
549 { 0x80, 0x80, 0x00 },
550 { 0xc0, 0xc0, 0xc0 },
551 { 0xc0, 0xdc, 0xc0 },
552 { 0xf0, 0xca, 0xa6 },
553 { 0xf0, 0xfb, 0xff },
554 { 0xa4, 0xa0, 0xa0 },
555 { 0x80, 0x80, 0x80 },
556 { 0x00, 0x00, 0xf0 },
557 { 0x00, 0xff, 0x00 },
558 { 0x00, 0xff, 0xff },
559 { 0xff, 0x00, 0x00 },
560 { 0xff, 0x00, 0xff },
561 { 0xff, 0xff, 0x00 },
566 /******************************************************************************
567 * GetDIBits [GDI32.@]
569 * Retrieves bits of bitmap and copies to buffer.
572 * Success: Number of scan lines copied from bitmap
575 INT WINAPI
GetDIBits(
576 HDC hdc
, /* [in] Handle to device context */
577 HBITMAP hbitmap
, /* [in] Handle to bitmap */
578 UINT startscan
, /* [in] First scan line to set in dest bitmap */
579 UINT lines
, /* [in] Number of scan lines to copy */
580 LPVOID bits
, /* [out] Address of array for bitmap bits */
581 BITMAPINFO
* info
, /* [out] Address of structure with bitmap data */
582 UINT coloruse
) /* [in] RGB or palette index */
594 RGBTRIPLE
* rgbTriples
;
599 bitmap_type
= DIB_GetBitmapInfo( &info
->bmiHeader
, &width
, &height
, &planes
, &bpp
, &compr
, &size
);
600 if (bitmap_type
== -1)
602 ERR("Invalid bitmap format\n");
605 core_header
= (bitmap_type
== 0);
606 if (!(dc
= get_dc_ptr( hdc
)))
608 SetLastError( ERROR_INVALID_PARAMETER
);
612 if (!(bmp
= GDI_GetObjPtr( hbitmap
, OBJ_BITMAP
)))
614 release_dc_ptr( dc
);
618 colorPtr
= (LPBYTE
) info
+ (WORD
) info
->bmiHeader
.biSize
;
619 rgbTriples
= colorPtr
;
622 /* Transfer color info */
626 case 0: /* query bitmap info only */
629 BITMAPCOREHEADER
* coreheader
= (BITMAPCOREHEADER
*) info
;
630 coreheader
->bcWidth
= bmp
->bitmap
.bmWidth
;
631 coreheader
->bcHeight
= bmp
->bitmap
.bmHeight
;
632 coreheader
->bcPlanes
= 1;
633 coreheader
->bcBitCount
= bmp
->bitmap
.bmBitsPixel
;
637 info
->bmiHeader
.biWidth
= bmp
->bitmap
.bmWidth
;
638 info
->bmiHeader
.biHeight
= bmp
->bitmap
.bmHeight
;
639 info
->bmiHeader
.biPlanes
= 1;
640 info
->bmiHeader
.biSizeImage
=
641 DIB_GetDIBImageBytes( bmp
->bitmap
.bmWidth
,
642 bmp
->bitmap
.bmHeight
,
643 bmp
->bitmap
.bmBitsPixel
);
644 info
->bmiHeader
.biCompression
= (bmp
->bitmap
.bmBitsPixel
> 8) ? BI_BITFIELDS
: BI_RGB
;
645 switch(bmp
->bitmap
.bmBitsPixel
)
648 info
->bmiHeader
.biBitCount
= 16;
651 info
->bmiHeader
.biBitCount
= 32;
654 info
->bmiHeader
.biBitCount
= bmp
->bitmap
.bmBitsPixel
;
657 info
->bmiHeader
.biXPelsPerMeter
= 0;
658 info
->bmiHeader
.biYPelsPerMeter
= 0;
659 info
->bmiHeader
.biClrUsed
= 0;
660 info
->bmiHeader
.biClrImportant
= 0;
662 /* Windows 2000 doesn't touch the additional struct members if
663 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
665 lines
= abs(bmp
->bitmap
.bmHeight
);
671 if (!core_header
) info
->bmiHeader
.biClrUsed
= 0;
673 /* If the bitmap object already has a dib section at the
674 same color depth then get the color map from it */
675 if (bmp
->dib
&& bmp
->dib
->dsBm
.bmBitsPixel
== bpp
) {
676 if(coloruse
== DIB_RGB_COLORS
) {
677 unsigned int colors
= min( bmp
->nb_colors
, 1 << bpp
);
681 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
682 RGBTRIPLE
* index
= rgbTriples
;
684 for (i
=0; i
< colors
; i
++, index
++)
686 index
->rgbtRed
= bmp
->color_table
[i
].rgbRed
;
687 index
->rgbtGreen
= bmp
->color_table
[i
].rgbGreen
;
688 index
->rgbtBlue
= bmp
->color_table
[i
].rgbBlue
;
693 if (colors
!= 1 << bpp
) info
->bmiHeader
.biClrUsed
= colors
;
694 memcpy(colorPtr
, bmp
->color_table
, colors
* sizeof(RGBQUAD
));
698 WORD
*index
= colorPtr
;
699 for(i
= 0; i
< 1 << info
->bmiHeader
.biBitCount
; i
++, index
++)
704 if (coloruse
== DIB_PAL_COLORS
) {
705 for (i
= 0; i
< (1 << bpp
); i
++)
706 ((WORD
*)colorPtr
)[i
] = (WORD
)i
;
708 else if(bpp
> 1 && bpp
== bmp
->bitmap
.bmBitsPixel
) {
709 /* For color DDBs in native depth (mono DDBs always have
710 a black/white palette):
711 Generate the color map from the selected palette */
712 PALETTEENTRY palEntry
[256];
714 memset( palEntry
, 0, sizeof(palEntry
) );
715 if (!GetPaletteEntries( dc
->hPalette
, 0, 1 << bmp
->bitmap
.bmBitsPixel
, palEntry
))
717 release_dc_ptr( dc
);
718 GDI_ReleaseObj( hbitmap
);
721 for (i
= 0; i
< (1 << bmp
->bitmap
.bmBitsPixel
); i
++) {
724 rgbTriples
[i
].rgbtRed
= palEntry
[i
].peRed
;
725 rgbTriples
[i
].rgbtGreen
= palEntry
[i
].peGreen
;
726 rgbTriples
[i
].rgbtBlue
= palEntry
[i
].peBlue
;
730 rgbQuads
[i
].rgbRed
= palEntry
[i
].peRed
;
731 rgbQuads
[i
].rgbGreen
= palEntry
[i
].peGreen
;
732 rgbQuads
[i
].rgbBlue
= palEntry
[i
].peBlue
;
733 rgbQuads
[i
].rgbReserved
= 0;
741 rgbTriples
[0].rgbtRed
= rgbTriples
[0].rgbtGreen
=
742 rgbTriples
[0].rgbtBlue
= 0;
743 rgbTriples
[1].rgbtRed
= rgbTriples
[1].rgbtGreen
=
744 rgbTriples
[1].rgbtBlue
= 0xff;
748 rgbQuads
[0].rgbRed
= rgbQuads
[0].rgbGreen
=
749 rgbQuads
[0].rgbBlue
= 0;
750 rgbQuads
[0].rgbReserved
= 0;
751 rgbQuads
[1].rgbRed
= rgbQuads
[1].rgbGreen
=
752 rgbQuads
[1].rgbBlue
= 0xff;
753 rgbQuads
[1].rgbReserved
= 0;
759 memcpy(colorPtr
, EGAColorsTriples
, sizeof(EGAColorsTriples
));
761 memcpy(colorPtr
, EGAColorsQuads
, sizeof(EGAColorsQuads
));
772 memcpy(rgbTriples
, DefLogPaletteTriples
,
773 10 * sizeof(RGBTRIPLE
));
774 memcpy(rgbTriples
+ 246, DefLogPaletteTriples
+ 10,
775 10 * sizeof(RGBTRIPLE
));
776 color
= rgbTriples
+ 10;
777 for(r
= 0; r
<= 5; r
++) /* FIXME */
778 for(g
= 0; g
<= 5; g
++)
779 for(b
= 0; b
<= 5; b
++) {
780 color
->rgbtRed
= (r
* 0xff) / 5;
781 color
->rgbtGreen
= (g
* 0xff) / 5;
782 color
->rgbtBlue
= (b
* 0xff) / 5;
791 memcpy(rgbQuads
, DefLogPaletteQuads
,
792 10 * sizeof(RGBQUAD
));
793 memcpy(rgbQuads
+ 246, DefLogPaletteQuads
+ 10,
794 10 * sizeof(RGBQUAD
));
795 color
= rgbQuads
+ 10;
796 for(r
= 0; r
<= 5; r
++) /* FIXME */
797 for(g
= 0; g
<= 5; g
++)
798 for(b
= 0; b
<= 5; b
++) {
799 color
->rgbRed
= (r
* 0xff) / 5;
800 color
->rgbGreen
= (g
* 0xff) / 5;
801 color
->rgbBlue
= (b
* 0xff) / 5;
802 color
->rgbReserved
= 0;
813 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
815 ((PDWORD
)info
->bmiColors
)[0] = 0x7c00;
816 ((PDWORD
)info
->bmiColors
)[1] = 0x03e0;
817 ((PDWORD
)info
->bmiColors
)[2] = 0x001f;
822 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
824 ((PDWORD
)info
->bmiColors
)[0] = 0xf800;
825 ((PDWORD
)info
->bmiColors
)[1] = 0x07e0;
826 ((PDWORD
)info
->bmiColors
)[2] = 0x001f;
832 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
834 ((PDWORD
)info
->bmiColors
)[0] = 0xff0000;
835 ((PDWORD
)info
->bmiColors
)[1] = 0x00ff00;
836 ((PDWORD
)info
->bmiColors
)[2] = 0x0000ff;
843 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
844 if(bmp
->dib
&& bmp
->dib
->dsBm
.bmBitsPixel
>= 15 && bpp
>= 15)
846 /*FIXME: Only RGB dibs supported for now */
847 unsigned int srcwidth
= bmp
->dib
->dsBm
.bmWidth
, srcwidthb
= bmp
->dib
->dsBm
.bmWidthBytes
;
848 unsigned int dstwidth
= width
;
849 int dstwidthb
= DIB_GetDIBWidthBytes( width
, bpp
);
850 LPBYTE dbits
= bits
, sbits
= (LPBYTE
) bmp
->dib
->dsBm
.bmBits
+ (startscan
* srcwidthb
);
851 unsigned int x
, y
, width
, widthb
;
853 if ((height
< 0) ^ (bmp
->dib
->dsBmih
.biHeight
< 0))
855 dbits
= (LPBYTE
)bits
+ (dstwidthb
* (lines
-1));
856 dstwidthb
= -dstwidthb
;
862 case 16: /* 16 bpp dstDIB */
864 LPWORD dstbits
= (LPWORD
)dbits
;
865 WORD rmask
= 0x7c00, gmask
= 0x03e0, bmask
= 0x001f;
867 /* FIXME: BI_BITFIELDS not supported yet */
869 switch(bmp
->dib
->dsBm
.bmBitsPixel
) {
871 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
873 widthb
= min(srcwidthb
, abs(dstwidthb
));
874 /* FIXME: BI_BITFIELDS not supported yet */
875 for (y
= 0; y
< lines
; y
++, dbits
+=dstwidthb
, sbits
+=srcwidthb
)
876 memcpy(dbits
, sbits
, widthb
);
880 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
882 LPBYTE srcbits
= sbits
;
884 width
= min(srcwidth
, dstwidth
);
885 for( y
= 0; y
< lines
; y
++) {
886 for( x
= 0; x
< width
; x
++, srcbits
+= 3)
887 *dstbits
++ = ((srcbits
[0] >> 3) & bmask
) |
888 (((WORD
)srcbits
[1] << 2) & gmask
) |
889 (((WORD
)srcbits
[2] << 7) & rmask
);
891 dstbits
= (LPWORD
)(dbits
+=dstwidthb
);
892 srcbits
= (sbits
+= srcwidthb
);
897 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
899 LPDWORD srcbits
= (LPDWORD
)sbits
;
902 width
= min(srcwidth
, dstwidth
);
903 for( y
= 0; y
< lines
; y
++) {
904 for( x
= 0; x
< width
; x
++ ) {
906 *dstbits
++ = (WORD
)(((val
>> 3) & bmask
) | ((val
>> 6) & gmask
) |
907 ((val
>> 9) & rmask
));
909 dstbits
= (LPWORD
)(dbits
+=dstwidthb
);
910 srcbits
= (LPDWORD
)(sbits
+=srcwidthb
);
915 default: /* ? bit bmp -> 16 bit DIB */
916 FIXME("15/16 bit DIB %d bit bitmap\n",
917 bmp
->bitmap
.bmBitsPixel
);
923 case 24: /* 24 bpp dstDIB */
925 LPBYTE dstbits
= dbits
;
927 switch(bmp
->dib
->dsBm
.bmBitsPixel
) {
929 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
931 LPWORD srcbits
= (LPWORD
)sbits
;
934 width
= min(srcwidth
, dstwidth
);
935 /* FIXME: BI_BITFIELDS not supported yet */
936 for( y
= 0; y
< lines
; y
++) {
937 for( x
= 0; x
< width
; x
++ ) {
939 *dstbits
++ = (BYTE
)(((val
<< 3) & 0xf8) | ((val
>> 2) & 0x07));
940 *dstbits
++ = (BYTE
)(((val
>> 2) & 0xf8) | ((val
>> 7) & 0x07));
941 *dstbits
++ = (BYTE
)(((val
>> 7) & 0xf8) | ((val
>> 12) & 0x07));
943 dstbits
= dbits
+=dstwidthb
;
944 srcbits
= (LPWORD
)(sbits
+=srcwidthb
);
949 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
951 widthb
= min(srcwidthb
, abs(dstwidthb
));
952 for (y
= 0; y
< lines
; y
++, dbits
+=dstwidthb
, sbits
+=srcwidthb
)
953 memcpy(dbits
, sbits
, widthb
);
957 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
959 LPBYTE srcbits
= sbits
;
961 width
= min(srcwidth
, dstwidth
);
962 for( y
= 0; y
< lines
; y
++) {
963 for( x
= 0; x
< width
; x
++, srcbits
++ ) {
964 *dstbits
++ = *srcbits
++;
965 *dstbits
++ = *srcbits
++;
966 *dstbits
++ = *srcbits
++;
968 dstbits
= dbits
+=dstwidthb
;
969 srcbits
= sbits
+=srcwidthb
;
974 default: /* ? bit bmp -> 24 bit DIB */
975 FIXME("24 bit DIB %d bit bitmap\n",
976 bmp
->bitmap
.bmBitsPixel
);
982 case 32: /* 32 bpp dstDIB */
984 LPDWORD dstbits
= (LPDWORD
)dbits
;
986 /* FIXME: BI_BITFIELDS not supported yet */
988 switch(bmp
->dib
->dsBm
.bmBitsPixel
) {
989 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
991 LPWORD srcbits
= (LPWORD
)sbits
;
994 width
= min(srcwidth
, dstwidth
);
995 /* FIXME: BI_BITFIELDS not supported yet */
996 for( y
= 0; y
< lines
; y
++) {
997 for( x
= 0; x
< width
; x
++ ) {
998 val
= (DWORD
)*srcbits
++;
999 *dstbits
++ = ((val
<< 3) & 0xf8) | ((val
>> 2) & 0x07) |
1000 ((val
<< 6) & 0xf800) | ((val
<< 1) & 0x0700) |
1001 ((val
<< 9) & 0xf80000) | ((val
<< 4) & 0x070000);
1003 dstbits
=(LPDWORD
)(dbits
+=dstwidthb
);
1004 srcbits
=(LPWORD
)(sbits
+=srcwidthb
);
1009 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1011 LPBYTE srcbits
= sbits
;
1013 width
= min(srcwidth
, dstwidth
);
1014 for( y
= 0; y
< lines
; y
++) {
1015 for( x
= 0; x
< width
; x
++, srcbits
+=3 )
1016 *dstbits
++ = srcbits
[0] |
1019 dstbits
=(LPDWORD
)(dbits
+=dstwidthb
);
1020 srcbits
=(sbits
+=srcwidthb
);
1025 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1027 widthb
= min(srcwidthb
, abs(dstwidthb
));
1028 /* FIXME: BI_BITFIELDS not supported yet */
1029 for (y
= 0; y
< lines
; y
++, dbits
+=dstwidthb
, sbits
+=srcwidthb
) {
1030 memcpy(dbits
, sbits
, widthb
);
1035 default: /* ? bit bmp -> 32 bit DIB */
1036 FIXME("32 bit DIB %d bit bitmap\n",
1037 bmp
->bitmap
.bmBitsPixel
);
1043 default: /* ? bit DIB */
1044 FIXME("Unsupported DIB depth %d\n", info
->bmiHeader
.biBitCount
);
1048 /* Otherwise, get bits from the XImage */
1051 if (!bmp
->funcs
&& !BITMAP_SetOwnerDC( hbitmap
, dc
)) lines
= 0;
1054 if (bmp
->funcs
&& bmp
->funcs
->pGetDIBits
)
1055 lines
= bmp
->funcs
->pGetDIBits( dc
->physDev
, hbitmap
, startscan
,
1056 lines
, bits
, info
, coloruse
);
1058 lines
= 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1062 else lines
= abs(height
);
1064 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1065 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1069 /* FIXME: biSizeImage should be calculated according to the selected
1070 compression algorithm if biCompression != BI_RGB */
1071 info
->bmiHeader
.biSizeImage
= DIB_GetDIBImageBytes( width
, height
, bpp
);
1072 TRACE("biSizeImage = %d, ", info
->bmiHeader
.biSizeImage
);
1074 TRACE("biWidth = %d, biHeight = %d\n", width
, height
);
1077 release_dc_ptr( dc
);
1078 GDI_ReleaseObj( hbitmap
);
1083 /***********************************************************************
1084 * CreateDIBitmap (GDI32.@)
1086 * Creates a DDB (device dependent bitmap) from a DIB.
1087 * The DDB will have the same color depth as the reference DC.
1089 HBITMAP WINAPI
CreateDIBitmap( HDC hdc
, const BITMAPINFOHEADER
*header
,
1090 DWORD init
, LPCVOID bits
, const BITMAPINFO
*data
,
1100 if (!header
) return 0;
1102 if (DIB_GetBitmapInfo( header
, &width
, &height
, &planes
, &bpp
, &compr
, &size
) == -1) return 0;
1106 TRACE("Bitmap has a negative width\n");
1110 /* Top-down DIBs have a negative height */
1111 if (height
< 0) height
= -height
;
1113 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1114 hdc
, header
, init
, bits
, data
, coloruse
, width
, height
, bpp
, compr
);
1117 handle
= CreateBitmap( width
, height
, 1, 1, NULL
);
1119 handle
= CreateCompatibleBitmap( hdc
, width
, height
);
1123 if (init
== CBM_INIT
)
1125 if (SetDIBits( hdc
, handle
, 0, height
, bits
, data
, coloruse
) == 0)
1127 DeleteObject( handle
);
1132 else if (hdc
&& ((dc
= get_dc_ptr( hdc
)) != NULL
) )
1134 if (!BITMAP_SetOwnerDC( handle
, dc
))
1136 DeleteObject( handle
);
1139 release_dc_ptr( dc
);
1146 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1147 static void DIB_CopyColorTable( DC
*dc
, BITMAPOBJ
*bmp
, WORD coloruse
, const BITMAPINFO
*info
)
1149 RGBQUAD
*colorTable
;
1150 unsigned int colors
, i
;
1151 BOOL core_info
= info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
);
1155 colors
= 1 << ((const BITMAPCOREINFO
*) info
)->bmciHeader
.bcBitCount
;
1159 colors
= info
->bmiHeader
.biClrUsed
;
1160 if (!colors
) colors
= 1 << info
->bmiHeader
.biBitCount
;
1164 ERR("called with >256 colors!\n");
1168 if (!(colorTable
= HeapAlloc(GetProcessHeap(), 0, colors
* sizeof(RGBQUAD
) ))) return;
1170 if(coloruse
== DIB_RGB_COLORS
)
1174 /* Convert RGBTRIPLEs to RGBQUADs */
1175 for (i
=0; i
< colors
; i
++)
1177 colorTable
[i
].rgbRed
= ((const BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtRed
;
1178 colorTable
[i
].rgbGreen
= ((const BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtGreen
;
1179 colorTable
[i
].rgbBlue
= ((const BITMAPCOREINFO
*) info
)->bmciColors
[i
].rgbtBlue
;
1180 colorTable
[i
].rgbReserved
= 0;
1185 memcpy(colorTable
, (const BYTE
*) info
+ (WORD
) info
->bmiHeader
.biSize
, colors
* sizeof(RGBQUAD
));
1190 PALETTEENTRY entries
[256];
1191 const WORD
*index
= (const WORD
*) ((const BYTE
*) info
+ (WORD
) info
->bmiHeader
.biSize
);
1192 UINT count
= GetPaletteEntries( dc
->hPalette
, 0, colors
, entries
);
1194 for (i
= 0; i
< colors
; i
++, index
++)
1196 PALETTEENTRY
*entry
= &entries
[*index
% count
];
1197 colorTable
[i
].rgbRed
= entry
->peRed
;
1198 colorTable
[i
].rgbGreen
= entry
->peGreen
;
1199 colorTable
[i
].rgbBlue
= entry
->peBlue
;
1200 colorTable
[i
].rgbReserved
= 0;
1203 bmp
->color_table
= colorTable
;
1204 bmp
->nb_colors
= colors
;
1207 /***********************************************************************
1208 * CreateDIBSection (GDI32.@)
1210 HBITMAP WINAPI
CreateDIBSection(HDC hdc
, CONST BITMAPINFO
*bmi
, UINT usage
,
1211 VOID
**bits
, HANDLE section
, DWORD offset
)
1215 BOOL bDesktopDC
= FALSE
;
1221 DWORD compression
, sizeImage
;
1222 void *mapBits
= NULL
;
1225 if(bits
) *bits
= NULL
;
1229 if (((bitmap_type
= DIB_GetBitmapInfo( &bmi
->bmiHeader
, &width
, &height
,
1230 &planes
, &bpp
, &compression
, &sizeImage
)) == -1))
1233 if (compression
!= BI_RGB
&& compression
!= BI_BITFIELDS
)
1235 TRACE("can't create a compressed (%u) dibsection\n", compression
);
1239 if (!(dib
= HeapAlloc( GetProcessHeap(), 0, sizeof(*dib
) ))) return 0;
1241 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1242 width
, height
, planes
, bpp
, sizeImage
, usage
== DIB_PAL_COLORS
? "PAL" : "RGB");
1244 dib
->dsBm
.bmType
= 0;
1245 dib
->dsBm
.bmWidth
= width
;
1246 dib
->dsBm
.bmHeight
= height
>= 0 ? height
: -height
;
1247 dib
->dsBm
.bmWidthBytes
= DIB_GetDIBWidthBytes(width
, bpp
);
1248 dib
->dsBm
.bmPlanes
= planes
;
1249 dib
->dsBm
.bmBitsPixel
= bpp
;
1250 dib
->dsBm
.bmBits
= NULL
;
1252 if (!bitmap_type
) /* core header */
1254 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1255 dib
->dsBmih
.biSize
= sizeof(BITMAPINFOHEADER
);
1256 dib
->dsBmih
.biWidth
= width
;
1257 dib
->dsBmih
.biHeight
= height
;
1258 dib
->dsBmih
.biPlanes
= planes
;
1259 dib
->dsBmih
.biBitCount
= bpp
;
1260 dib
->dsBmih
.biCompression
= compression
;
1261 dib
->dsBmih
.biXPelsPerMeter
= 0;
1262 dib
->dsBmih
.biYPelsPerMeter
= 0;
1263 dib
->dsBmih
.biClrUsed
= 0;
1264 dib
->dsBmih
.biClrImportant
= 0;
1268 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1269 dib
->dsBmih
= bmi
->bmiHeader
;
1270 dib
->dsBmih
.biSize
= sizeof(BITMAPINFOHEADER
);
1273 /* set number of entries in bmi.bmiColors table */
1275 dib
->dsBmih
.biClrUsed
= 1 << bpp
;
1277 dib
->dsBmih
.biSizeImage
= dib
->dsBm
.bmWidthBytes
* dib
->dsBm
.bmHeight
;
1279 /* set dsBitfields values */
1280 if (usage
== DIB_PAL_COLORS
|| bpp
<= 8)
1282 dib
->dsBitfields
[0] = dib
->dsBitfields
[1] = dib
->dsBitfields
[2] = 0;
1288 dib
->dsBitfields
[0] = (compression
== BI_BITFIELDS
) ? *(const DWORD
*)bmi
->bmiColors
: 0x7c00;
1289 dib
->dsBitfields
[1] = (compression
== BI_BITFIELDS
) ? *((const DWORD
*)bmi
->bmiColors
+ 1) : 0x03e0;
1290 dib
->dsBitfields
[2] = (compression
== BI_BITFIELDS
) ? *((const DWORD
*)bmi
->bmiColors
+ 2) : 0x001f;
1294 dib
->dsBitfields
[0] = (compression
== BI_BITFIELDS
) ? *(const DWORD
*)bmi
->bmiColors
: 0xff0000;
1295 dib
->dsBitfields
[1] = (compression
== BI_BITFIELDS
) ? *((const DWORD
*)bmi
->bmiColors
+ 1) : 0x00ff00;
1296 dib
->dsBitfields
[2] = (compression
== BI_BITFIELDS
) ? *((const DWORD
*)bmi
->bmiColors
+ 2) : 0x0000ff;
1300 /* get storage location for DIB bits */
1304 SYSTEM_INFO SystemInfo
;
1308 GetSystemInfo( &SystemInfo
);
1309 mapOffset
= offset
- (offset
% SystemInfo
.dwAllocationGranularity
);
1310 mapSize
= dib
->dsBmih
.biSizeImage
+ (offset
- mapOffset
);
1311 mapBits
= MapViewOfFile( section
, FILE_MAP_ALL_ACCESS
, 0, mapOffset
, mapSize
);
1312 if (mapBits
) dib
->dsBm
.bmBits
= (char *)mapBits
+ (offset
- mapOffset
);
1317 dib
->dsBm
.bmBits
= VirtualAlloc( NULL
, dib
->dsBmih
.biSizeImage
,
1318 MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
);
1320 dib
->dshSection
= section
;
1321 dib
->dsOffset
= offset
;
1323 if (!dib
->dsBm
.bmBits
)
1325 HeapFree( GetProcessHeap(), 0, dib
);
1329 /* If the reference hdc is null, take the desktop dc */
1332 hdc
= CreateCompatibleDC(0);
1336 if (!(dc
= get_dc_ptr( hdc
))) goto error
;
1338 /* create Device Dependent Bitmap and add DIB pointer */
1339 ret
= CreateBitmap( dib
->dsBm
.bmWidth
, dib
->dsBm
.bmHeight
, 1,
1340 (bpp
== 1) ? 1 : GetDeviceCaps(hdc
, BITSPIXEL
), NULL
);
1342 if (ret
&& ((bmp
= GDI_GetObjPtr(ret
, OBJ_BITMAP
))))
1345 bmp
->funcs
= dc
->funcs
;
1346 /* create local copy of DIB palette */
1347 if (bpp
<= 8) DIB_CopyColorTable( dc
, bmp
, usage
, bmi
);
1348 GDI_ReleaseObj( ret
);
1350 if (dc
->funcs
->pCreateDIBSection
)
1352 if (!dc
->funcs
->pCreateDIBSection(dc
->physDev
, ret
, bmi
, usage
))
1354 DeleteObject( ret
);
1360 release_dc_ptr( dc
);
1361 if (bDesktopDC
) DeleteDC( hdc
);
1362 if (ret
&& bits
) *bits
= dib
->dsBm
.bmBits
;
1366 if (bDesktopDC
) DeleteDC( hdc
);
1367 if (section
) UnmapViewOfFile( mapBits
);
1368 else if (!offset
) VirtualFree( dib
->dsBm
.bmBits
, 0, MEM_RELEASE
);
1369 HeapFree( GetProcessHeap(), 0, dib
);