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 (dst->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, HDC hdc )
212 PALETTEENTRY palEntry[256];
213 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
214 int i, colors = get_dib_num_of_colors( info );
216 if (!palette) return 0;
217 if (!colors) return 0;
219 memset( palEntry, 0, sizeof(palEntry) );
220 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
223 for (i = 0; i < colors; i++)
225 info->bmiColors[i].rgbRed = palEntry[i].peRed;
226 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
227 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
228 info->bmiColors[i].rgbReserved = 0;
234 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
236 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
237 const int bpp = info->bmiHeader.biBitCount;
240 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
242 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
245 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
249 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
251 BYTE skip, num, data;
252 BYTE *out_bits, *in_bits = bits->ptr;
256 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
258 out_bits = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ) );
259 *clip = CreateRectRgn( 0, 0, 0, 0 );
260 run = CreateRectRgn( 0, 0, 0, 0 );
261 if (!out_bits || !*clip || !run) goto fail;
263 x = left = right = 0;
266 while (i < info->bmiHeader.biSizeImage - 1)
269 data = in_bits[i + 1];
274 if (x + num > width) num = width - x;
277 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
278 if (info->bmiHeader.biBitCount == 8)
279 memset( out_ptr, s, num );
284 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
285 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
290 /* this will write one too many if num is odd, but that doesn't matter */
291 if (num) memset( out_ptr, s, (num + 1) / 2 );
303 SetRectRgn( run, left, y, right, y + 1 );
304 CombineRgn( *clip, run, *clip, RGN_OR );
309 left = right = x = 0;
318 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
320 if (x > width) x = width;
327 else /* data bytes of data */
330 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
331 if (skip > info->bmiHeader.biSizeImage - i) goto done;
332 skip = (skip + 1) & ~1;
333 if (x + num > width) num = width - x;
336 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
337 if (info->bmiHeader.biBitCount == 8)
338 memcpy( out_ptr, in_bits + i, num );
343 const BYTE *in_ptr = in_bits + i;
344 for ( ; num; num--, x++)
348 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
352 *out_ptr = (*in_ptr++ << 4) & 0xf0;
356 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
368 if (bits->free) bits->free( bits );
370 bits->ptr = out_bits;
371 bits->is_copy = TRUE;
372 bits->free = free_heap_bits;
377 if (run) DeleteObject( run );
378 if (*clip) DeleteObject( *clip );
379 HeapFree( GetProcessHeap(), 0, out_bits );
385 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
386 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
387 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
388 BITMAPINFO *info, UINT coloruse, DWORD rop )
390 DC *dc = get_nulldrv_dc( dev );
396 /* make sure we have a real implementation for StretchBlt and PutImage */
397 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pPutImage ) == dev)
400 height = info->bmiHeader.biHeight;
402 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
403 info->bmiHeader.biCompression == BI_RGB)
405 /* Windows appears to have a fast case optimization
406 * that uses the wrong origin for top-down DIBs */
407 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
409 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
412 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
413 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
414 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
415 bm.bmBitsPixel == info->bmiHeader.biBitCount && bm.bmPlanes == 1)
418 return SetDIBits( dev->hdc, hBitmap, 0, abs( height ), bits, info, coloruse );
423 hdcMem = CreateCompatibleDC( dev->hdc );
424 hBitmap = CreateCompatibleBitmap( dev->hdc, info->bmiHeader.biWidth, height );
425 SelectObject( hdcMem, hBitmap );
426 if (coloruse == DIB_PAL_COLORS)
427 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
429 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
431 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
432 * contain all the rectangle described in bmiHeader, but only part of it.
433 * This mean that those undescribed pixels must be left untouched.
434 * So, we first copy on a memory bitmap the current content of the
435 * destination rectangle, blit the DIB bits on top of it - hence leaving
436 * the gaps untouched -, and blitting the rectangle back.
437 * This insure that gaps are untouched on the destination rectangle
439 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
440 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
442 ret = SetDIBits( hdcMem, hBitmap, 0, abs( height ), bits, info, coloruse );
443 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
444 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
446 DeleteObject( hBitmap );
450 /***********************************************************************
451 * StretchDIBits (GDI32.@)
453 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
454 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
455 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
457 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
458 BITMAPINFO *info = (BITMAPINFO *)buffer;
463 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
465 SetLastError( ERROR_INVALID_PARAMETER );
469 if ((dc = get_dc_ptr( hdc )))
471 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
473 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
474 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
475 release_dc_ptr( dc );
481 /******************************************************************************
482 * SetDIBits [GDI32.@]
484 * Sets pixels in a bitmap using colors from DIB.
487 * hdc [I] Handle to device context
488 * hbitmap [I] Handle to bitmap
489 * startscan [I] Starting scan line
490 * lines [I] Number of scan lines
491 * bits [I] Array of bitmap bits
492 * info [I] Address of structure with data
493 * coloruse [I] Type of color indexes to use
496 * Success: Number of scan lines copied
499 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
500 UINT lines, LPCVOID bits, const BITMAPINFO *info,
504 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
505 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
506 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
507 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
510 struct gdi_image_bits src_bits;
511 struct bitblt_coords src, dst;
512 INT src_to_dst_offset;
514 const struct gdi_dc_funcs *funcs;
516 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
518 SetLastError( ERROR_INVALID_PARAMETER );
522 src_bits.ptr = (void *)bits;
523 src_bits.is_copy = FALSE;
524 src_bits.free = NULL;
525 src_bits.param = NULL;
527 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, hdc )) return 0;
529 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
531 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
533 if (lines == 0) goto done;
534 else lines = src_info->bmiHeader.biHeight;
537 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
540 dst.visrect.left = 0;
542 dst.visrect.right = bitmap->bitmap.bmWidth;
543 dst.visrect.bottom = bitmap->bitmap.bmHeight;
545 src.visrect.left = 0;
547 src.visrect.right = src_info->bmiHeader.biWidth;
548 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
550 if (src_info->bmiHeader.biHeight > 0)
552 src_to_dst_offset = -startscan;
553 lines = min( lines, src.visrect.bottom - startscan );
554 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
558 src_to_dst_offset = src.visrect.bottom - lines - startscan;
559 /* Unlike the bottom-up case, Windows doesn't limit lines. */
560 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
563 funcs = get_bitmap_funcs( bitmap );
567 offset_rect( &src.visrect, 0, src_to_dst_offset );
568 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
569 src.visrect = dst.visrect;
570 offset_rect( &src.visrect, 0, -src_to_dst_offset );
572 src.x = src.visrect.left;
573 src.y = src.visrect.top;
574 src.width = src.visrect.right - src.visrect.left;
575 src.height = src.visrect.bottom - src.visrect.top;
577 dst.x = dst.visrect.left;
578 dst.y = dst.visrect.top;
579 dst.width = dst.visrect.right - dst.visrect.left;
580 dst.height = dst.visrect.bottom - dst.visrect.top;
582 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
584 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
585 if (err == ERROR_BAD_FORMAT)
589 dst_info->bmiHeader.biWidth = dst.width;
590 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
593 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr );
594 if (src_bits.free) src_bits.free( &src_bits );
596 src_bits.is_copy = TRUE;
597 src_bits.free = free_heap_bits;
599 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
601 else err = ERROR_OUTOFMEMORY;
606 if (src_bits.free) src_bits.free( &src_bits );
607 if (clip) DeleteObject( clip );
608 GDI_ReleaseObj( hbitmap );
613 /***********************************************************************
614 * SetDIBitsToDevice (GDI32.@)
616 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
617 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
618 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
621 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
622 BITMAPINFO *info = (BITMAPINFO *)buffer;
627 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
629 SetLastError( ERROR_INVALID_PARAMETER );
633 if ((dc = get_dc_ptr( hdc )))
635 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
637 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
638 ySrc, startscan, lines, bits, info, coloruse );
639 release_dc_ptr( dc );
644 /***********************************************************************
645 * SetDIBColorTable (GDI32.@)
647 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
653 if (!(dc = get_dc_ptr( hdc ))) return 0;
655 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
657 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
659 /* Check if currently selected bitmap is a DIB */
660 if (bitmap->color_table)
662 if (startpos < bitmap->nb_colors)
664 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
665 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
669 GDI_ReleaseObj( dc->hBitmap );
670 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
672 release_dc_ptr( dc );
677 /***********************************************************************
678 * GetDIBColorTable (GDI32.@)
680 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
686 if (!(dc = get_dc_ptr( hdc ))) return 0;
688 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
690 /* Check if currently selected bitmap is a DIB */
691 if (bitmap->color_table)
693 if (startpos < bitmap->nb_colors)
695 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
696 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
700 GDI_ReleaseObj( dc->hBitmap );
702 release_dc_ptr( dc );
706 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
707 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
708 { 0x00, 0x00, 0x00, 0x00 },
709 { 0x00, 0x00, 0x80, 0x00 },
710 { 0x00, 0x80, 0x00, 0x00 },
711 { 0x00, 0x80, 0x80, 0x00 },
712 { 0x80, 0x00, 0x00, 0x00 },
713 { 0x80, 0x00, 0x80, 0x00 },
714 { 0x80, 0x80, 0x00, 0x00 },
715 { 0xc0, 0xc0, 0xc0, 0x00 },
716 { 0xc0, 0xdc, 0xc0, 0x00 },
717 { 0xf0, 0xca, 0xa6, 0x00 },
718 { 0xf0, 0xfb, 0xff, 0x00 },
719 { 0xa4, 0xa0, 0xa0, 0x00 },
720 { 0x80, 0x80, 0x80, 0x00 },
721 { 0x00, 0x00, 0xff, 0x00 },
722 { 0x00, 0xff, 0x00, 0x00 },
723 { 0x00, 0xff, 0xff, 0x00 },
724 { 0xff, 0x00, 0x00, 0x00 },
725 { 0xff, 0x00, 0xff, 0x00 },
726 { 0xff, 0xff, 0x00, 0x00 },
727 { 0xff, 0xff, 0xff, 0x00 }
730 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
731 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
732 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
734 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
736 BITMAPINFOHEADER header;
738 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
739 header.biWidth = bmp->bitmap.bmWidth;
740 header.biHeight = bmp->bitmap.bmHeight;
745 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
746 switch (bmp->dib->dsBm.bmBitsPixel)
750 header.biCompression = BI_BITFIELDS;
753 header.biCompression = BI_RGB;
759 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
760 header.biBitCount = bmp->bitmap.bmBitsPixel;
763 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
764 header.biXPelsPerMeter = 0;
765 header.biYPelsPerMeter = 0;
766 header.biClrUsed = 0;
767 header.biClrImportant = 0;
769 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
771 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
773 coreheader->bcWidth = header.biWidth;
774 coreheader->bcHeight = header.biHeight;
775 coreheader->bcPlanes = header.biPlanes;
776 coreheader->bcBitCount = header.biBitCount;
779 info->bmiHeader = header;
781 return abs(bmp->bitmap.bmHeight);
784 /************************************************************************
787 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
789 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
791 unsigned int colors = get_dib_num_of_colors( src );
792 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
794 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
796 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
798 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
799 if (coloruse == DIB_PAL_COLORS)
800 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
804 for (i = 0; i < colors; i++)
806 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
807 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
808 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
814 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
815 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
817 if (src->bmiHeader.biCompression == BI_BITFIELDS)
818 /* bitfields are always at bmiColors even in larger structures */
819 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
822 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
825 if (coloruse == DIB_PAL_COLORS)
826 size = colors * sizeof(WORD);
828 size = colors * sizeof(RGBQUAD);
829 memcpy( colorptr, src_colors, size );
834 static void fill_default_color_table( BITMAPINFO *info )
838 switch (info->bmiHeader.biBitCount)
841 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
842 info->bmiColors[0].rgbReserved = 0;
843 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
844 info->bmiColors[1].rgbReserved = 0;
848 /* The EGA palette is the first and last 8 colours of the default palette
849 with the innermost pair swapped */
850 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
851 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
852 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
853 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
857 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
858 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
859 for (i = 10; i < 246; i++)
861 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
862 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
863 info->bmiColors[i].rgbBlue = i & 0xc0;
864 info->bmiColors[i].rgbReserved = 0;
869 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
873 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
875 info->bmiHeader.biSize = sizeof(info->bmiHeader);
876 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
877 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
878 info->bmiHeader.biPlanes = 1;
879 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
880 info->bmiHeader.biCompression = BI_RGB;
881 info->bmiHeader.biXPelsPerMeter = 0;
882 info->bmiHeader.biYPelsPerMeter = 0;
883 info->bmiHeader.biClrUsed = 0;
884 info->bmiHeader.biClrImportant = 0;
885 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
889 /******************************************************************************
890 * GetDIBits [GDI32.@]
892 * Retrieves bits of bitmap and copies to buffer.
895 * Success: Number of scan lines copied from bitmap
898 INT WINAPI GetDIBits(
899 HDC hdc, /* [in] Handle to device context */
900 HBITMAP hbitmap, /* [in] Handle to bitmap */
901 UINT startscan, /* [in] First scan line to set in dest bitmap */
902 UINT lines, /* [in] Number of scan lines to copy */
903 LPVOID bits, /* [out] Address of array for bitmap bits */
904 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
905 UINT coloruse) /* [in] RGB or palette index */
909 int i, dst_to_src_offset, ret = 0;
911 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
912 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
913 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
914 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
915 const struct gdi_dc_funcs *funcs;
916 struct gdi_image_bits src_bits;
917 struct bitblt_coords src, dst;
918 BOOL empty_rect = FALSE;
920 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
921 own copy and transfer the colour info back at the end */
922 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
924 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
926 dst_info->bmiHeader.biClrUsed = 0;
927 dst_info->bmiHeader.biClrImportant = 0;
929 if (!(dc = get_dc_ptr( hdc )))
931 SetLastError( ERROR_INVALID_PARAMETER );
935 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
937 release_dc_ptr( dc );
941 funcs = get_bitmap_funcs( bmp );
943 src.visrect.left = 0;
945 src.visrect.right = bmp->bitmap.bmWidth;
946 src.visrect.bottom = bmp->bitmap.bmHeight;
948 dst.visrect.left = 0;
950 dst.visrect.right = dst_info->bmiHeader.biWidth;
951 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
953 if (lines == 0 || startscan >= dst.visrect.bottom)
956 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
958 ret = fill_query_info( info, bmp );
962 /* validate parameters */
964 if (dst_info->bmiHeader.biWidth <= 0) goto done;
965 if (dst_info->bmiHeader.biHeight == 0) goto done;
967 switch (dst_info->bmiHeader.biCompression)
970 if (dst_info->bmiHeader.biBitCount != 4) goto done;
971 if (dst_info->bmiHeader.biHeight < 0) goto done;
972 if (bits) goto done; /* can't retrieve compressed bits */
975 if (dst_info->bmiHeader.biBitCount != 8) goto done;
976 if (dst_info->bmiHeader.biHeight < 0) goto done;
977 if (bits) goto done; /* can't retrieve compressed bits */
980 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
983 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
984 if (dst_info->bmiHeader.biBitCount == 1) break;
985 if (dst_info->bmiHeader.biBitCount == 4) break;
986 if (dst_info->bmiHeader.biBitCount == 8) break;
987 if (dst_info->bmiHeader.biBitCount == 16) break;
988 if (dst_info->bmiHeader.biBitCount == 24) break;
989 if (dst_info->bmiHeader.biBitCount == 32) break;
997 if (dst_info->bmiHeader.biHeight > 0)
999 dst_to_src_offset = -startscan;
1000 lines = min( lines, dst.visrect.bottom - startscan );
1001 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1005 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1006 if (dst_to_src_offset < 0)
1008 dst_to_src_offset = 0;
1009 lines = dst.visrect.bottom - startscan;
1011 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1014 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1015 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1016 dst.visrect = src.visrect;
1017 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1019 if (dst_info->bmiHeader.biHeight > 0)
1021 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1023 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1024 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1025 memset( bits, 0, pad_bytes );
1026 bits = (char *)bits + pad_bytes;
1031 if (dst.visrect.bottom < lines)
1033 int pad_lines = lines - dst.visrect.bottom;
1034 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1035 int pad_bytes = pad_lines * stride;
1036 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1040 if (empty_rect) bits = NULL;
1042 src.x = src.visrect.left;
1043 src.y = src.visrect.top;
1044 src.width = src.visrect.right - src.visrect.left;
1045 src.height = src.visrect.bottom - src.visrect.top;
1050 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1054 /* fill out the src colour table, if it needs one */
1055 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1057 fill_default_color_table( src_info );
1058 src_info->bmiHeader.biClrUsed = 1 << src_info->bmiHeader.biBitCount;
1061 /* if the src and dst are the same depth, copy the colour info across */
1062 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1064 switch (src_info->bmiHeader.biBitCount)
1067 if (src_info->bmiHeader.biCompression == BI_RGB)
1069 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1070 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1074 if (src_info->bmiHeader.biCompression == BI_RGB)
1076 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1077 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1081 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1082 copy_color_info( dst_info, src_info, coloruse );
1084 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1086 if( coloruse == DIB_PAL_COLORS )
1088 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1092 fill_default_color_table( dst_info );
1098 if(dst_info->bmiHeader.biHeight > 0)
1099 dst_info->bmiHeader.biHeight = src.height;
1101 dst_info->bmiHeader.biHeight = -src.height;
1103 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
1104 if (src_bits.free) src_bits.free( &src_bits );
1108 ret = empty_rect ? FALSE : TRUE;
1110 if (coloruse == DIB_PAL_COLORS)
1112 WORD *index = (WORD *)dst_info->bmiColors;
1113 int colors = get_dib_num_of_colors( dst_info );
1114 for (i = 0; i < colors; i++, index++)
1118 copy_color_info( info, dst_info, coloruse );
1121 release_dc_ptr( dc );
1122 GDI_ReleaseObj( hbitmap );
1127 /***********************************************************************
1128 * CreateDIBitmap (GDI32.@)
1130 * Creates a DDB (device dependent bitmap) from a DIB.
1131 * The DDB will have the same color depth as the reference DC.
1133 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1134 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1137 BITMAPINFOHEADER info;
1141 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1142 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1143 if (info.biWidth < 0) return 0;
1145 /* Top-down DIBs have a negative height */
1146 height = abs( info.biHeight );
1148 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1149 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1150 info.biBitCount, info.biCompression);
1153 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1155 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1159 if (init & CBM_INIT)
1161 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1163 DeleteObject( handle );
1172 /* Copy/synthesize RGB palette from BITMAPINFO */
1173 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1175 unsigned int colors, i;
1177 colors = get_dib_num_of_colors( info );
1178 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1179 bmp->nb_colors = colors;
1181 if (coloruse == DIB_RGB_COLORS)
1183 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1187 PALETTEENTRY entries[256];
1188 const WORD *index = (const WORD *)info->bmiColors;
1189 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1191 for (i = 0; i < colors; i++, index++)
1193 PALETTEENTRY *entry = &entries[*index % count];
1194 bmp->color_table[i].rgbRed = entry->peRed;
1195 bmp->color_table[i].rgbGreen = entry->peGreen;
1196 bmp->color_table[i].rgbBlue = entry->peBlue;
1197 bmp->color_table[i].rgbReserved = 0;
1202 /***********************************************************************
1203 * CreateDIBSection (GDI32.@)
1205 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1206 VOID **bits, HANDLE section, DWORD offset)
1208 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1209 BITMAPINFO *info = (BITMAPINFO *)buffer;
1212 BOOL bDesktopDC = FALSE;
1215 void *mapBits = NULL;
1217 if (bits) *bits = NULL;
1218 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1219 if (info->bmiHeader.biPlanes != 1)
1221 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1222 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1225 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1227 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1228 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1229 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1230 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1231 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1233 dib->dsBm.bmType = 0;
1234 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1235 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1236 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1237 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1238 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1239 dib->dsBm.bmBits = NULL;
1240 dib->dsBmih = info->bmiHeader;
1242 /* set number of entries in bmi.bmiColors table */
1243 if( info->bmiHeader.biBitCount <= 8 )
1244 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1246 /* set dsBitfields values */
1247 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1249 dib->dsBmih.biCompression = BI_BITFIELDS;
1250 dib->dsBitfields[0] = 0x7c00;
1251 dib->dsBitfields[1] = 0x03e0;
1252 dib->dsBitfields[2] = 0x001f;
1254 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1256 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1257 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1258 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1259 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1261 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1263 /* get storage location for DIB bits */
1267 SYSTEM_INFO SystemInfo;
1271 GetSystemInfo( &SystemInfo );
1272 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1273 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1274 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1275 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1280 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1281 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1283 dib->dshSection = section;
1284 dib->dsOffset = offset;
1286 if (!dib->dsBm.bmBits)
1288 HeapFree( GetProcessHeap(), 0, dib );
1292 /* If the reference hdc is null, take the desktop dc */
1295 hdc = CreateCompatibleDC(0);
1299 if (!(dc = get_dc_ptr( hdc ))) goto error;
1301 /* create Device Dependent Bitmap and add DIB pointer */
1302 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1303 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1305 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1307 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1309 bmp->funcs = physdev->funcs;
1310 /* create local copy of DIB palette */
1311 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1312 GDI_ReleaseObj( ret );
1314 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1316 DeleteObject( ret );
1321 release_dc_ptr( dc );
1322 if (bDesktopDC) DeleteDC( hdc );
1323 if (ret && bits) *bits = dib->dsBm.bmBits;
1327 if (bDesktopDC) DeleteDC( hdc );
1328 if (section) UnmapViewOfFile( mapBits );
1329 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1330 HeapFree( GetProcessHeap(), 0, dib );