2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize),
32 or use the internal function DIB_GetBitmapInfo.
35 * The palettes are stored in different formats:
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
46 If biCompression is BI_BITFIELDS, the color masks are at the same position
47 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48 the new headers have structure members for the masks.
51 * You should never access the color table using the bmiColors member,
52 because the passed structure may have one of the extended headers
53 mentioned above. Use this to calculate the location:
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
60 Search for "Bitmap Structures" in MSDN
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
76 /***********************************************************************
79 * Return the size of the bitmap info structure including color table.
81 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
83 unsigned int colors, size, masks = 0;
85 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
87 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
88 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
89 return sizeof(BITMAPCOREHEADER) + colors *
90 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
92 else /* assume BITMAPINFOHEADER */
94 colors = info->bmiHeader.biClrUsed;
95 if (colors > 256) colors = 256;
96 if (!colors && (info->bmiHeader.biBitCount <= 8))
97 colors = 1 << info->bmiHeader.biBitCount;
98 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
99 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
100 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
105 /***********************************************************************
108 * Get the info from a bitmap header.
109 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
111 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
112 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
114 if (header->biSize == sizeof(BITMAPCOREHEADER))
116 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
117 *width = core->bcWidth;
118 *height = core->bcHeight;
119 *planes = core->bcPlanes;
120 *bpp = core->bcBitCount;
125 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
127 *width = header->biWidth;
128 *height = header->biHeight;
129 *planes = header->biPlanes;
130 *bpp = header->biBitCount;
131 *compr = header->biCompression;
132 *size = header->biSizeImage;
135 ERR("(%d): unknown/wrong size for header\n", header->biSize );
139 /*******************************************************************************************
140 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
142 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info, UINT coloruse )
147 void *src_colors = (char *)info + info->bmiHeader.biSize;
149 int bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size );
151 if (bitmap_type == -1) return FALSE;
153 colors = (bpp > 8) ? 0 : 1 << bpp;
155 if (bitmap_type == 1)
157 dst->bmiHeader = info->bmiHeader;
158 dst->bmiHeader.biSize = sizeof(dst->bmiHeader);
160 if (info->bmiHeader.biClrUsed) colors = info->bmiHeader.biClrUsed;
162 if (info->bmiHeader.biCompression == BI_BITFIELDS)
163 /* bitfields are always at bmiColors even in larger structures */
164 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
169 if (coloruse == DIB_PAL_COLORS)
170 size = colors * sizeof(WORD);
172 size = colors * sizeof(RGBQUAD);
173 memcpy( dst->bmiColors, src_colors, size );
178 dst->bmiHeader.biSize = sizeof(dst->bmiHeader);
179 dst->bmiHeader.biWidth = width;
180 dst->bmiHeader.biHeight = height;
181 dst->bmiHeader.biPlanes = planes;
182 dst->bmiHeader.biBitCount = bpp;
183 dst->bmiHeader.biCompression = compr;
184 dst->bmiHeader.biSizeImage = size;
185 dst->bmiHeader.biXPelsPerMeter = 0;
186 dst->bmiHeader.biYPelsPerMeter = 0;
187 dst->bmiHeader.biClrUsed = 0;
188 dst->bmiHeader.biClrImportant = 0;
192 if (coloruse == DIB_PAL_COLORS)
193 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
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;
212 static int fill_color_table_from_palette( BITMAPINFO *info, DC *dc )
214 PALETTEENTRY palEntry[256];
215 int i, colors = (info->bmiHeader.biBitCount > 8) ? 0 : 1 << info->bmiHeader.biBitCount;
217 if (info->bmiHeader.biClrUsed) colors = info->bmiHeader.biClrUsed;
219 if (!colors) return 0;
221 memset( palEntry, 0, sizeof(palEntry) );
222 if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
225 for (i = 0; i < colors; i++)
227 info->bmiColors[i].rgbRed = palEntry[i].peRed;
228 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
229 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
230 info->bmiColors[i].rgbReserved = 0;
236 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
238 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
239 const int bpp = info->bmiHeader.biBitCount;
242 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
244 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
247 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
251 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
253 BYTE skip, num, data;
254 BYTE *out_bits, *in_bits = bits->ptr;
258 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
260 out_bits = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ) );
261 *clip = CreateRectRgn( 0, 0, 0, 0 );
262 run = CreateRectRgn( 0, 0, 0, 0 );
263 if (!out_bits || !*clip || !run) goto fail;
265 x = left = right = 0;
268 while (i < info->bmiHeader.biSizeImage - 1)
271 data = in_bits[i + 1];
276 if (x + num > width) num = width - x;
279 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
280 if (info->bmiHeader.biBitCount == 8)
281 memset( out_ptr, s, num );
286 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
287 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
292 /* this will write one too many if num is odd, but that doesn't matter */
293 if (num) memset( out_ptr, s, (num + 1) / 2 );
305 SetRectRgn( run, left, y, right, y + 1 );
306 CombineRgn( *clip, run, *clip, RGN_OR );
311 left = right = x = 0;
320 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
322 if (x > width) x = width;
329 else /* data bytes of data */
332 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
333 if (skip > info->bmiHeader.biSizeImage - i) goto done;
334 skip = (skip + 1) & ~1;
335 if (x + num > width) num = width - x;
338 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
339 if (info->bmiHeader.biBitCount == 8)
340 memcpy( out_ptr, in_bits + i, num );
345 const BYTE *in_ptr = in_bits + i;
346 for ( ; num; num--, x++)
350 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
354 *out_ptr = (*in_ptr++ << 4) & 0xf0;
358 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
370 if (bits->free) bits->free( bits );
372 bits->ptr = out_bits;
373 bits->is_copy = TRUE;
374 bits->free = free_heap_bits;
379 if (run) DeleteObject( run );
380 if (*clip) DeleteObject( *clip );
381 HeapFree( GetProcessHeap(), 0, out_bits );
387 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
388 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
389 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
390 const BITMAPINFO *info, UINT coloruse, DWORD rop )
392 DC *dc = get_nulldrv_dc( dev );
400 /* make sure we have a real implementation for StretchBlt and PutImage */
401 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pPutImage ) == dev)
404 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
407 if (width < 0) return 0;
409 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
410 info->bmiHeader.biCompression == BI_RGB)
412 /* Windows appears to have a fast case optimization
413 * that uses the wrong origin for top-down DIBs */
414 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
416 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
419 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
420 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
421 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
422 bm.bmBitsPixel == bpp && bm.bmPlanes == planes)
425 return SetDIBits( dev->hdc, hBitmap, 0, abs( height ), bits, info, coloruse );
430 hdcMem = CreateCompatibleDC( dev->hdc );
431 hBitmap = CreateCompatibleBitmap( dev->hdc, width, height );
432 SelectObject( hdcMem, hBitmap );
433 if (coloruse == DIB_PAL_COLORS)
434 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
436 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
438 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
439 * contain all the rectangle described in bmiHeader, but only part of it.
440 * This mean that those undescribed pixels must be left untouched.
441 * So, we first copy on a memory bitmap the current content of the
442 * destination rectangle, blit the DIB bits on top of it - hence leaving
443 * the gaps untouched -, and blitting the rectangle back.
444 * This insure that gaps are untouched on the destination rectangle
446 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
447 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
449 ret = SetDIBits( hdcMem, hBitmap, 0, abs( height ), bits, info, coloruse );
450 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
451 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
453 DeleteObject( hBitmap );
457 /***********************************************************************
458 * StretchDIBits (GDI32.@)
460 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
461 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
462 const BITMAPINFO *info, UINT coloruse, DWORD rop )
467 if (!bits || !info) return 0;
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,
503 DC *dc = get_dc_ptr( hdc );
504 BOOL delete_hdc = FALSE;
507 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
508 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
509 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
510 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
513 struct gdi_image_bits src_bits;
514 struct bitblt_coords src, dst;
515 INT src_to_dst_offset;
518 src_bits.ptr = (void *)bits;
519 src_bits.is_copy = FALSE;
520 src_bits.free = NULL;
521 src_bits.param = NULL;
523 if (coloruse == DIB_RGB_COLORS && !dc)
525 hdc = CreateCompatibleDC(0);
526 dc = get_dc_ptr( hdc );
534 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
536 release_dc_ptr( dc );
537 if (delete_hdc) DeleteDC(hdc);
541 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse )) goto done;
543 if (coloruse == DIB_PAL_COLORS)
544 if (!fill_color_table_from_palette( src_info, dc )) goto done;
546 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
548 if ( src_info->bmiHeader.biHeight < 0 ||
549 (src_info->bmiHeader.biCompression == BI_RLE4 && src_info->bmiHeader.biBitCount != 4) ||
550 (src_info->bmiHeader.biCompression == BI_RLE8 && src_info->bmiHeader.biBitCount != 8) )
552 SetLastError( ERROR_INVALID_PARAMETER );
556 if (lines == 0) goto done;
557 else lines = src_info->bmiHeader.biHeight;
560 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
563 dst.visrect.left = 0;
565 dst.visrect.right = bitmap->bitmap.bmWidth;
566 dst.visrect.bottom = bitmap->bitmap.bmHeight;
568 src.visrect.left = 0;
570 src.visrect.right = src_info->bmiHeader.biWidth;
571 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
573 if (src_info->bmiHeader.biHeight > 0)
575 src_to_dst_offset = -startscan;
576 lines = min( lines, src.visrect.bottom - startscan );
577 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
581 src_to_dst_offset = src.visrect.bottom - lines - startscan;
582 /* Unlike the bottom-up case, Windows doesn't limit lines. */
583 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
586 physdev = GET_DC_PHYSDEV( dc, pPutImage );
587 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) goto done;
591 offset_rect( &src.visrect, 0, src_to_dst_offset );
592 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
593 src.visrect = dst.visrect;
594 offset_rect( &src.visrect, 0, -src_to_dst_offset );
596 src.x = src.visrect.left;
597 src.y = src.visrect.top;
598 src.width = src.visrect.right - src.visrect.left;
599 src.height = src.visrect.bottom - src.visrect.top;
601 dst.x = dst.visrect.left;
602 dst.y = dst.visrect.top;
603 dst.width = dst.visrect.right - dst.visrect.left;
604 dst.height = dst.visrect.bottom - dst.visrect.top;
606 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
608 err = physdev->funcs->pPutImage( physdev, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
609 if (err == ERROR_BAD_FORMAT)
613 dst_info->bmiHeader.biWidth = dst.width;
614 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
617 err = convert_bitmapinfo( src_info, src_bits.ptr, &src.visrect, dst_info, ptr );
619 if (src_bits.free) src_bits.free( &src_bits );
621 src_bits.is_copy = TRUE;
622 src_bits.free = free_heap_bits;
624 err = physdev->funcs->pPutImage( physdev, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
627 else err = ERROR_OUTOFMEMORY;
632 if (src_bits.free) src_bits.free( &src_bits );
633 if (clip) DeleteObject( clip );
634 GDI_ReleaseObj( hbitmap );
635 release_dc_ptr( dc );
636 if (delete_hdc) DeleteDC(hdc);
641 /***********************************************************************
642 * SetDIBitsToDevice (GDI32.@)
644 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
645 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
646 UINT lines, LPCVOID bits, const BITMAPINFO *info,
654 if ((dc = get_dc_ptr( hdc )))
656 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
658 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
659 ySrc, startscan, lines, bits, info, coloruse );
660 release_dc_ptr( dc );
665 /***********************************************************************
666 * SetDIBColorTable (GDI32.@)
668 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
674 if (!(dc = get_dc_ptr( hdc ))) return 0;
676 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
678 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
680 /* Check if currently selected bitmap is a DIB */
681 if (bitmap->color_table)
683 if (startpos < bitmap->nb_colors)
685 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
686 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
690 GDI_ReleaseObj( dc->hBitmap );
691 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
693 release_dc_ptr( dc );
698 /***********************************************************************
699 * GetDIBColorTable (GDI32.@)
701 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
707 if (!(dc = get_dc_ptr( hdc ))) return 0;
709 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
711 /* Check if currently selected bitmap is a DIB */
712 if (bitmap->color_table)
714 if (startpos < bitmap->nb_colors)
716 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
717 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
721 GDI_ReleaseObj( dc->hBitmap );
723 release_dc_ptr( dc );
727 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
728 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
729 { 0x00, 0x00, 0x00, 0x00 },
730 { 0x00, 0x00, 0x80, 0x00 },
731 { 0x00, 0x80, 0x00, 0x00 },
732 { 0x00, 0x80, 0x80, 0x00 },
733 { 0x80, 0x00, 0x00, 0x00 },
734 { 0x80, 0x00, 0x80, 0x00 },
735 { 0x80, 0x80, 0x00, 0x00 },
736 { 0xc0, 0xc0, 0xc0, 0x00 },
737 { 0xc0, 0xdc, 0xc0, 0x00 },
738 { 0xf0, 0xca, 0xa6, 0x00 },
739 { 0xf0, 0xfb, 0xff, 0x00 },
740 { 0xa4, 0xa0, 0xa0, 0x00 },
741 { 0x80, 0x80, 0x80, 0x00 },
742 { 0x00, 0x00, 0xff, 0x00 },
743 { 0x00, 0xff, 0x00, 0x00 },
744 { 0x00, 0xff, 0xff, 0x00 },
745 { 0xff, 0x00, 0x00, 0x00 },
746 { 0xff, 0x00, 0xff, 0x00 },
747 { 0xff, 0xff, 0x00, 0x00 },
748 { 0xff, 0xff, 0xff, 0x00 }
751 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
752 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
753 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
755 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
757 BITMAPINFOHEADER header;
759 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
760 header.biWidth = bmp->bitmap.bmWidth;
761 header.biHeight = bmp->bitmap.bmHeight;
766 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
767 switch (bmp->dib->dsBm.bmBitsPixel)
771 header.biCompression = BI_BITFIELDS;
774 header.biCompression = BI_RGB;
780 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
781 header.biBitCount = bmp->bitmap.bmBitsPixel;
784 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
785 header.biXPelsPerMeter = 0;
786 header.biYPelsPerMeter = 0;
787 header.biClrUsed = 0;
788 header.biClrImportant = 0;
790 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
792 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
794 coreheader->bcWidth = header.biWidth;
795 coreheader->bcHeight = header.biHeight;
796 coreheader->bcPlanes = header.biPlanes;
797 coreheader->bcBitCount = header.biBitCount;
800 info->bmiHeader = header;
802 return abs(bmp->bitmap.bmHeight);
805 /************************************************************************
808 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
810 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
812 unsigned int colors = src->bmiHeader.biBitCount > 8 ? 0 : 1 << src->bmiHeader.biBitCount;
813 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
815 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
817 if (src->bmiHeader.biClrUsed) colors = src->bmiHeader.biClrUsed;
819 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
821 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
822 if (coloruse == DIB_PAL_COLORS)
823 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
827 for (i = 0; i < colors; i++)
829 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
830 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
831 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
837 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
838 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
840 if (src->bmiHeader.biCompression == BI_BITFIELDS)
841 /* bitfields are always at bmiColors even in larger structures */
842 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
845 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
848 if (coloruse == DIB_PAL_COLORS)
849 size = colors * sizeof(WORD);
851 size = colors * sizeof(RGBQUAD);
852 memcpy( colorptr, src_colors, size );
857 static void fill_default_color_table( BITMAPINFO *info )
861 switch (info->bmiHeader.biBitCount)
864 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
865 info->bmiColors[0].rgbReserved = 0;
866 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
867 info->bmiColors[1].rgbReserved = 0;
871 /* The EGA palette is the first and last 8 colours of the default palette
872 with the innermost pair swapped */
873 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
874 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
875 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
876 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
880 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
881 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
882 for (i = 10; i < 246; i++)
884 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
885 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
886 info->bmiColors[i].rgbBlue = i & 0xc0;
887 info->bmiColors[i].rgbReserved = 0;
892 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
896 /******************************************************************************
897 * GetDIBits [GDI32.@]
899 * Retrieves bits of bitmap and copies to buffer.
902 * Success: Number of scan lines copied from bitmap
905 INT WINAPI GetDIBits(
906 HDC hdc, /* [in] Handle to device context */
907 HBITMAP hbitmap, /* [in] Handle to bitmap */
908 UINT startscan, /* [in] First scan line to set in dest bitmap */
909 UINT lines, /* [in] Number of scan lines to copy */
910 LPVOID bits, /* [out] Address of array for bitmap bits */
911 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
912 UINT coloruse) /* [in] RGB or palette index */
922 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
923 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
924 unsigned int colors = 0;
928 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
929 if (bitmap_type == -1)
931 ERR("Invalid bitmap format\n");
934 if (!(dc = get_dc_ptr( hdc )))
936 SetLastError( ERROR_INVALID_PARAMETER );
940 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
942 release_dc_ptr( dc );
947 if (bpp == 0) /* query bitmap info only */
949 lines = fill_query_info( info, bmp );
953 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
954 own copy and transfer the colour info back at the end */
956 dst_info->bmiHeader.biSize = sizeof(dst_info->bmiHeader);
957 dst_info->bmiHeader.biWidth = width;
958 dst_info->bmiHeader.biHeight = height;
959 dst_info->bmiHeader.biPlanes = planes;
960 dst_info->bmiHeader.biBitCount = bpp;
961 dst_info->bmiHeader.biCompression = compr;
962 dst_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
963 dst_info->bmiHeader.biXPelsPerMeter = 0;
964 dst_info->bmiHeader.biYPelsPerMeter = 0;
965 dst_info->bmiHeader.biClrUsed = 0;
966 dst_info->bmiHeader.biClrImportant = 0;
976 /* If the bitmap object is a dib section at the
977 same color depth then get the color map from it */
978 if (bmp->dib && bpp == bmp->dib->dsBm.bmBitsPixel && coloruse == DIB_RGB_COLORS)
980 colors = min( colors, bmp->nb_colors );
981 if (colors != 1 << bpp) dst_info->bmiHeader.biClrUsed = colors;
982 memcpy( dst_info->bmiColors, bmp->color_table, colors * sizeof(RGBQUAD) );
985 /* For color DDBs in native depth (mono DDBs always have a black/white palette):
986 Generate the color map from the selected palette. In the DIB_PAL_COLORS
987 case we'll fix up the indices after the format conversion. */
988 else if ( (bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) || coloruse == DIB_PAL_COLORS )
990 if (!fill_color_table_from_palette( dst_info, dc ))
997 fill_default_color_table( dst_info );
1002 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
1003 memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1007 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
1011 if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
1012 memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
1014 memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1017 memcpy( dst_info->bmiColors, bit_fields_565, sizeof(bit_fields_565) );
1023 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
1025 if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
1026 memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
1028 memcpy( dst_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1035 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1036 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1037 struct gdi_image_bits src_bits;
1038 struct bitblt_coords src;
1041 src.visrect.left = 0;
1042 src.visrect.right = min( width, bmp->bitmap.bmWidth );
1044 if (startscan >= bmp->bitmap.bmHeight) /* constrain lines to within src bitmap */
1047 lines = min( lines, bmp->bitmap.bmHeight - startscan );
1048 lines = min( lines, abs(height) ); /* and constrain to within dest bitmap */
1050 if (lines == 0) goto done;
1052 src.visrect.bottom = bmp->bitmap.bmHeight - startscan;
1053 src.visrect.top = src.visrect.bottom - lines;
1054 src.x = src.visrect.left;
1055 src.y = src.visrect.top;
1056 src.width = src.visrect.right - src.visrect.left;
1057 src.height = src.visrect.bottom - src.visrect.top;
1059 err = bmp->funcs->pGetImage( NULL, hbitmap, src_info, &src_bits, &src );
1066 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1069 memcpy( src_info->bmiColors, bmp->color_table, bmp->nb_colors * sizeof(RGBQUAD) );
1071 fill_default_color_table( src_info );
1074 if(dst_info->bmiHeader.biHeight > 0)
1075 dst_info->bmiHeader.biHeight = lines;
1077 dst_info->bmiHeader.biHeight = -lines;
1079 convert_bitmapinfo( src_info, src_bits.ptr, &src.visrect, dst_info, bits );
1080 if (src_bits.free) src_bits.free( &src_bits );
1082 else lines = abs(height);
1084 if (coloruse == DIB_PAL_COLORS)
1086 WORD *index = (WORD *)dst_info->bmiColors;
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,
1116 if (!header) return 0;
1118 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1122 TRACE("Bitmap has a negative width\n");
1126 /* Top-down DIBs have a negative height */
1127 if (height < 0) height = -height;
1129 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1130 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1133 handle = CreateBitmap( width, height, 1, 1, NULL );
1135 handle = CreateCompatibleBitmap( hdc, width, height );
1139 if (init & CBM_INIT)
1141 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1143 DeleteObject( handle );
1152 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1153 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1155 RGBQUAD *colorTable;
1156 unsigned int colors, i;
1157 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1161 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1165 colors = info->bmiHeader.biClrUsed;
1166 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1170 ERR("called with >256 colors!\n");
1174 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1176 if(coloruse == DIB_RGB_COLORS)
1180 /* Convert RGBTRIPLEs to RGBQUADs */
1181 for (i=0; i < colors; i++)
1183 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1184 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1185 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1186 colorTable[i].rgbReserved = 0;
1191 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1196 PALETTEENTRY entries[256];
1197 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1198 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1200 for (i = 0; i < colors; i++, index++)
1202 PALETTEENTRY *entry = &entries[*index % count];
1203 colorTable[i].rgbRed = entry->peRed;
1204 colorTable[i].rgbGreen = entry->peGreen;
1205 colorTable[i].rgbBlue = entry->peBlue;
1206 colorTable[i].rgbReserved = 0;
1209 bmp->color_table = colorTable;
1210 bmp->nb_colors = colors;
1213 /***********************************************************************
1214 * CreateDIBSection (GDI32.@)
1216 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1217 VOID **bits, HANDLE section, DWORD offset)
1221 BOOL bDesktopDC = FALSE;
1227 DWORD compression, sizeImage;
1228 void *mapBits = NULL;
1231 if(bits) *bits = NULL;
1235 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1236 &planes, &bpp, &compression, &sizeImage )) == -1))
1243 if (compression == BI_BITFIELDS) break;
1249 if (compression == BI_RGB) break;
1252 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1256 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1258 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1259 width, height, planes, bpp, compression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1260 sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1262 dib->dsBm.bmType = 0;
1263 dib->dsBm.bmWidth = width;
1264 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1265 dib->dsBm.bmWidthBytes = get_dib_stride( width, bpp );
1266 dib->dsBm.bmPlanes = planes;
1267 dib->dsBm.bmBitsPixel = bpp;
1268 dib->dsBm.bmBits = NULL;
1270 if (!bitmap_type) /* core header */
1272 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1273 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1274 dib->dsBmih.biWidth = width;
1275 dib->dsBmih.biHeight = height;
1276 dib->dsBmih.biPlanes = planes;
1277 dib->dsBmih.biBitCount = bpp;
1278 dib->dsBmih.biCompression = compression;
1279 dib->dsBmih.biXPelsPerMeter = 0;
1280 dib->dsBmih.biYPelsPerMeter = 0;
1281 dib->dsBmih.biClrUsed = 0;
1282 dib->dsBmih.biClrImportant = 0;
1286 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1287 dib->dsBmih = bmi->bmiHeader;
1288 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1291 /* set number of entries in bmi.bmiColors table */
1293 dib->dsBmih.biClrUsed = 1 << bpp;
1295 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1297 /* set dsBitfields values */
1298 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1300 if((bpp == 15 || bpp == 16) && compression == BI_RGB)
1302 /* In this case Windows changes biCompression to BI_BITFIELDS,
1303 however for now we won't do this, as there are a lot
1304 of places where BI_BITFIELDS is currently unsupported. */
1306 /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
1307 dib->dsBitfields[0] = 0x7c00;
1308 dib->dsBitfields[1] = 0x03e0;
1309 dib->dsBitfields[2] = 0x001f;
1311 else if(compression == BI_BITFIELDS)
1313 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1314 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1315 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1318 /* get storage location for DIB bits */
1322 SYSTEM_INFO SystemInfo;
1326 GetSystemInfo( &SystemInfo );
1327 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1328 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1329 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1330 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1335 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1336 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1338 dib->dshSection = section;
1339 dib->dsOffset = offset;
1341 if (!dib->dsBm.bmBits)
1343 HeapFree( GetProcessHeap(), 0, dib );
1347 /* If the reference hdc is null, take the desktop dc */
1350 hdc = CreateCompatibleDC(0);
1354 if (!(dc = get_dc_ptr( hdc ))) goto error;
1356 /* create Device Dependent Bitmap and add DIB pointer */
1357 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1358 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1360 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1362 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1364 bmp->funcs = physdev->funcs;
1365 /* create local copy of DIB palette */
1366 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1367 GDI_ReleaseObj( ret );
1369 if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1371 DeleteObject( ret );
1376 release_dc_ptr( dc );
1377 if (bDesktopDC) DeleteDC( hdc );
1378 if (ret && bits) *bits = dib->dsBm.bmBits;
1382 if (bDesktopDC) DeleteDC( hdc );
1383 if (section) UnmapViewOfFile( mapBits );
1384 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1385 HeapFree( GetProcessHeap(), 0, dib );