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 if (info->bmiHeader.biClrUsed) colors = min( info->bmiHeader.biClrUsed, 256 );
94 else colors = info->bmiHeader.biBitCount > 8 ? 0 : 1 << info->bmiHeader.biBitCount;
95 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
96 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
97 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
101 /*******************************************************************************************
102 * Verify that the DIB parameters are valid.
104 static BOOL is_valid_dib_format( const BITMAPINFOHEADER *info, BOOL allow_compression )
106 if (info->biWidth <= 0) return FALSE;
107 if (info->biHeight == 0) return FALSE;
109 if (allow_compression && (info->biCompression == BI_RLE4 || info->biCompression == BI_RLE8))
111 if (info->biHeight < 0) return FALSE;
112 if (!info->biSizeImage) return FALSE;
113 return info->biBitCount == (info->biCompression == BI_RLE4 ? 4 : 8);
116 if (!info->biPlanes) return FALSE;
118 switch (info->biBitCount)
124 return (info->biCompression == BI_RGB);
127 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
133 /*******************************************************************************************
134 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
136 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
138 if (!info) return FALSE;
140 if (info->biSize == sizeof(BITMAPCOREHEADER))
142 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
143 dst->biWidth = core->bcWidth;
144 dst->biHeight = core->bcHeight;
145 dst->biPlanes = core->bcPlanes;
146 dst->biBitCount = core->bcBitCount;
147 dst->biCompression = BI_RGB;
148 dst->biXPelsPerMeter = 0;
149 dst->biYPelsPerMeter = 0;
151 dst->biClrImportant = 0;
153 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
159 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
163 dst->biSize = sizeof(*dst);
164 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
165 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
169 /*******************************************************************************************
170 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
172 * The resulting stanitized BITMAPINFO is guaranteed to have:
173 * - biSize set to sizeof(BITMAPINFOHEADER)
174 * - biSizeImage set to the actual image size even for non-compressed DIB
175 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
176 * - color table present only for <= 8 bpp, always starts at info->bmiColors
178 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
179 UINT coloruse, BOOL allow_compression )
183 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
184 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
186 src_colors = (char *)info + info->bmiHeader.biSize;
188 if (dst->bmiHeader.biCompression == BI_BITFIELDS)
190 /* bitfields are always at bmiColors even in larger structures */
191 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
192 dst->bmiHeader.biClrUsed = 0;
194 else if (dst->bmiHeader.biBitCount <= 8)
196 unsigned int colors = dst->bmiHeader.biClrUsed;
197 unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
199 if (!colors) colors = max_colors;
200 else colors = min( colors, max_colors );
202 if (coloruse == DIB_PAL_COLORS)
204 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
207 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
209 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
214 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
215 for (i = 0; i < colors; i++)
217 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
218 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
219 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
220 dst->bmiColors[i].rgbReserved = 0;
223 memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
224 dst->bmiHeader.biClrUsed = max_colors;
226 else dst->bmiHeader.biClrUsed = 0;
231 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
233 PALETTEENTRY palEntry[256];
234 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
235 int i, colors = 1 << info->bmiHeader.biBitCount;
237 info->bmiHeader.biClrUsed = colors;
239 if (!palette) return 0;
241 memset( palEntry, 0, sizeof(palEntry) );
242 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
245 for (i = 0; i < colors; i++)
247 info->bmiColors[i].rgbRed = palEntry[i].peRed;
248 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
249 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
250 info->bmiColors[i].rgbReserved = 0;
256 BOOL fill_color_table_from_pal_colors( BITMAPINFO *info, HDC hdc )
258 PALETTEENTRY entries[256];
261 const WORD *index = (const WORD *)info->bmiColors;
262 int i, count, colors = info->bmiHeader.biClrUsed;
264 if (!colors) return TRUE;
265 if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return FALSE;
266 if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return FALSE;
268 for (i = 0; i < colors; i++, index++)
270 table[i].rgbRed = entries[*index % count].peRed;
271 table[i].rgbGreen = entries[*index % count].peGreen;
272 table[i].rgbBlue = entries[*index % count].peBlue;
273 table[i].rgbReserved = 0;
275 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
276 memcpy( info->bmiColors, table, colors * sizeof(RGBQUAD) );
277 memset( info->bmiColors + colors, 0, (info->bmiHeader.biClrUsed - colors) * sizeof(RGBQUAD) );
281 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
283 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
284 const int bpp = info->bmiHeader.biBitCount;
287 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
289 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
292 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
296 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
298 BYTE skip, num, data;
299 BYTE *out_bits, *in_bits = bits->ptr;
301 if (clip) *clip = NULL;
303 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
305 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
306 if (!out_bits) goto fail;
310 *clip = CreateRectRgn( 0, 0, 0, 0 );
311 run = CreateRectRgn( 0, 0, 0, 0 );
312 if (!*clip || !run) goto fail;
315 x = left = right = 0;
318 while (i < info->bmiHeader.biSizeImage - 1)
321 data = in_bits[i + 1];
326 if (x + num > width) num = width - x;
329 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
330 if (info->bmiHeader.biBitCount == 8)
331 memset( out_ptr, s, num );
336 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
337 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
342 /* this will write one too many if num is odd, but that doesn't matter */
343 if (num) memset( out_ptr, s, (num + 1) / 2 );
353 if(left != right && clip)
355 SetRectRgn( run, left, y, right, y + 1 );
356 CombineRgn( *clip, run, *clip, RGN_OR );
361 left = right = x = 0;
370 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
372 if (x > width) x = width;
379 else /* data bytes of data */
382 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
383 if (skip > info->bmiHeader.biSizeImage - i) goto done;
384 skip = (skip + 1) & ~1;
385 if (x + num > width) num = width - x;
388 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
389 if (info->bmiHeader.biBitCount == 8)
390 memcpy( out_ptr, in_bits + i, num );
395 const BYTE *in_ptr = in_bits + i;
396 for ( ; num; num--, x++)
400 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
404 *out_ptr = (*in_ptr++ << 4) & 0xf0;
408 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
419 if (run) DeleteObject( run );
420 if (bits->free) bits->free( bits );
422 bits->ptr = out_bits;
423 bits->is_copy = TRUE;
424 bits->free = free_heap_bits;
429 if (run) DeleteObject( run );
430 if (clip && *clip) DeleteObject( *clip );
431 HeapFree( GetProcessHeap(), 0, out_bits );
437 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
438 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
439 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
441 DC *dc = get_nulldrv_dc( dev );
442 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
443 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
444 struct bitblt_coords src, dst;
445 struct gdi_image_bits src_bits;
449 INT height = abs( src_info->bmiHeader.biHeight );
450 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
453 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
454 xSrc, ySrc, widthSrc, heightSrc, rop);
456 src_bits.ptr = (void*)bits;
457 src_bits.is_copy = FALSE;
458 src_bits.free = NULL;
460 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
464 rect.right = xDst + widthDst;
465 rect.bottom = yDst + heightDst;
466 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
469 dst.width = rect.right - rect.left;
470 dst.height = rect.bottom - rect.top;
472 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
475 dst.width = -dst.width;
477 rop &= ~NOMIRRORBITMAP;
480 src.width = widthSrc;
482 src.height = heightSrc;
484 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
485 non_stretch_from_origin = TRUE;
487 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
489 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
490 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
493 if (rop != SRCCOPY || non_stretch_from_origin)
495 if (dst.width == 1 && src.width > 1) src.width--;
496 if (dst.height == 1 && src.height > 1) src.height--;
501 if (dst.width < 0 && dst.width == src.width)
503 /* This is off-by-one, but that's what Windows does */
506 dst.width = -dst.width;
507 src.width = -src.width;
509 if (dst.height < 0 && dst.height == src.height)
513 dst.height = -dst.height;
514 src.height = -src.height;
518 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
520 if (src.y >= height && src.y + src.height + 1 < height)
522 else if (src.y > 0 && src.y + src.height + 1 < 0)
523 src.y = -src.height - 1;
525 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
527 src.visrect.left = 0;
528 src.visrect.right = src_info->bmiHeader.biWidth;
530 src.visrect.bottom = height;
531 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
533 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
535 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
537 if (!intersect_vis_rectangles( &dst, &src )) goto done;
539 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
541 dev = GET_DC_PHYSDEV( dc, pPutImage );
542 copy_bitmapinfo( dst_info, src_info );
543 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
544 if (err == ERROR_BAD_FORMAT)
546 /* 1-bpp destination without a color table requires a fake 1-entry table
547 * that contains only the background color */
548 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
550 COLORREF color = GetBkColor( dev->hdc );
551 dst_info->bmiColors[0].rgbRed = GetRValue( color );
552 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
553 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
554 dst_info->bmiColors[0].rgbReserved = 0;
555 dst_info->bmiHeader.biClrUsed = 1;
558 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
560 /* get rid of the fake 1-bpp table */
561 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
562 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
566 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
568 copy_bitmapinfo( src_info, dst_info );
569 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
570 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
573 else if (rop == SRCCOPY) ret = height;
574 else ret = src_info->bmiHeader.biHeight;
577 if (src_bits.free) src_bits.free( &src_bits );
578 if (clip) DeleteObject( clip );
582 /***********************************************************************
583 * StretchDIBits (GDI32.@)
585 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
586 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
587 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
589 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
590 BITMAPINFO *info = (BITMAPINFO *)buffer;
595 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
597 SetLastError( ERROR_INVALID_PARAMETER );
601 if ((dc = get_dc_ptr( hdc )))
603 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
605 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
606 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
607 release_dc_ptr( dc );
613 /******************************************************************************
614 * SetDIBits [GDI32.@]
616 * Sets pixels in a bitmap using colors from DIB.
619 * hdc [I] Handle to device context
620 * hbitmap [I] Handle to bitmap
621 * startscan [I] Starting scan line
622 * lines [I] Number of scan lines
623 * bits [I] Array of bitmap bits
624 * info [I] Address of structure with data
625 * coloruse [I] Type of color indexes to use
628 * Success: Number of scan lines copied
631 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
632 UINT lines, LPCVOID bits, const BITMAPINFO *info,
636 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
637 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
638 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
639 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
642 struct gdi_image_bits src_bits;
643 struct bitblt_coords src, dst;
644 INT src_to_dst_offset;
646 const struct gdi_dc_funcs *funcs;
648 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
650 SetLastError( ERROR_INVALID_PARAMETER );
653 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
655 DWORD *masks = (DWORD *)src_info->bmiColors;
656 if (!masks[0] || !masks[1] || !masks[2])
658 SetLastError( ERROR_INVALID_PARAMETER );
663 src_bits.ptr = (void *)bits;
664 src_bits.is_copy = FALSE;
665 src_bits.free = NULL;
666 src_bits.param = NULL;
668 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
670 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
672 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
674 if (lines == 0) goto done;
675 else lines = src_info->bmiHeader.biHeight;
678 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
681 dst.visrect.left = 0;
683 dst.visrect.right = bitmap->bitmap.bmWidth;
684 dst.visrect.bottom = bitmap->bitmap.bmHeight;
686 src.visrect.left = 0;
688 src.visrect.right = src_info->bmiHeader.biWidth;
689 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
691 if (src_info->bmiHeader.biHeight > 0)
693 src_to_dst_offset = -startscan;
694 lines = min( lines, src.visrect.bottom - startscan );
695 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
699 src_to_dst_offset = src.visrect.bottom - lines - startscan;
700 /* Unlike the bottom-up case, Windows doesn't limit lines. */
701 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
704 funcs = get_bitmap_funcs( bitmap );
708 offset_rect( &src.visrect, 0, src_to_dst_offset );
709 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
710 src.visrect = dst.visrect;
711 offset_rect( &src.visrect, 0, -src_to_dst_offset );
713 src.x = src.visrect.left;
714 src.y = src.visrect.top;
715 src.width = src.visrect.right - src.visrect.left;
716 src.height = src.visrect.bottom - src.visrect.top;
718 dst.x = dst.visrect.left;
719 dst.y = dst.visrect.top;
720 dst.width = dst.visrect.right - dst.visrect.left;
721 dst.height = dst.visrect.bottom - dst.visrect.top;
723 copy_bitmapinfo( dst_info, src_info );
725 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
726 if (err == ERROR_BAD_FORMAT)
728 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
729 if (!err) err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
734 if (src_bits.free) src_bits.free( &src_bits );
735 if (clip) DeleteObject( clip );
736 GDI_ReleaseObj( hbitmap );
741 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
742 INT x_src, INT y_src, UINT startscan, UINT lines,
743 const void *bits, BITMAPINFO *src_info, UINT coloruse )
745 DC *dc = get_nulldrv_dc( dev );
746 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
747 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
748 struct bitblt_coords src, dst;
749 struct gdi_image_bits src_bits;
757 top_down = (src_info->bmiHeader.biHeight < 0);
758 height = abs( src_info->bmiHeader.biHeight );
760 src_bits.ptr = (void *)bits;
761 src_bits.is_copy = FALSE;
762 src_bits.free = NULL;
764 if (!lines) return 0;
765 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
767 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
771 src_info->bmiHeader.biWidth = x_src + cx;
772 src_info->bmiHeader.biHeight = y_src + cy;
773 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
778 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
782 if (startscan >= height) return 0;
783 if (!top_down && lines > height - startscan) lines = height - startscan;
785 /* map src to top-down coordinates with startscan as origin */
787 src.y = startscan + lines - (y_src + cy);
794 /* get rid of unnecessary lines */
795 if (src.y >= lines) return 0;
799 else if (src.y >= lines) return lines;
801 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
804 src.visrect.left = src.x;
805 src.visrect.top = src.y;
806 src.visrect.right = src.x + cx;
807 src.visrect.bottom = src.y + cy;
810 rect.right = src_info->bmiHeader.biWidth;
811 rect.bottom = abs( src_info->bmiHeader.biHeight );
812 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
820 LPtoDP( dev->hdc, &pt, 1 );
825 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
829 rect.right = dst.x + cx;
830 rect.bottom = dst.y + cy;
831 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
833 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
834 intersect_rect( &rect, &src.visrect, &dst.visrect );
835 src.visrect = dst.visrect = rect;
836 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
837 if (is_rect_empty( &dst.visrect )) goto done;
838 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
840 dev = GET_DC_PHYSDEV( dc, pPutImage );
841 copy_bitmapinfo( dst_info, src_info );
842 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
843 if (err == ERROR_BAD_FORMAT)
845 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
846 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
851 if (src_bits.free) src_bits.free( &src_bits );
852 if (clip) DeleteObject( clip );
856 /***********************************************************************
857 * SetDIBitsToDevice (GDI32.@)
859 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
860 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
861 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
864 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
865 BITMAPINFO *info = (BITMAPINFO *)buffer;
870 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
872 SetLastError( ERROR_INVALID_PARAMETER );
876 if ((dc = get_dc_ptr( hdc )))
878 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
880 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
881 ySrc, startscan, lines, bits, info, coloruse );
882 release_dc_ptr( dc );
887 /***********************************************************************
888 * SetDIBColorTable (GDI32.@)
890 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
896 if (!(dc = get_dc_ptr( hdc ))) return 0;
898 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
900 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
902 /* Check if currently selected bitmap is a DIB */
903 if (bitmap->color_table)
905 if (startpos < bitmap->dib->dsBmih.biClrUsed)
907 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
908 memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
911 GDI_ReleaseObj( dc->hBitmap );
912 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
914 release_dc_ptr( dc );
919 /***********************************************************************
920 * GetDIBColorTable (GDI32.@)
922 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
928 if (!(dc = get_dc_ptr( hdc ))) return 0;
930 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
932 /* Check if currently selected bitmap is a DIB */
933 if (bitmap->color_table)
935 if (startpos < bitmap->dib->dsBmih.biClrUsed)
937 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
938 memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
941 GDI_ReleaseObj( dc->hBitmap );
943 release_dc_ptr( dc );
947 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
948 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
949 { 0x00, 0x00, 0x00, 0x00 },
950 { 0x00, 0x00, 0x80, 0x00 },
951 { 0x00, 0x80, 0x00, 0x00 },
952 { 0x00, 0x80, 0x80, 0x00 },
953 { 0x80, 0x00, 0x00, 0x00 },
954 { 0x80, 0x00, 0x80, 0x00 },
955 { 0x80, 0x80, 0x00, 0x00 },
956 { 0xc0, 0xc0, 0xc0, 0x00 },
957 { 0xc0, 0xdc, 0xc0, 0x00 },
958 { 0xf0, 0xca, 0xa6, 0x00 },
959 { 0xf0, 0xfb, 0xff, 0x00 },
960 { 0xa4, 0xa0, 0xa0, 0x00 },
961 { 0x80, 0x80, 0x80, 0x00 },
962 { 0x00, 0x00, 0xff, 0x00 },
963 { 0x00, 0xff, 0x00, 0x00 },
964 { 0x00, 0xff, 0xff, 0x00 },
965 { 0xff, 0x00, 0x00, 0x00 },
966 { 0xff, 0x00, 0xff, 0x00 },
967 { 0xff, 0xff, 0x00, 0x00 },
968 { 0xff, 0xff, 0xff, 0x00 }
971 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
972 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
973 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
975 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
977 BITMAPINFOHEADER header;
979 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
980 header.biWidth = bmp->bitmap.bmWidth;
981 header.biHeight = bmp->bitmap.bmHeight;
986 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
987 switch (bmp->dib->dsBm.bmBitsPixel)
991 header.biCompression = BI_BITFIELDS;
994 header.biCompression = BI_RGB;
1000 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
1001 header.biBitCount = bmp->bitmap.bmBitsPixel;
1004 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
1005 header.biXPelsPerMeter = 0;
1006 header.biYPelsPerMeter = 0;
1007 header.biClrUsed = 0;
1008 header.biClrImportant = 0;
1010 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
1012 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
1014 coreheader->bcWidth = header.biWidth;
1015 coreheader->bcHeight = header.biHeight;
1016 coreheader->bcPlanes = header.biPlanes;
1017 coreheader->bcBitCount = header.biBitCount;
1020 info->bmiHeader = header;
1022 return abs(bmp->bitmap.bmHeight);
1025 /************************************************************************
1028 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1030 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1032 assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1034 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1036 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1037 if (coloruse == DIB_PAL_COLORS)
1038 memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1042 for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1044 core->bmciColors[i].rgbtRed = src->bmiColors[i].rgbRed;
1045 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1046 core->bmciColors[i].rgbtBlue = src->bmiColors[i].rgbBlue;
1052 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1053 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1055 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1056 /* bitfields are always at bmiColors even in larger structures */
1057 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1058 else if (src->bmiHeader.biClrUsed)
1060 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1063 if (coloruse == DIB_PAL_COLORS)
1064 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1066 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1067 memcpy( colorptr, src->bmiColors, size );
1072 void fill_default_color_table( BITMAPINFO *info )
1076 switch (info->bmiHeader.biBitCount)
1079 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
1080 info->bmiColors[0].rgbReserved = 0;
1081 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
1082 info->bmiColors[1].rgbReserved = 0;
1086 /* The EGA palette is the first and last 8 colours of the default palette
1087 with the innermost pair swapped */
1088 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
1089 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
1090 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
1091 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
1095 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
1096 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
1097 for (i = 10; i < 246; i++)
1099 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
1100 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
1101 info->bmiColors[i].rgbBlue = i & 0xc0;
1102 info->bmiColors[i].rgbReserved = 0;
1107 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
1109 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1112 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1114 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1115 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1116 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1117 info->bmiHeader.biPlanes = 1;
1118 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1119 info->bmiHeader.biCompression = BI_RGB;
1120 info->bmiHeader.biXPelsPerMeter = 0;
1121 info->bmiHeader.biYPelsPerMeter = 0;
1122 info->bmiHeader.biClrUsed = 0;
1123 info->bmiHeader.biClrImportant = 0;
1124 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1127 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1129 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1130 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1131 unsigned int info_size;
1133 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1135 info_size = get_dib_info_size( info, usage );
1136 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + info->bmiHeader.biSizeImage )))
1138 memcpy( ret, info, info_size );
1139 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size( src_info, usage ),
1140 info->bmiHeader.biSizeImage );
1145 /******************************************************************************
1146 * GetDIBits [GDI32.@]
1148 * Retrieves bits of bitmap and copies to buffer.
1151 * Success: Number of scan lines copied from bitmap
1154 INT WINAPI GetDIBits(
1155 HDC hdc, /* [in] Handle to device context */
1156 HBITMAP hbitmap, /* [in] Handle to bitmap */
1157 UINT startscan, /* [in] First scan line to set in dest bitmap */
1158 UINT lines, /* [in] Number of scan lines to copy */
1159 LPVOID bits, /* [out] Address of array for bitmap bits */
1160 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1161 UINT coloruse) /* [in] RGB or palette index */
1165 int i, dst_to_src_offset, ret = 0;
1167 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1168 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1169 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1170 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1171 const struct gdi_dc_funcs *funcs;
1172 struct gdi_image_bits src_bits;
1173 struct bitblt_coords src, dst;
1174 BOOL empty_rect = FALSE;
1176 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1177 own copy and transfer the colour info back at the end */
1178 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1180 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1182 dst_info->bmiHeader.biClrUsed = 0;
1183 dst_info->bmiHeader.biClrImportant = 0;
1185 if (!(dc = get_dc_ptr( hdc )))
1187 SetLastError( ERROR_INVALID_PARAMETER );
1191 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1193 release_dc_ptr( dc );
1197 funcs = get_bitmap_funcs( bmp );
1199 src.visrect.left = 0;
1200 src.visrect.top = 0;
1201 src.visrect.right = bmp->bitmap.bmWidth;
1202 src.visrect.bottom = bmp->bitmap.bmHeight;
1204 dst.visrect.left = 0;
1205 dst.visrect.top = 0;
1206 dst.visrect.right = dst_info->bmiHeader.biWidth;
1207 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1209 if (lines == 0 || startscan >= dst.visrect.bottom)
1212 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1214 ret = fill_query_info( info, bmp );
1218 /* validate parameters */
1220 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1221 if (dst_info->bmiHeader.biHeight == 0) goto done;
1223 switch (dst_info->bmiHeader.biCompression)
1226 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1227 if (dst_info->bmiHeader.biHeight < 0) goto done;
1228 if (bits) goto done; /* can't retrieve compressed bits */
1231 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1232 if (dst_info->bmiHeader.biHeight < 0) goto done;
1233 if (bits) goto done; /* can't retrieve compressed bits */
1236 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1239 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1240 if (dst_info->bmiHeader.biBitCount == 1) break;
1241 if (dst_info->bmiHeader.biBitCount == 4) break;
1242 if (dst_info->bmiHeader.biBitCount == 8) break;
1243 if (dst_info->bmiHeader.biBitCount == 16) break;
1244 if (dst_info->bmiHeader.biBitCount == 24) break;
1245 if (dst_info->bmiHeader.biBitCount == 32) break;
1253 if (dst_info->bmiHeader.biHeight > 0)
1255 dst_to_src_offset = -startscan;
1256 lines = min( lines, dst.visrect.bottom - startscan );
1257 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1261 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1262 if (dst_to_src_offset < 0)
1264 dst_to_src_offset = 0;
1265 lines = dst.visrect.bottom - startscan;
1267 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1270 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1271 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1272 dst.visrect = src.visrect;
1273 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1275 if (dst_info->bmiHeader.biHeight > 0)
1277 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1279 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1280 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1281 memset( bits, 0, pad_bytes );
1282 bits = (char *)bits + pad_bytes;
1287 if (dst.visrect.bottom < lines)
1289 int pad_lines = lines - dst.visrect.bottom;
1290 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1291 int pad_bytes = pad_lines * stride;
1292 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1296 if (empty_rect) bits = NULL;
1298 src.x = src.visrect.left;
1299 src.y = src.visrect.top;
1300 src.width = src.visrect.right - src.visrect.left;
1301 src.height = src.visrect.bottom - src.visrect.top;
1306 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1310 /* fill out the src colour table, if it needs one */
1311 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1312 fill_default_color_table( src_info );
1314 /* if the src and dst are the same depth, copy the colour info across */
1315 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1317 switch (src_info->bmiHeader.biBitCount)
1320 if (src_info->bmiHeader.biCompression == BI_RGB)
1322 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1323 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1327 if (src_info->bmiHeader.biCompression == BI_RGB)
1329 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1330 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1334 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1335 copy_color_info( dst_info, src_info, coloruse );
1337 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1339 if( coloruse == DIB_PAL_COLORS )
1341 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1345 fill_default_color_table( dst_info );
1351 if(dst_info->bmiHeader.biHeight > 0)
1352 dst_info->bmiHeader.biHeight = src.height;
1354 dst_info->bmiHeader.biHeight = -src.height;
1356 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1357 if (src_bits.free) src_bits.free( &src_bits );
1361 ret = empty_rect ? FALSE : TRUE;
1363 if (coloruse == DIB_PAL_COLORS)
1365 WORD *index = (WORD *)dst_info->bmiColors;
1366 for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1370 copy_color_info( info, dst_info, coloruse );
1371 if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1374 release_dc_ptr( dc );
1375 GDI_ReleaseObj( hbitmap );
1380 /***********************************************************************
1381 * CreateDIBitmap (GDI32.@)
1383 * Creates a DDB (device dependent bitmap) from a DIB.
1384 * The DDB will have the same color depth as the reference DC.
1386 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1387 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1390 BITMAPINFOHEADER info;
1394 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1395 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1396 if (info.biWidth < 0) return 0;
1398 /* Top-down DIBs have a negative height */
1399 height = abs( info.biHeight );
1401 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1402 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1403 info.biBitCount, info.biCompression);
1406 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1408 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1412 if (init & CBM_INIT)
1414 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1416 DeleteObject( handle );
1426 /***********************************************************************
1427 * CreateDIBSection (GDI32.@)
1429 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1430 VOID **bits, HANDLE section, DWORD offset)
1432 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1433 BITMAPINFO *info = (BITMAPINFO *)buffer;
1436 BOOL bDesktopDC = FALSE;
1439 RGBQUAD *color_table = NULL;
1440 void *mapBits = NULL;
1442 if (bits) *bits = NULL;
1443 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1444 if (info->bmiHeader.biPlanes != 1)
1446 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1447 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1450 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1452 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1453 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1454 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1455 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1456 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1458 dib->dsBm.bmType = 0;
1459 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1460 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1461 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1462 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1463 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1464 dib->dsBm.bmBits = NULL;
1465 dib->dsBmih = info->bmiHeader;
1467 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1469 if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1471 dib->dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1472 if (!(color_table = HeapAlloc( GetProcessHeap(), 0, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) )))
1474 memcpy( color_table, info->bmiColors, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) );
1477 /* set dsBitfields values */
1478 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1480 dib->dsBmih.biCompression = BI_BITFIELDS;
1481 dib->dsBitfields[0] = 0x7c00;
1482 dib->dsBitfields[1] = 0x03e0;
1483 dib->dsBitfields[2] = 0x001f;
1485 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1487 if (usage == DIB_PAL_COLORS) goto error;
1488 dib->dsBitfields[0] = *(const DWORD *)info->bmiColors;
1489 dib->dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1490 dib->dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1491 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1493 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1495 /* get storage location for DIB bits */
1499 SYSTEM_INFO SystemInfo;
1503 GetSystemInfo( &SystemInfo );
1504 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1505 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1506 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1507 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1512 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1513 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1515 dib->dshSection = section;
1516 dib->dsOffset = offset;
1518 if (!dib->dsBm.bmBits) goto error;
1520 /* If the reference hdc is null, take the desktop dc */
1523 hdc = CreateCompatibleDC(0);
1527 if (!(dc = get_dc_ptr( hdc ))) goto error;
1529 /* create Device Dependent Bitmap and add DIB pointer */
1530 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1531 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1533 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1535 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1537 bmp->funcs = physdev->funcs;
1538 bmp->color_table = color_table;
1539 GDI_ReleaseObj( ret );
1541 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1543 DeleteObject( ret );
1548 release_dc_ptr( dc );
1549 if (bDesktopDC) DeleteDC( hdc );
1550 if (ret && bits) *bits = dib->dsBm.bmBits;
1554 if (bDesktopDC) DeleteDC( hdc );
1555 if (section) UnmapViewOfFile( mapBits );
1556 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1557 HeapFree( GetProcessHeap(), 0, color_table );
1558 HeapFree( GetProcessHeap(), 0, dib );