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 );
617 if (src_bits.free) src_bits.free( &src_bits );
619 src_bits.is_copy = TRUE;
620 src_bits.free = free_heap_bits;
622 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
624 else err = ERROR_OUTOFMEMORY;
629 if (src_bits.free) src_bits.free( &src_bits );
630 if (clip) DeleteObject( clip );
631 GDI_ReleaseObj( hbitmap );
632 release_dc_ptr( dc );
633 if (delete_hdc) DeleteDC(hdc);
638 /***********************************************************************
639 * SetDIBitsToDevice (GDI32.@)
641 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
642 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
643 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
646 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
647 BITMAPINFO *info = (BITMAPINFO *)buffer;
652 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
654 SetLastError( ERROR_INVALID_PARAMETER );
658 if ((dc = get_dc_ptr( hdc )))
660 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
662 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
663 ySrc, startscan, lines, bits, info, coloruse );
664 release_dc_ptr( dc );
669 /***********************************************************************
670 * SetDIBColorTable (GDI32.@)
672 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
678 if (!(dc = get_dc_ptr( hdc ))) return 0;
680 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
682 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
684 /* Check if currently selected bitmap is a DIB */
685 if (bitmap->color_table)
687 if (startpos < bitmap->nb_colors)
689 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
690 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
694 GDI_ReleaseObj( dc->hBitmap );
695 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
697 release_dc_ptr( dc );
702 /***********************************************************************
703 * GetDIBColorTable (GDI32.@)
705 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
711 if (!(dc = get_dc_ptr( hdc ))) return 0;
713 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
715 /* Check if currently selected bitmap is a DIB */
716 if (bitmap->color_table)
718 if (startpos < bitmap->nb_colors)
720 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
721 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
725 GDI_ReleaseObj( dc->hBitmap );
727 release_dc_ptr( dc );
731 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
732 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
733 { 0x00, 0x00, 0x00, 0x00 },
734 { 0x00, 0x00, 0x80, 0x00 },
735 { 0x00, 0x80, 0x00, 0x00 },
736 { 0x00, 0x80, 0x80, 0x00 },
737 { 0x80, 0x00, 0x00, 0x00 },
738 { 0x80, 0x00, 0x80, 0x00 },
739 { 0x80, 0x80, 0x00, 0x00 },
740 { 0xc0, 0xc0, 0xc0, 0x00 },
741 { 0xc0, 0xdc, 0xc0, 0x00 },
742 { 0xf0, 0xca, 0xa6, 0x00 },
743 { 0xf0, 0xfb, 0xff, 0x00 },
744 { 0xa4, 0xa0, 0xa0, 0x00 },
745 { 0x80, 0x80, 0x80, 0x00 },
746 { 0x00, 0x00, 0xff, 0x00 },
747 { 0x00, 0xff, 0x00, 0x00 },
748 { 0x00, 0xff, 0xff, 0x00 },
749 { 0xff, 0x00, 0x00, 0x00 },
750 { 0xff, 0x00, 0xff, 0x00 },
751 { 0xff, 0xff, 0x00, 0x00 },
752 { 0xff, 0xff, 0xff, 0x00 }
755 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
756 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
757 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
759 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
761 BITMAPINFOHEADER header;
763 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
764 header.biWidth = bmp->bitmap.bmWidth;
765 header.biHeight = bmp->bitmap.bmHeight;
770 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
771 switch (bmp->dib->dsBm.bmBitsPixel)
775 header.biCompression = BI_BITFIELDS;
778 header.biCompression = BI_RGB;
784 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
785 header.biBitCount = bmp->bitmap.bmBitsPixel;
788 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
789 header.biXPelsPerMeter = 0;
790 header.biYPelsPerMeter = 0;
791 header.biClrUsed = 0;
792 header.biClrImportant = 0;
794 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
796 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
798 coreheader->bcWidth = header.biWidth;
799 coreheader->bcHeight = header.biHeight;
800 coreheader->bcPlanes = header.biPlanes;
801 coreheader->bcBitCount = header.biBitCount;
804 info->bmiHeader = header;
806 return abs(bmp->bitmap.bmHeight);
809 /************************************************************************
812 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
814 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
816 unsigned int colors = get_dib_num_of_colors( src );
817 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
819 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
821 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
823 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
824 if (coloruse == DIB_PAL_COLORS)
825 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
829 for (i = 0; i < colors; i++)
831 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
832 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
833 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
839 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
840 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
842 if (src->bmiHeader.biCompression == BI_BITFIELDS)
843 /* bitfields are always at bmiColors even in larger structures */
844 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
847 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
850 if (coloruse == DIB_PAL_COLORS)
851 size = colors * sizeof(WORD);
853 size = colors * sizeof(RGBQUAD);
854 memcpy( colorptr, src_colors, size );
859 static void fill_default_color_table( BITMAPINFO *info )
863 switch (info->bmiHeader.biBitCount)
866 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
867 info->bmiColors[0].rgbReserved = 0;
868 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
869 info->bmiColors[1].rgbReserved = 0;
873 /* The EGA palette is the first and last 8 colours of the default palette
874 with the innermost pair swapped */
875 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
876 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
877 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
878 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
882 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
883 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
884 for (i = 10; i < 246; i++)
886 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
887 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
888 info->bmiColors[i].rgbBlue = i & 0xc0;
889 info->bmiColors[i].rgbReserved = 0;
894 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
898 /******************************************************************************
899 * GetDIBits [GDI32.@]
901 * Retrieves bits of bitmap and copies to buffer.
904 * Success: Number of scan lines copied from bitmap
907 INT WINAPI GetDIBits(
908 HDC hdc, /* [in] Handle to device context */
909 HBITMAP hbitmap, /* [in] Handle to bitmap */
910 UINT startscan, /* [in] First scan line to set in dest bitmap */
911 UINT lines, /* [in] Number of scan lines to copy */
912 LPVOID bits, /* [out] Address of array for bitmap bits */
913 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
914 UINT coloruse) /* [in] RGB or palette index */
918 int i, dst_to_src_offset, ret = 0;
920 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
921 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
922 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
923 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
924 const struct gdi_dc_funcs *funcs;
925 struct gdi_image_bits src_bits;
926 struct bitblt_coords src, dst;
927 BOOL empty_rect = FALSE;
929 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
930 own copy and transfer the colour info back at the end */
931 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
932 dst_info->bmiHeader.biClrUsed = 0;
933 dst_info->bmiHeader.biClrImportant = 0;
935 if (!(dc = get_dc_ptr( hdc )))
937 SetLastError( ERROR_INVALID_PARAMETER );
941 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
943 release_dc_ptr( dc );
947 funcs = get_bitmap_funcs( bmp );
949 if (dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
951 ret = fill_query_info( info, bmp );
955 src.visrect.left = 0;
957 src.visrect.right = bmp->bitmap.bmWidth;
958 src.visrect.bottom = bmp->bitmap.bmHeight;
960 dst.visrect.left = 0;
962 dst.visrect.right = dst_info->bmiHeader.biWidth;
963 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
965 if (lines == 0 || startscan >= dst.visrect.bottom)
970 if (dst_info->bmiHeader.biHeight > 0)
972 dst_to_src_offset = -startscan;
973 lines = min( lines, dst.visrect.bottom - startscan );
974 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
978 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
979 if (dst_to_src_offset < 0)
981 dst_to_src_offset = 0;
982 lines = dst.visrect.bottom - startscan;
984 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
987 offset_rect( &dst.visrect, 0, dst_to_src_offset );
988 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
989 dst.visrect = src.visrect;
990 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
992 if (dst_info->bmiHeader.biHeight > 0)
994 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
996 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
997 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
998 memset( bits, 0, pad_bytes );
999 bits = (char *)bits + pad_bytes;
1004 if (dst.visrect.bottom < lines)
1006 int pad_lines = lines - dst.visrect.bottom;
1007 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1008 int pad_bytes = pad_lines * stride;
1009 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1013 if (empty_rect) bits = NULL;
1015 src.x = src.visrect.left;
1016 src.y = src.visrect.top;
1017 src.width = src.visrect.right - src.visrect.left;
1018 src.height = src.visrect.bottom - src.visrect.top;
1023 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1027 /* fill out the src colour table, if it needs one */
1028 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1030 fill_default_color_table( src_info );
1031 src_info->bmiHeader.biClrUsed = 1 << src_info->bmiHeader.biBitCount;
1034 /* if the src and dst are the same depth, copy the colour info across */
1035 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1037 switch (src_info->bmiHeader.biBitCount)
1040 if (src_info->bmiHeader.biCompression == BI_RGB)
1042 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1043 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1047 if (src_info->bmiHeader.biCompression == BI_RGB)
1049 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1050 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1054 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1055 copy_color_info( dst_info, src_info, coloruse );
1057 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1059 if( coloruse == DIB_PAL_COLORS )
1061 if (!fill_color_table_from_palette( dst_info, dc )) goto done;
1065 fill_default_color_table( dst_info );
1071 if(dst_info->bmiHeader.biHeight > 0)
1072 dst_info->bmiHeader.biHeight = src.height;
1074 dst_info->bmiHeader.biHeight = -src.height;
1076 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
1077 if (src_bits.free) src_bits.free( &src_bits );
1081 ret = empty_rect ? FALSE : TRUE;
1083 if (coloruse == DIB_PAL_COLORS)
1085 WORD *index = (WORD *)dst_info->bmiColors;
1086 int colors = get_dib_num_of_colors( dst_info );
1087 for (i = 0; i < colors; i++, index++)
1091 copy_color_info( info, dst_info, coloruse );
1094 release_dc_ptr( dc );
1095 GDI_ReleaseObj( hbitmap );
1100 /***********************************************************************
1101 * CreateDIBitmap (GDI32.@)
1103 * Creates a DDB (device dependent bitmap) from a DIB.
1104 * The DDB will have the same color depth as the reference DC.
1106 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1107 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1110 BITMAPINFOHEADER info;
1114 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1115 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1116 if (info.biWidth < 0) return 0;
1118 /* Top-down DIBs have a negative height */
1119 height = abs( info.biHeight );
1121 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1122 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1123 info.biBitCount, info.biCompression);
1126 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1128 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1132 if (init & CBM_INIT)
1134 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1136 DeleteObject( handle );
1145 /* Copy/synthesize RGB palette from BITMAPINFO */
1146 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1148 unsigned int colors, i;
1150 colors = get_dib_num_of_colors( info );
1151 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1152 bmp->nb_colors = colors;
1154 if (coloruse == DIB_RGB_COLORS)
1156 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1160 PALETTEENTRY entries[256];
1161 const WORD *index = (const WORD *)info->bmiColors;
1162 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1164 for (i = 0; i < colors; i++, index++)
1166 PALETTEENTRY *entry = &entries[*index % count];
1167 bmp->color_table[i].rgbRed = entry->peRed;
1168 bmp->color_table[i].rgbGreen = entry->peGreen;
1169 bmp->color_table[i].rgbBlue = entry->peBlue;
1170 bmp->color_table[i].rgbReserved = 0;
1175 /***********************************************************************
1176 * CreateDIBSection (GDI32.@)
1178 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1179 VOID **bits, HANDLE section, DWORD offset)
1181 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1182 BITMAPINFO *info = (BITMAPINFO *)buffer;
1185 BOOL bDesktopDC = FALSE;
1188 void *mapBits = NULL;
1190 if (bits) *bits = NULL;
1191 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1192 if (info->bmiHeader.biPlanes != 1)
1194 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1195 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1198 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1200 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1201 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1202 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1203 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1204 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1206 dib->dsBm.bmType = 0;
1207 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1208 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1209 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1210 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1211 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1212 dib->dsBm.bmBits = NULL;
1213 dib->dsBmih = info->bmiHeader;
1215 /* set number of entries in bmi.bmiColors table */
1216 if( info->bmiHeader.biBitCount <= 8 )
1217 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1219 /* set dsBitfields values */
1220 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1222 dib->dsBmih.biCompression = BI_BITFIELDS;
1223 dib->dsBitfields[0] = 0x7c00;
1224 dib->dsBitfields[1] = 0x03e0;
1225 dib->dsBitfields[2] = 0x001f;
1227 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1229 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1230 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1231 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1232 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1234 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1236 /* get storage location for DIB bits */
1240 SYSTEM_INFO SystemInfo;
1244 GetSystemInfo( &SystemInfo );
1245 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1246 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1247 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1248 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1253 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1254 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1256 dib->dshSection = section;
1257 dib->dsOffset = offset;
1259 if (!dib->dsBm.bmBits)
1261 HeapFree( GetProcessHeap(), 0, dib );
1265 /* If the reference hdc is null, take the desktop dc */
1268 hdc = CreateCompatibleDC(0);
1272 if (!(dc = get_dc_ptr( hdc ))) goto error;
1274 /* create Device Dependent Bitmap and add DIB pointer */
1275 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1276 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1278 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1280 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1282 bmp->funcs = physdev->funcs;
1283 /* create local copy of DIB palette */
1284 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1285 GDI_ReleaseObj( ret );
1287 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1289 DeleteObject( ret );
1294 release_dc_ptr( dc );
1295 if (bDesktopDC) DeleteDC( hdc );
1296 if (ret && bits) *bits = dib->dsBm.bmBits;
1300 if (bDesktopDC) DeleteDC( hdc );
1301 if (section) UnmapViewOfFile( mapBits );
1302 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1303 HeapFree( GetProcessHeap(), 0, dib );