2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize).
34 * The palettes are stored in different formats:
36 - BITMAPCOREINFO: Array of RGBTRIPLE
37 - BITMAPINFO: Array of RGBQUAD
40 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
43 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45 If biCompression is BI_BITFIELDS, the color masks are at the same position
46 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
47 the new headers have structure members for the masks.
50 * You should never access the color table using the bmiColors member,
51 because the passed structure may have one of the extended headers
52 mentioned above. Use this to calculate the location:
55 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 Search for "Bitmap Structures" in MSDN
69 #include "gdi_private.h"
70 #include "wine/debug.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
75 /***********************************************************************
78 * Return the size of the bitmap info structure including color table.
80 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
82 unsigned int colors, size, masks = 0;
84 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
86 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
87 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
88 return sizeof(BITMAPCOREHEADER) + colors *
89 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
91 else /* assume BITMAPINFOHEADER */
93 colors = get_dib_num_of_colors( info );
94 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
95 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
96 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
100 /*******************************************************************************************
101 * Verify that the DIB parameters are valid.
103 static BOOL is_valid_dib_format( const BITMAPINFOHEADER *info, BOOL allow_compression )
105 if (info->biWidth <= 0) return FALSE;
106 if (info->biHeight == 0) return FALSE;
108 if (allow_compression && (info->biCompression == BI_RLE4 || info->biCompression == BI_RLE8))
110 if (info->biHeight < 0) return FALSE;
111 if (!info->biSizeImage) return FALSE;
112 return info->biBitCount == (info->biCompression == BI_RLE4 ? 4 : 8);
115 if (!info->biPlanes) return FALSE;
117 switch (info->biBitCount)
123 return (info->biCompression == BI_RGB);
126 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
132 /*******************************************************************************************
133 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
135 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
137 if (!info) return FALSE;
139 if (info->biSize == sizeof(BITMAPCOREHEADER))
141 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
142 dst->biWidth = core->bcWidth;
143 dst->biHeight = core->bcHeight;
144 dst->biPlanes = core->bcPlanes;
145 dst->biBitCount = core->bcBitCount;
146 dst->biCompression = BI_RGB;
147 dst->biXPelsPerMeter = 0;
148 dst->biYPelsPerMeter = 0;
150 dst->biClrImportant = 0;
152 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
158 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
162 dst->biSize = sizeof(*dst);
163 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
164 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
168 /*******************************************************************************************
169 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
171 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
172 UINT coloruse, BOOL allow_compression )
177 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
178 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
180 src_colors = (char *)info + info->bmiHeader.biSize;
181 colors = get_dib_num_of_colors( dst );
183 if (info->bmiHeader.biCompression == BI_BITFIELDS)
185 /* bitfields are always at bmiColors even in larger structures */
186 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
190 if (coloruse == DIB_PAL_COLORS)
191 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
192 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
193 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
197 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
198 for (i = 0; i < colors; i++)
200 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
201 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
202 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
203 dst->bmiColors[i].rgbReserved = 0;
210 static int fill_color_table_from_palette( BITMAPINFO *info, DC *dc )
212 PALETTEENTRY palEntry[256];
213 int i, colors = get_dib_num_of_colors( info );
215 if (!colors) return 0;
217 memset( palEntry, 0, sizeof(palEntry) );
218 if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
221 for (i = 0; i < colors; i++)
223 info->bmiColors[i].rgbRed = palEntry[i].peRed;
224 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
225 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
226 info->bmiColors[i].rgbReserved = 0;
232 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
234 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
235 const int bpp = info->bmiHeader.biBitCount;
238 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
240 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
243 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
247 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
249 BYTE skip, num, data;
250 BYTE *out_bits, *in_bits = bits->ptr;
254 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
256 out_bits = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ) );
257 *clip = CreateRectRgn( 0, 0, 0, 0 );
258 run = CreateRectRgn( 0, 0, 0, 0 );
259 if (!out_bits || !*clip || !run) goto fail;
261 x = left = right = 0;
264 while (i < info->bmiHeader.biSizeImage - 1)
267 data = in_bits[i + 1];
272 if (x + num > width) num = width - x;
275 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
276 if (info->bmiHeader.biBitCount == 8)
277 memset( out_ptr, s, num );
282 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
283 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
288 /* this will write one too many if num is odd, but that doesn't matter */
289 if (num) memset( out_ptr, s, (num + 1) / 2 );
301 SetRectRgn( run, left, y, right, y + 1 );
302 CombineRgn( *clip, run, *clip, RGN_OR );
307 left = right = x = 0;
316 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
318 if (x > width) x = width;
325 else /* data bytes of data */
328 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
329 if (skip > info->bmiHeader.biSizeImage - i) goto done;
330 skip = (skip + 1) & ~1;
331 if (x + num > width) num = width - x;
334 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
335 if (info->bmiHeader.biBitCount == 8)
336 memcpy( out_ptr, in_bits + i, num );
341 const BYTE *in_ptr = in_bits + i;
342 for ( ; num; num--, x++)
346 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
350 *out_ptr = (*in_ptr++ << 4) & 0xf0;
354 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
366 if (bits->free) bits->free( bits );
368 bits->ptr = out_bits;
369 bits->is_copy = TRUE;
370 bits->free = free_heap_bits;
375 if (run) DeleteObject( run );
376 if (*clip) DeleteObject( *clip );
377 HeapFree( GetProcessHeap(), 0, out_bits );
383 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
384 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
385 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
386 const BITMAPINFO *info, UINT coloruse, DWORD rop )
388 DC *dc = get_nulldrv_dc( dev );
394 /* make sure we have a real implementation for StretchBlt and PutImage */
395 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pPutImage ) == dev)
398 height = info->bmiHeader.biHeight;
400 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
401 info->bmiHeader.biCompression == BI_RGB)
403 /* Windows appears to have a fast case optimization
404 * that uses the wrong origin for top-down DIBs */
405 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
407 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
410 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
411 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
412 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
413 bm.bmBitsPixel == info->bmiHeader.biBitCount && bm.bmPlanes == 1)
416 return SetDIBits( dev->hdc, hBitmap, 0, abs( height ), bits, info, coloruse );
421 hdcMem = CreateCompatibleDC( dev->hdc );
422 hBitmap = CreateCompatibleBitmap( dev->hdc, info->bmiHeader.biWidth, height );
423 SelectObject( hdcMem, hBitmap );
424 if (coloruse == DIB_PAL_COLORS)
425 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
427 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
429 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
430 * contain all the rectangle described in bmiHeader, but only part of it.
431 * This mean that those undescribed pixels must be left untouched.
432 * So, we first copy on a memory bitmap the current content of the
433 * destination rectangle, blit the DIB bits on top of it - hence leaving
434 * the gaps untouched -, and blitting the rectangle back.
435 * This insure that gaps are untouched on the destination rectangle
437 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
438 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
440 ret = SetDIBits( hdcMem, hBitmap, 0, abs( height ), bits, info, coloruse );
441 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
442 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
444 DeleteObject( hBitmap );
448 /***********************************************************************
449 * StretchDIBits (GDI32.@)
451 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
452 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
453 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
455 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
456 BITMAPINFO *info = (BITMAPINFO *)buffer;
461 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
463 SetLastError( ERROR_INVALID_PARAMETER );
467 if ((dc = get_dc_ptr( hdc )))
469 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
471 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
472 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
473 release_dc_ptr( dc );
479 /******************************************************************************
480 * SetDIBits [GDI32.@]
482 * Sets pixels in a bitmap using colors from DIB.
485 * hdc [I] Handle to device context
486 * hbitmap [I] Handle to bitmap
487 * startscan [I] Starting scan line
488 * lines [I] Number of scan lines
489 * bits [I] Array of bitmap bits
490 * info [I] Address of structure with data
491 * coloruse [I] Type of color indexes to use
494 * Success: Number of scan lines copied
497 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
498 UINT lines, LPCVOID bits, const BITMAPINFO *info,
501 DC *dc = get_dc_ptr( hdc );
502 BOOL delete_hdc = FALSE;
505 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
506 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
507 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
508 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
511 struct gdi_image_bits src_bits;
512 struct bitblt_coords src, dst;
513 INT src_to_dst_offset;
515 const struct gdi_dc_funcs *funcs;
517 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
519 SetLastError( ERROR_INVALID_PARAMETER );
523 src_bits.ptr = (void *)bits;
524 src_bits.is_copy = FALSE;
525 src_bits.free = NULL;
526 src_bits.param = NULL;
528 if (coloruse == DIB_RGB_COLORS && !dc)
530 hdc = CreateCompatibleDC(0);
531 dc = get_dc_ptr( hdc );
539 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
541 release_dc_ptr( dc );
542 if (delete_hdc) DeleteDC(hdc);
546 if (coloruse == DIB_PAL_COLORS)
547 if (!fill_color_table_from_palette( src_info, dc )) goto done;
549 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
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 /* Hack to ensure we don't get the nulldrv if the bmp hasn't been selected
583 physdev = GET_DC_PHYSDEV( dc, pCreateBitmap );
584 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) goto done;
586 funcs = get_bitmap_funcs( bitmap );
590 offset_rect( &src.visrect, 0, src_to_dst_offset );
591 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
592 src.visrect = dst.visrect;
593 offset_rect( &src.visrect, 0, -src_to_dst_offset );
595 src.x = src.visrect.left;
596 src.y = src.visrect.top;
597 src.width = src.visrect.right - src.visrect.left;
598 src.height = src.visrect.bottom - src.visrect.top;
600 dst.x = dst.visrect.left;
601 dst.y = dst.visrect.top;
602 dst.width = dst.visrect.right - dst.visrect.left;
603 dst.height = dst.visrect.bottom - dst.visrect.top;
605 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
607 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
608 if (err == ERROR_BAD_FORMAT)
612 dst_info->bmiHeader.biWidth = dst.width;
613 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
616 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr );
618 if (src_bits.free) src_bits.free( &src_bits );
620 src_bits.is_copy = TRUE;
621 src_bits.free = free_heap_bits;
623 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
626 else err = ERROR_OUTOFMEMORY;
631 if (src_bits.free) src_bits.free( &src_bits );
632 if (clip) DeleteObject( clip );
633 GDI_ReleaseObj( hbitmap );
634 release_dc_ptr( dc );
635 if (delete_hdc) DeleteDC(hdc);
640 /***********************************************************************
641 * SetDIBitsToDevice (GDI32.@)
643 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
644 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
645 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
648 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
649 BITMAPINFO *info = (BITMAPINFO *)buffer;
654 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
656 SetLastError( ERROR_INVALID_PARAMETER );
660 if ((dc = get_dc_ptr( hdc )))
662 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
664 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
665 ySrc, startscan, lines, bits, info, coloruse );
666 release_dc_ptr( dc );
671 /***********************************************************************
672 * SetDIBColorTable (GDI32.@)
674 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
680 if (!(dc = get_dc_ptr( hdc ))) return 0;
682 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
684 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
686 /* Check if currently selected bitmap is a DIB */
687 if (bitmap->color_table)
689 if (startpos < bitmap->nb_colors)
691 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
692 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
696 GDI_ReleaseObj( dc->hBitmap );
697 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
699 release_dc_ptr( dc );
704 /***********************************************************************
705 * GetDIBColorTable (GDI32.@)
707 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
713 if (!(dc = get_dc_ptr( hdc ))) return 0;
715 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
717 /* Check if currently selected bitmap is a DIB */
718 if (bitmap->color_table)
720 if (startpos < bitmap->nb_colors)
722 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
723 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
727 GDI_ReleaseObj( dc->hBitmap );
729 release_dc_ptr( dc );
733 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
734 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
735 { 0x00, 0x00, 0x00, 0x00 },
736 { 0x00, 0x00, 0x80, 0x00 },
737 { 0x00, 0x80, 0x00, 0x00 },
738 { 0x00, 0x80, 0x80, 0x00 },
739 { 0x80, 0x00, 0x00, 0x00 },
740 { 0x80, 0x00, 0x80, 0x00 },
741 { 0x80, 0x80, 0x00, 0x00 },
742 { 0xc0, 0xc0, 0xc0, 0x00 },
743 { 0xc0, 0xdc, 0xc0, 0x00 },
744 { 0xf0, 0xca, 0xa6, 0x00 },
745 { 0xf0, 0xfb, 0xff, 0x00 },
746 { 0xa4, 0xa0, 0xa0, 0x00 },
747 { 0x80, 0x80, 0x80, 0x00 },
748 { 0x00, 0x00, 0xff, 0x00 },
749 { 0x00, 0xff, 0x00, 0x00 },
750 { 0x00, 0xff, 0xff, 0x00 },
751 { 0xff, 0x00, 0x00, 0x00 },
752 { 0xff, 0x00, 0xff, 0x00 },
753 { 0xff, 0xff, 0x00, 0x00 },
754 { 0xff, 0xff, 0xff, 0x00 }
757 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
758 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
759 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
761 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
763 BITMAPINFOHEADER header;
765 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
766 header.biWidth = bmp->bitmap.bmWidth;
767 header.biHeight = bmp->bitmap.bmHeight;
772 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
773 switch (bmp->dib->dsBm.bmBitsPixel)
777 header.biCompression = BI_BITFIELDS;
780 header.biCompression = BI_RGB;
786 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
787 header.biBitCount = bmp->bitmap.bmBitsPixel;
790 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
791 header.biXPelsPerMeter = 0;
792 header.biYPelsPerMeter = 0;
793 header.biClrUsed = 0;
794 header.biClrImportant = 0;
796 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
798 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
800 coreheader->bcWidth = header.biWidth;
801 coreheader->bcHeight = header.biHeight;
802 coreheader->bcPlanes = header.biPlanes;
803 coreheader->bcBitCount = header.biBitCount;
806 info->bmiHeader = header;
808 return abs(bmp->bitmap.bmHeight);
811 /************************************************************************
814 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
816 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
818 unsigned int colors = get_dib_num_of_colors( src );
819 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
821 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
823 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
825 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
826 if (coloruse == DIB_PAL_COLORS)
827 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
831 for (i = 0; i < colors; i++)
833 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
834 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
835 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
841 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
842 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
844 if (src->bmiHeader.biCompression == BI_BITFIELDS)
845 /* bitfields are always at bmiColors even in larger structures */
846 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
849 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
852 if (coloruse == DIB_PAL_COLORS)
853 size = colors * sizeof(WORD);
855 size = colors * sizeof(RGBQUAD);
856 memcpy( colorptr, src_colors, size );
861 static void fill_default_color_table( BITMAPINFO *info )
865 switch (info->bmiHeader.biBitCount)
868 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
869 info->bmiColors[0].rgbReserved = 0;
870 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
871 info->bmiColors[1].rgbReserved = 0;
875 /* The EGA palette is the first and last 8 colours of the default palette
876 with the innermost pair swapped */
877 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
878 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
879 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
880 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
884 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
885 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
886 for (i = 10; i < 246; i++)
888 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
889 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
890 info->bmiColors[i].rgbBlue = i & 0xc0;
891 info->bmiColors[i].rgbReserved = 0;
896 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
900 /******************************************************************************
901 * GetDIBits [GDI32.@]
903 * Retrieves bits of bitmap and copies to buffer.
906 * Success: Number of scan lines copied from bitmap
909 INT WINAPI GetDIBits(
910 HDC hdc, /* [in] Handle to device context */
911 HBITMAP hbitmap, /* [in] Handle to bitmap */
912 UINT startscan, /* [in] First scan line to set in dest bitmap */
913 UINT lines, /* [in] Number of scan lines to copy */
914 LPVOID bits, /* [out] Address of array for bitmap bits */
915 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
916 UINT coloruse) /* [in] RGB or palette index */
920 int i, dst_to_src_offset, ret = 0;
922 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
923 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
924 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
925 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
926 const struct gdi_dc_funcs *funcs;
927 struct gdi_image_bits src_bits;
928 struct bitblt_coords src, dst;
929 BOOL empty_rect = FALSE;
931 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
932 own copy and transfer the colour info back at the end */
933 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
934 dst_info->bmiHeader.biClrUsed = 0;
935 dst_info->bmiHeader.biClrImportant = 0;
937 if (!(dc = get_dc_ptr( hdc )))
939 SetLastError( ERROR_INVALID_PARAMETER );
943 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
945 release_dc_ptr( dc );
949 funcs = get_bitmap_funcs( bmp );
951 if (dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
953 ret = fill_query_info( info, bmp );
957 src.visrect.left = 0;
959 src.visrect.right = bmp->bitmap.bmWidth;
960 src.visrect.bottom = bmp->bitmap.bmHeight;
962 dst.visrect.left = 0;
964 dst.visrect.right = dst_info->bmiHeader.biWidth;
965 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
967 if (lines == 0 || startscan >= dst.visrect.bottom)
972 if (dst_info->bmiHeader.biHeight > 0)
974 dst_to_src_offset = -startscan;
975 lines = min( lines, dst.visrect.bottom - startscan );
976 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
980 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
981 if (dst_to_src_offset < 0)
983 dst_to_src_offset = 0;
984 lines = dst.visrect.bottom - startscan;
986 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
989 offset_rect( &dst.visrect, 0, dst_to_src_offset );
990 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
991 dst.visrect = src.visrect;
992 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
994 if (dst_info->bmiHeader.biHeight > 0)
996 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
998 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
999 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1000 memset( bits, 0, pad_bytes );
1001 bits = (char *)bits + pad_bytes;
1006 if (dst.visrect.bottom < lines)
1008 int pad_lines = lines - dst.visrect.bottom;
1009 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1010 int pad_bytes = pad_lines * stride;
1011 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1015 if (empty_rect) bits = NULL;
1017 src.x = src.visrect.left;
1018 src.y = src.visrect.top;
1019 src.width = src.visrect.right - src.visrect.left;
1020 src.height = src.visrect.bottom - src.visrect.top;
1025 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1029 /* fill out the src colour table, if it needs one */
1030 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1032 fill_default_color_table( src_info );
1033 src_info->bmiHeader.biClrUsed = 1 << src_info->bmiHeader.biBitCount;
1036 /* if the src and dst are the same depth, copy the colour info across */
1037 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1039 switch (src_info->bmiHeader.biBitCount)
1042 if (src_info->bmiHeader.biCompression == BI_RGB)
1044 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1045 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1049 if (src_info->bmiHeader.biCompression == BI_RGB)
1051 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1052 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1056 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1057 copy_color_info( dst_info, src_info, coloruse );
1059 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1061 if( coloruse == DIB_PAL_COLORS )
1063 if (!fill_color_table_from_palette( dst_info, dc )) goto done;
1067 fill_default_color_table( dst_info );
1073 if(dst_info->bmiHeader.biHeight > 0)
1074 dst_info->bmiHeader.biHeight = src.height;
1076 dst_info->bmiHeader.biHeight = -src.height;
1078 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
1079 if (src_bits.free) src_bits.free( &src_bits );
1083 ret = empty_rect ? FALSE : TRUE;
1085 if (coloruse == DIB_PAL_COLORS)
1087 WORD *index = (WORD *)dst_info->bmiColors;
1088 int colors = get_dib_num_of_colors( dst_info );
1089 for (i = 0; i < colors; i++, index++)
1093 copy_color_info( info, dst_info, coloruse );
1096 release_dc_ptr( dc );
1097 GDI_ReleaseObj( hbitmap );
1102 /***********************************************************************
1103 * CreateDIBitmap (GDI32.@)
1105 * Creates a DDB (device dependent bitmap) from a DIB.
1106 * The DDB will have the same color depth as the reference DC.
1108 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1109 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1112 BITMAPINFOHEADER info;
1116 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1117 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1118 if (info.biWidth < 0) return 0;
1120 /* Top-down DIBs have a negative height */
1121 height = abs( info.biHeight );
1123 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1124 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1125 info.biBitCount, info.biCompression);
1128 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1130 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1134 if (init & CBM_INIT)
1136 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1138 DeleteObject( handle );
1147 /* Copy/synthesize RGB palette from BITMAPINFO */
1148 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1150 unsigned int colors, i;
1152 colors = get_dib_num_of_colors( info );
1153 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1154 bmp->nb_colors = colors;
1156 if (coloruse == DIB_RGB_COLORS)
1158 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1162 PALETTEENTRY entries[256];
1163 const WORD *index = (const WORD *)info->bmiColors;
1164 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1166 for (i = 0; i < colors; i++, index++)
1168 PALETTEENTRY *entry = &entries[*index % count];
1169 bmp->color_table[i].rgbRed = entry->peRed;
1170 bmp->color_table[i].rgbGreen = entry->peGreen;
1171 bmp->color_table[i].rgbBlue = entry->peBlue;
1172 bmp->color_table[i].rgbReserved = 0;
1177 /***********************************************************************
1178 * CreateDIBSection (GDI32.@)
1180 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1181 VOID **bits, HANDLE section, DWORD offset)
1183 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1184 BITMAPINFO *info = (BITMAPINFO *)buffer;
1187 BOOL bDesktopDC = FALSE;
1190 void *mapBits = NULL;
1192 if (bits) *bits = NULL;
1193 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1194 if (info->bmiHeader.biPlanes != 1)
1196 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1197 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1200 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1202 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1203 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1204 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1205 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1206 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1208 dib->dsBm.bmType = 0;
1209 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1210 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1211 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1212 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1213 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1214 dib->dsBm.bmBits = NULL;
1215 dib->dsBmih = info->bmiHeader;
1217 /* set number of entries in bmi.bmiColors table */
1218 if( info->bmiHeader.biBitCount <= 8 )
1219 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1221 /* set dsBitfields values */
1222 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1224 dib->dsBmih.biCompression = BI_BITFIELDS;
1225 dib->dsBitfields[0] = 0x7c00;
1226 dib->dsBitfields[1] = 0x03e0;
1227 dib->dsBitfields[2] = 0x001f;
1229 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1231 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1232 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1233 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1234 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1236 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1238 /* get storage location for DIB bits */
1242 SYSTEM_INFO SystemInfo;
1246 GetSystemInfo( &SystemInfo );
1247 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1248 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1249 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1250 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1255 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1256 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1258 dib->dshSection = section;
1259 dib->dsOffset = offset;
1261 if (!dib->dsBm.bmBits)
1263 HeapFree( GetProcessHeap(), 0, dib );
1267 /* If the reference hdc is null, take the desktop dc */
1270 hdc = CreateCompatibleDC(0);
1274 if (!(dc = get_dc_ptr( hdc ))) goto error;
1276 /* create Device Dependent Bitmap and add DIB pointer */
1277 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1278 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1280 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1282 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1284 bmp->funcs = physdev->funcs;
1285 /* create local copy of DIB palette */
1286 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1287 GDI_ReleaseObj( ret );
1289 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1291 DeleteObject( ret );
1296 release_dc_ptr( dc );
1297 if (bDesktopDC) DeleteDC( hdc );
1298 if (ret && bits) *bits = dib->dsBm.bmBits;
1302 if (bDesktopDC) DeleteDC( hdc );
1303 if (section) UnmapViewOfFile( mapBits );
1304 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1305 HeapFree( GetProcessHeap(), 0, dib );