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) );
187 dst->bmiHeader.biClrUsed = 0;
191 if (coloruse == DIB_PAL_COLORS)
192 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
193 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
194 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
198 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
199 for (i = 0; i < colors; i++)
201 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
202 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
203 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
204 dst->bmiColors[i].rgbReserved = 0;
207 dst->bmiHeader.biClrUsed = colors;
212 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
214 PALETTEENTRY palEntry[256];
215 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
216 int i, colors = get_dib_num_of_colors( info );
218 if (!palette) return 0;
219 if (!colors) return 0;
221 memset( palEntry, 0, sizeof(palEntry) );
222 if (!GetPaletteEntries( palette, 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;
256 if (clip) *clip = NULL;
258 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
260 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
261 if (!out_bits) goto fail;
265 *clip = CreateRectRgn( 0, 0, 0, 0 );
266 run = CreateRectRgn( 0, 0, 0, 0 );
267 if (!*clip || !run) goto fail;
270 x = left = right = 0;
273 while (i < info->bmiHeader.biSizeImage - 1)
276 data = in_bits[i + 1];
281 if (x + num > width) num = width - x;
284 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
285 if (info->bmiHeader.biBitCount == 8)
286 memset( out_ptr, s, num );
291 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
292 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
297 /* this will write one too many if num is odd, but that doesn't matter */
298 if (num) memset( out_ptr, s, (num + 1) / 2 );
308 if(left != right && clip)
310 SetRectRgn( run, left, y, right, y + 1 );
311 CombineRgn( *clip, run, *clip, RGN_OR );
316 left = right = x = 0;
325 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
327 if (x > width) x = width;
334 else /* data bytes of data */
337 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
338 if (skip > info->bmiHeader.biSizeImage - i) goto done;
339 skip = (skip + 1) & ~1;
340 if (x + num > width) num = width - x;
343 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
344 if (info->bmiHeader.biBitCount == 8)
345 memcpy( out_ptr, in_bits + i, num );
350 const BYTE *in_ptr = in_bits + i;
351 for ( ; num; num--, x++)
355 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
359 *out_ptr = (*in_ptr++ << 4) & 0xf0;
363 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
374 if (run) DeleteObject( run );
375 if (bits->free) bits->free( bits );
377 bits->ptr = out_bits;
378 bits->is_copy = TRUE;
379 bits->free = free_heap_bits;
384 if (run) DeleteObject( run );
385 if (clip && *clip) DeleteObject( *clip );
386 HeapFree( GetProcessHeap(), 0, out_bits );
392 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
393 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
394 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
396 DC *dc = get_nulldrv_dc( dev );
397 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
398 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
399 struct bitblt_coords src, dst;
400 struct gdi_image_bits src_bits;
404 INT height = abs( src_info->bmiHeader.biHeight );
405 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
406 RECT rect, clip_rect;
408 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
409 xSrc, ySrc, widthSrc, heightSrc, rop);
411 src_bits.ptr = (void*)bits;
412 src_bits.is_copy = FALSE;
413 src_bits.free = NULL;
415 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
419 rect.right = xDst + widthDst;
420 rect.bottom = yDst + heightDst;
421 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
424 dst.width = rect.right - rect.left;
425 dst.height = rect.bottom - rect.top;
427 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
430 dst.width = -dst.width;
432 rop &= ~NOMIRRORBITMAP;
435 src.width = widthSrc;
437 src.height = heightSrc;
439 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
440 non_stretch_from_origin = TRUE;
442 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
444 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
445 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
448 if (rop != SRCCOPY || non_stretch_from_origin)
450 if (dst.width == 1 && src.width > 1) src.width--;
451 if (dst.height == 1 && src.height > 1) src.height--;
456 if (dst.width < 0 && dst.width == src.width)
458 /* This is off-by-one, but that's what Windows does */
461 dst.width = -dst.width;
462 src.width = -src.width;
464 if (dst.height < 0 && dst.height == src.height)
468 dst.height = -dst.height;
469 src.height = -src.height;
473 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
475 if (src.y >= height && src.y + src.height + 1 < height)
477 else if (src.y > 0 && src.y + src.height + 1 < 0)
478 src.y = -src.height - 1;
480 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
482 src.visrect.left = 0;
483 src.visrect.right = src_info->bmiHeader.biWidth;
485 src.visrect.bottom = height;
486 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
488 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
490 if (get_clip_box( dc, &clip_rect ))
491 intersect_rect( &dst.visrect, &rect, &clip_rect );
494 if (is_rect_empty( &dst.visrect )) goto done;
496 if (!intersect_vis_rectangles( &dst, &src )) goto done;
498 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
500 dev = GET_DC_PHYSDEV( dc, pPutImage );
501 copy_bitmapinfo( dst_info, src_info );
502 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
503 if (err == ERROR_BAD_FORMAT)
505 /* 1-bpp destination without a color table requires a fake 1-entry table
506 * that contains only the background color */
507 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
509 COLORREF color = GetBkColor( dev->hdc );
510 dst_info->bmiColors[0].rgbRed = GetRValue( color );
511 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
512 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
513 dst_info->bmiColors[0].rgbReserved = 0;
514 dst_info->bmiHeader.biClrUsed = 1;
517 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
519 /* get rid of the fake 1-bpp table */
520 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
521 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
525 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
527 copy_bitmapinfo( src_info, dst_info );
528 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
529 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
532 else if (rop == SRCCOPY) ret = height;
533 else ret = src_info->bmiHeader.biHeight;
536 if (src_bits.free) src_bits.free( &src_bits );
537 if (clip) DeleteObject( clip );
541 /***********************************************************************
542 * StretchDIBits (GDI32.@)
544 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
545 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
546 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
548 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
549 BITMAPINFO *info = (BITMAPINFO *)buffer;
554 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
556 SetLastError( ERROR_INVALID_PARAMETER );
560 if ((dc = get_dc_ptr( hdc )))
562 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
564 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
565 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
566 release_dc_ptr( dc );
572 /******************************************************************************
573 * SetDIBits [GDI32.@]
575 * Sets pixels in a bitmap using colors from DIB.
578 * hdc [I] Handle to device context
579 * hbitmap [I] Handle to bitmap
580 * startscan [I] Starting scan line
581 * lines [I] Number of scan lines
582 * bits [I] Array of bitmap bits
583 * info [I] Address of structure with data
584 * coloruse [I] Type of color indexes to use
587 * Success: Number of scan lines copied
590 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
591 UINT lines, LPCVOID bits, const BITMAPINFO *info,
595 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
596 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
597 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
598 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
601 struct gdi_image_bits src_bits;
602 struct bitblt_coords src, dst;
603 INT src_to_dst_offset;
605 const struct gdi_dc_funcs *funcs;
607 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
609 SetLastError( ERROR_INVALID_PARAMETER );
612 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
614 DWORD *masks = (DWORD *)src_info->bmiColors;
615 if (!masks[0] || !masks[1] || !masks[2])
617 SetLastError( ERROR_INVALID_PARAMETER );
622 src_bits.ptr = (void *)bits;
623 src_bits.is_copy = FALSE;
624 src_bits.free = NULL;
625 src_bits.param = NULL;
627 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, hdc )) return 0;
629 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
631 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
633 if (lines == 0) goto done;
634 else lines = src_info->bmiHeader.biHeight;
637 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
640 dst.visrect.left = 0;
642 dst.visrect.right = bitmap->bitmap.bmWidth;
643 dst.visrect.bottom = bitmap->bitmap.bmHeight;
645 src.visrect.left = 0;
647 src.visrect.right = src_info->bmiHeader.biWidth;
648 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
650 if (src_info->bmiHeader.biHeight > 0)
652 src_to_dst_offset = -startscan;
653 lines = min( lines, src.visrect.bottom - startscan );
654 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
658 src_to_dst_offset = src.visrect.bottom - lines - startscan;
659 /* Unlike the bottom-up case, Windows doesn't limit lines. */
660 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
663 funcs = get_bitmap_funcs( bitmap );
667 offset_rect( &src.visrect, 0, src_to_dst_offset );
668 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
669 src.visrect = dst.visrect;
670 offset_rect( &src.visrect, 0, -src_to_dst_offset );
672 src.x = src.visrect.left;
673 src.y = src.visrect.top;
674 src.width = src.visrect.right - src.visrect.left;
675 src.height = src.visrect.bottom - src.visrect.top;
677 dst.x = dst.visrect.left;
678 dst.y = dst.visrect.top;
679 dst.width = dst.visrect.right - dst.visrect.left;
680 dst.height = dst.visrect.bottom - dst.visrect.top;
682 copy_bitmapinfo( dst_info, src_info );
684 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
685 if (err == ERROR_BAD_FORMAT)
689 dst_info->bmiHeader.biWidth = dst.width;
690 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
693 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
694 if (src_bits.free) src_bits.free( &src_bits );
696 src_bits.is_copy = TRUE;
697 src_bits.free = free_heap_bits;
699 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
701 else err = ERROR_OUTOFMEMORY;
706 if (src_bits.free) src_bits.free( &src_bits );
707 if (clip) DeleteObject( clip );
708 GDI_ReleaseObj( hbitmap );
713 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
714 INT x_src, INT y_src, UINT startscan, UINT lines,
715 const void *bits, BITMAPINFO *src_info, UINT coloruse )
717 DC *dc = get_nulldrv_dc( dev );
718 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
719 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
720 struct bitblt_coords src, dst;
721 struct gdi_image_bits src_bits;
729 top_down = (src_info->bmiHeader.biHeight < 0);
730 height = abs( src_info->bmiHeader.biHeight );
732 src_bits.ptr = (void *)bits;
733 src_bits.is_copy = FALSE;
734 src_bits.free = NULL;
736 if (!lines) return 0;
737 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
739 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
743 src_info->bmiHeader.biWidth = x_src + cx;
744 src_info->bmiHeader.biHeight = y_src + cy;
745 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
750 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
754 if (startscan >= height) return 0;
755 if (!top_down && lines > height - startscan) lines = height - startscan;
757 /* map src to top-down coordinates with startscan as origin */
759 src.y = startscan + lines - (y_src + cy);
766 /* get rid of unnecessary lines */
767 if (src.y >= lines) return 0;
771 else if (src.y >= lines) return lines;
773 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
776 src.visrect.left = src.x;
777 src.visrect.top = src.y;
778 src.visrect.right = src.x + cx;
779 src.visrect.bottom = src.y + cy;
782 rect.right = src_info->bmiHeader.biWidth;
783 rect.bottom = abs( src_info->bmiHeader.biHeight );
784 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
792 LPtoDP( dev->hdc, &pt, 1 );
797 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
799 dst.visrect.left = dst.x;
800 dst.visrect.top = dst.y;
801 dst.visrect.right = dst.x + cx;
802 dst.visrect.bottom = dst.y + cy;
803 if (get_clip_box( dc, &rect )) intersect_rect( &dst.visrect, &dst.visrect, &rect );
805 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
806 intersect_rect( &rect, &src.visrect, &dst.visrect );
807 src.visrect = dst.visrect = rect;
808 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
809 if (is_rect_empty( &dst.visrect )) goto done;
810 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
812 dev = GET_DC_PHYSDEV( dc, pPutImage );
813 copy_bitmapinfo( dst_info, src_info );
814 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
815 if (err == ERROR_BAD_FORMAT)
819 dst_info->bmiHeader.biWidth = src.visrect.right - src.visrect.left;
820 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
823 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
824 if (src_bits.free) src_bits.free( &src_bits );
826 src_bits.is_copy = TRUE;
827 src_bits.free = free_heap_bits;
828 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
830 else err = ERROR_OUTOFMEMORY;
835 if (src_bits.free) src_bits.free( &src_bits );
836 if (clip) DeleteObject( clip );
840 /***********************************************************************
841 * SetDIBitsToDevice (GDI32.@)
843 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
844 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
845 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
848 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
849 BITMAPINFO *info = (BITMAPINFO *)buffer;
854 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
856 SetLastError( ERROR_INVALID_PARAMETER );
860 if ((dc = get_dc_ptr( hdc )))
862 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
864 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
865 ySrc, startscan, lines, bits, info, coloruse );
866 release_dc_ptr( dc );
871 /***********************************************************************
872 * SetDIBColorTable (GDI32.@)
874 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
880 if (!(dc = get_dc_ptr( hdc ))) return 0;
882 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
884 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
886 /* Check if currently selected bitmap is a DIB */
887 if (bitmap->color_table)
889 if (startpos < bitmap->nb_colors)
891 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
892 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
896 GDI_ReleaseObj( dc->hBitmap );
897 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
899 release_dc_ptr( dc );
904 /***********************************************************************
905 * GetDIBColorTable (GDI32.@)
907 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
913 if (!(dc = get_dc_ptr( hdc ))) return 0;
915 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
917 /* Check if currently selected bitmap is a DIB */
918 if (bitmap->color_table)
920 if (startpos < bitmap->nb_colors)
922 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
923 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
927 GDI_ReleaseObj( dc->hBitmap );
929 release_dc_ptr( dc );
933 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
934 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
935 { 0x00, 0x00, 0x00, 0x00 },
936 { 0x00, 0x00, 0x80, 0x00 },
937 { 0x00, 0x80, 0x00, 0x00 },
938 { 0x00, 0x80, 0x80, 0x00 },
939 { 0x80, 0x00, 0x00, 0x00 },
940 { 0x80, 0x00, 0x80, 0x00 },
941 { 0x80, 0x80, 0x00, 0x00 },
942 { 0xc0, 0xc0, 0xc0, 0x00 },
943 { 0xc0, 0xdc, 0xc0, 0x00 },
944 { 0xf0, 0xca, 0xa6, 0x00 },
945 { 0xf0, 0xfb, 0xff, 0x00 },
946 { 0xa4, 0xa0, 0xa0, 0x00 },
947 { 0x80, 0x80, 0x80, 0x00 },
948 { 0x00, 0x00, 0xff, 0x00 },
949 { 0x00, 0xff, 0x00, 0x00 },
950 { 0x00, 0xff, 0xff, 0x00 },
951 { 0xff, 0x00, 0x00, 0x00 },
952 { 0xff, 0x00, 0xff, 0x00 },
953 { 0xff, 0xff, 0x00, 0x00 },
954 { 0xff, 0xff, 0xff, 0x00 }
957 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
958 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
959 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
961 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
963 BITMAPINFOHEADER header;
965 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
966 header.biWidth = bmp->bitmap.bmWidth;
967 header.biHeight = bmp->bitmap.bmHeight;
972 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
973 switch (bmp->dib->dsBm.bmBitsPixel)
977 header.biCompression = BI_BITFIELDS;
980 header.biCompression = BI_RGB;
986 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
987 header.biBitCount = bmp->bitmap.bmBitsPixel;
990 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
991 header.biXPelsPerMeter = 0;
992 header.biYPelsPerMeter = 0;
993 header.biClrUsed = 0;
994 header.biClrImportant = 0;
996 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
998 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
1000 coreheader->bcWidth = header.biWidth;
1001 coreheader->bcHeight = header.biHeight;
1002 coreheader->bcPlanes = header.biPlanes;
1003 coreheader->bcBitCount = header.biBitCount;
1006 info->bmiHeader = header;
1008 return abs(bmp->bitmap.bmHeight);
1011 /************************************************************************
1014 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1016 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1018 unsigned int colors = get_dib_num_of_colors( src );
1019 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
1021 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
1023 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1025 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1026 if (coloruse == DIB_PAL_COLORS)
1027 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
1031 for (i = 0; i < colors; i++)
1033 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
1034 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
1035 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
1041 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1042 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1044 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1045 /* bitfields are always at bmiColors even in larger structures */
1046 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1049 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1052 if (coloruse == DIB_PAL_COLORS)
1053 size = colors * sizeof(WORD);
1055 size = colors * sizeof(RGBQUAD);
1056 memcpy( colorptr, src_colors, size );
1061 static void fill_default_color_table( BITMAPINFO *info )
1065 switch (info->bmiHeader.biBitCount)
1068 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
1069 info->bmiColors[0].rgbReserved = 0;
1070 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
1071 info->bmiColors[1].rgbReserved = 0;
1075 /* The EGA palette is the first and last 8 colours of the default palette
1076 with the innermost pair swapped */
1077 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
1078 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
1079 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
1080 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
1084 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
1085 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
1086 for (i = 10; i < 246; i++)
1088 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
1089 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
1090 info->bmiColors[i].rgbBlue = i & 0xc0;
1091 info->bmiColors[i].rgbReserved = 0;
1096 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
1098 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1101 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1103 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1104 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1105 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1106 info->bmiHeader.biPlanes = 1;
1107 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1108 info->bmiHeader.biCompression = BI_RGB;
1109 info->bmiHeader.biXPelsPerMeter = 0;
1110 info->bmiHeader.biYPelsPerMeter = 0;
1111 info->bmiHeader.biClrUsed = 0;
1112 info->bmiHeader.biClrImportant = 0;
1113 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1116 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1118 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1119 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1120 int info_size, image_size;
1122 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1124 info_size = bitmap_info_size( info, usage );
1125 image_size = get_dib_image_size( info );
1126 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + image_size )))
1128 memcpy( ret, info, info_size );
1129 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size(src_info,usage), image_size );
1134 /******************************************************************************
1135 * GetDIBits [GDI32.@]
1137 * Retrieves bits of bitmap and copies to buffer.
1140 * Success: Number of scan lines copied from bitmap
1143 INT WINAPI GetDIBits(
1144 HDC hdc, /* [in] Handle to device context */
1145 HBITMAP hbitmap, /* [in] Handle to bitmap */
1146 UINT startscan, /* [in] First scan line to set in dest bitmap */
1147 UINT lines, /* [in] Number of scan lines to copy */
1148 LPVOID bits, /* [out] Address of array for bitmap bits */
1149 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1150 UINT coloruse) /* [in] RGB or palette index */
1154 int i, dst_to_src_offset, ret = 0;
1156 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1157 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1158 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1159 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1160 const struct gdi_dc_funcs *funcs;
1161 struct gdi_image_bits src_bits;
1162 struct bitblt_coords src, dst;
1163 BOOL empty_rect = FALSE;
1165 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1166 own copy and transfer the colour info back at the end */
1167 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1169 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1171 dst_info->bmiHeader.biClrUsed = 0;
1172 dst_info->bmiHeader.biClrImportant = 0;
1174 if (!(dc = get_dc_ptr( hdc )))
1176 SetLastError( ERROR_INVALID_PARAMETER );
1180 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1182 release_dc_ptr( dc );
1186 funcs = get_bitmap_funcs( bmp );
1188 src.visrect.left = 0;
1189 src.visrect.top = 0;
1190 src.visrect.right = bmp->bitmap.bmWidth;
1191 src.visrect.bottom = bmp->bitmap.bmHeight;
1193 dst.visrect.left = 0;
1194 dst.visrect.top = 0;
1195 dst.visrect.right = dst_info->bmiHeader.biWidth;
1196 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1198 if (lines == 0 || startscan >= dst.visrect.bottom)
1201 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1203 ret = fill_query_info( info, bmp );
1207 /* validate parameters */
1209 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1210 if (dst_info->bmiHeader.biHeight == 0) goto done;
1212 switch (dst_info->bmiHeader.biCompression)
1215 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1216 if (dst_info->bmiHeader.biHeight < 0) goto done;
1217 if (bits) goto done; /* can't retrieve compressed bits */
1220 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1221 if (dst_info->bmiHeader.biHeight < 0) goto done;
1222 if (bits) goto done; /* can't retrieve compressed bits */
1225 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1228 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1229 if (dst_info->bmiHeader.biBitCount == 1) break;
1230 if (dst_info->bmiHeader.biBitCount == 4) break;
1231 if (dst_info->bmiHeader.biBitCount == 8) break;
1232 if (dst_info->bmiHeader.biBitCount == 16) break;
1233 if (dst_info->bmiHeader.biBitCount == 24) break;
1234 if (dst_info->bmiHeader.biBitCount == 32) break;
1242 if (dst_info->bmiHeader.biHeight > 0)
1244 dst_to_src_offset = -startscan;
1245 lines = min( lines, dst.visrect.bottom - startscan );
1246 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1250 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1251 if (dst_to_src_offset < 0)
1253 dst_to_src_offset = 0;
1254 lines = dst.visrect.bottom - startscan;
1256 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1259 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1260 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1261 dst.visrect = src.visrect;
1262 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1264 if (dst_info->bmiHeader.biHeight > 0)
1266 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1268 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1269 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1270 memset( bits, 0, pad_bytes );
1271 bits = (char *)bits + pad_bytes;
1276 if (dst.visrect.bottom < lines)
1278 int pad_lines = lines - dst.visrect.bottom;
1279 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1280 int pad_bytes = pad_lines * stride;
1281 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1285 if (empty_rect) bits = NULL;
1287 src.x = src.visrect.left;
1288 src.y = src.visrect.top;
1289 src.width = src.visrect.right - src.visrect.left;
1290 src.height = src.visrect.bottom - src.visrect.top;
1295 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1299 /* fill out the src colour table, if it needs one */
1300 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1301 fill_default_color_table( src_info );
1303 /* if the src and dst are the same depth, copy the colour info across */
1304 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1306 switch (src_info->bmiHeader.biBitCount)
1309 if (src_info->bmiHeader.biCompression == BI_RGB)
1311 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1312 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1316 if (src_info->bmiHeader.biCompression == BI_RGB)
1318 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1319 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1323 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1324 copy_color_info( dst_info, src_info, coloruse );
1326 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1328 if( coloruse == DIB_PAL_COLORS )
1330 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1334 fill_default_color_table( dst_info );
1340 if(dst_info->bmiHeader.biHeight > 0)
1341 dst_info->bmiHeader.biHeight = src.height;
1343 dst_info->bmiHeader.biHeight = -src.height;
1345 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1346 if (src_bits.free) src_bits.free( &src_bits );
1350 ret = empty_rect ? FALSE : TRUE;
1352 if (coloruse == DIB_PAL_COLORS)
1354 WORD *index = (WORD *)dst_info->bmiColors;
1355 int colors = get_dib_num_of_colors( dst_info );
1356 for (i = 0; i < colors; i++, index++)
1360 copy_color_info( info, dst_info, coloruse );
1363 release_dc_ptr( dc );
1364 GDI_ReleaseObj( hbitmap );
1369 /***********************************************************************
1370 * CreateDIBitmap (GDI32.@)
1372 * Creates a DDB (device dependent bitmap) from a DIB.
1373 * The DDB will have the same color depth as the reference DC.
1375 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1376 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1379 BITMAPINFOHEADER info;
1383 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1384 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1385 if (info.biWidth < 0) return 0;
1387 /* Top-down DIBs have a negative height */
1388 height = abs( info.biHeight );
1390 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1391 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1392 info.biBitCount, info.biCompression);
1395 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1397 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1401 if (init & CBM_INIT)
1403 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1405 DeleteObject( handle );
1414 /* Copy/synthesize RGB palette from BITMAPINFO */
1415 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1417 unsigned int colors, i;
1419 colors = get_dib_num_of_colors( info );
1420 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1421 bmp->nb_colors = colors;
1423 if (coloruse == DIB_RGB_COLORS)
1425 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1429 PALETTEENTRY entries[256];
1430 const WORD *index = (const WORD *)info->bmiColors;
1431 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1433 for (i = 0; i < colors; i++, index++)
1435 PALETTEENTRY *entry = &entries[*index % count];
1436 bmp->color_table[i].rgbRed = entry->peRed;
1437 bmp->color_table[i].rgbGreen = entry->peGreen;
1438 bmp->color_table[i].rgbBlue = entry->peBlue;
1439 bmp->color_table[i].rgbReserved = 0;
1444 /***********************************************************************
1445 * CreateDIBSection (GDI32.@)
1447 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1448 VOID **bits, HANDLE section, DWORD offset)
1450 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1451 BITMAPINFO *info = (BITMAPINFO *)buffer;
1454 BOOL bDesktopDC = FALSE;
1457 void *mapBits = NULL;
1459 if (bits) *bits = NULL;
1460 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1461 if (info->bmiHeader.biPlanes != 1)
1463 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1464 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1467 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1469 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1470 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1471 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1472 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1473 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1475 dib->dsBm.bmType = 0;
1476 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1477 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1478 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1479 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1480 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1481 dib->dsBm.bmBits = NULL;
1482 dib->dsBmih = info->bmiHeader;
1484 /* set number of entries in bmi.bmiColors table */
1485 if( info->bmiHeader.biBitCount <= 8 )
1486 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1488 /* set dsBitfields values */
1489 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1491 dib->dsBmih.biCompression = BI_BITFIELDS;
1492 dib->dsBitfields[0] = 0x7c00;
1493 dib->dsBitfields[1] = 0x03e0;
1494 dib->dsBitfields[2] = 0x001f;
1496 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1498 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1499 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1500 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1501 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1503 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1505 /* get storage location for DIB bits */
1509 SYSTEM_INFO SystemInfo;
1513 GetSystemInfo( &SystemInfo );
1514 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1515 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1516 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1517 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1522 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1523 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1525 dib->dshSection = section;
1526 dib->dsOffset = offset;
1528 if (!dib->dsBm.bmBits)
1530 HeapFree( GetProcessHeap(), 0, dib );
1534 /* If the reference hdc is null, take the desktop dc */
1537 hdc = CreateCompatibleDC(0);
1541 if (!(dc = get_dc_ptr( hdc ))) goto error;
1543 /* create Device Dependent Bitmap and add DIB pointer */
1544 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1545 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1547 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1549 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1551 bmp->funcs = physdev->funcs;
1552 /* create local copy of DIB palette */
1553 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1554 GDI_ReleaseObj( ret );
1556 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1558 DeleteObject( ret );
1563 release_dc_ptr( dc );
1564 if (bDesktopDC) DeleteDC( hdc );
1565 if (ret && bits) *bits = dib->dsBm.bmBits;
1569 if (bDesktopDC) DeleteDC( hdc );
1570 if (section) UnmapViewOfFile( mapBits );
1571 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1572 HeapFree( GetProcessHeap(), 0, dib );