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 DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
948 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
949 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
951 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
953 BITMAPINFOHEADER header;
955 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
956 header.biWidth = bmp->bitmap.bmWidth;
957 header.biHeight = bmp->bitmap.bmHeight;
962 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
963 switch (bmp->dib->dsBm.bmBitsPixel)
967 header.biCompression = BI_BITFIELDS;
970 header.biCompression = BI_RGB;
976 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
977 header.biBitCount = bmp->bitmap.bmBitsPixel;
980 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
981 header.biXPelsPerMeter = 0;
982 header.biYPelsPerMeter = 0;
983 header.biClrUsed = 0;
984 header.biClrImportant = 0;
986 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
988 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
990 coreheader->bcWidth = header.biWidth;
991 coreheader->bcHeight = header.biHeight;
992 coreheader->bcPlanes = header.biPlanes;
993 coreheader->bcBitCount = header.biBitCount;
996 info->bmiHeader = header;
998 return abs(bmp->bitmap.bmHeight);
1001 /************************************************************************
1004 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1006 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1008 assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1010 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1012 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1013 if (coloruse == DIB_PAL_COLORS)
1014 memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1018 for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1020 core->bmciColors[i].rgbtRed = src->bmiColors[i].rgbRed;
1021 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1022 core->bmciColors[i].rgbtBlue = src->bmiColors[i].rgbBlue;
1028 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1029 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1031 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1032 /* bitfields are always at bmiColors even in larger structures */
1033 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1034 else if (src->bmiHeader.biClrUsed)
1036 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1039 if (coloruse == DIB_PAL_COLORS)
1040 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1042 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1043 memcpy( colorptr, src->bmiColors, size );
1048 const RGBQUAD *get_default_color_table( int bpp )
1050 static const RGBQUAD table_1[2] =
1052 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1054 static const RGBQUAD table_4[16] =
1056 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1057 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1058 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1059 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1061 static const RGBQUAD table_8[256] =
1063 /* first and last 10 entries are the default system palette entries */
1064 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1065 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1066 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1067 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1068 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1069 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1070 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1071 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1072 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1073 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1074 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1075 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1076 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1077 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1078 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1079 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1080 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1081 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1082 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1083 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1084 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1085 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1086 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1087 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1088 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1089 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1090 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1091 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1092 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1093 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1094 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1095 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1096 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1097 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1098 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1099 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1100 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1101 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1102 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1103 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1104 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1105 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1106 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1107 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1108 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1109 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1110 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1111 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1112 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1113 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1114 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1115 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1116 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1117 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1118 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1119 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1120 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1121 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1122 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1123 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1124 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1125 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1126 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1127 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1132 case 1: return table_1;
1133 case 4: return table_4;
1134 case 8: return table_8;
1135 default: return NULL;
1139 void fill_default_color_table( BITMAPINFO *info )
1141 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1142 memcpy( info->bmiColors, get_default_color_table( info->bmiHeader.biBitCount ),
1143 info->bmiHeader.biClrUsed * sizeof(RGBQUAD) );
1146 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1148 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1149 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1150 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1151 info->bmiHeader.biPlanes = 1;
1152 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1153 info->bmiHeader.biCompression = BI_RGB;
1154 info->bmiHeader.biXPelsPerMeter = 0;
1155 info->bmiHeader.biYPelsPerMeter = 0;
1156 info->bmiHeader.biClrUsed = 0;
1157 info->bmiHeader.biClrImportant = 0;
1160 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1162 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1163 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1164 unsigned int info_size;
1166 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1168 info_size = get_dib_info_size( info, usage );
1169 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + info->bmiHeader.biSizeImage )))
1171 memcpy( ret, info, info_size );
1172 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size( src_info, usage ),
1173 info->bmiHeader.biSizeImage );
1178 /******************************************************************************
1179 * GetDIBits [GDI32.@]
1181 * Retrieves bits of bitmap and copies to buffer.
1184 * Success: Number of scan lines copied from bitmap
1187 INT WINAPI GetDIBits(
1188 HDC hdc, /* [in] Handle to device context */
1189 HBITMAP hbitmap, /* [in] Handle to bitmap */
1190 UINT startscan, /* [in] First scan line to set in dest bitmap */
1191 UINT lines, /* [in] Number of scan lines to copy */
1192 LPVOID bits, /* [out] Address of array for bitmap bits */
1193 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1194 UINT coloruse) /* [in] RGB or palette index */
1198 int i, dst_to_src_offset, ret = 0;
1200 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1201 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1202 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1203 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1204 const struct gdi_dc_funcs *funcs;
1205 struct gdi_image_bits src_bits;
1206 struct bitblt_coords src, dst;
1207 BOOL empty_rect = FALSE;
1209 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1210 own copy and transfer the colour info back at the end */
1211 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1213 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1215 dst_info->bmiHeader.biClrUsed = 0;
1216 dst_info->bmiHeader.biClrImportant = 0;
1218 if (!(dc = get_dc_ptr( hdc )))
1220 SetLastError( ERROR_INVALID_PARAMETER );
1224 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1226 release_dc_ptr( dc );
1230 funcs = get_bitmap_funcs( bmp );
1232 src.visrect.left = 0;
1233 src.visrect.top = 0;
1234 src.visrect.right = bmp->bitmap.bmWidth;
1235 src.visrect.bottom = bmp->bitmap.bmHeight;
1237 dst.visrect.left = 0;
1238 dst.visrect.top = 0;
1239 dst.visrect.right = dst_info->bmiHeader.biWidth;
1240 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1242 if (lines == 0 || startscan >= dst.visrect.bottom)
1245 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1247 ret = fill_query_info( info, bmp );
1251 /* validate parameters */
1253 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1254 if (dst_info->bmiHeader.biHeight == 0) goto done;
1256 switch (dst_info->bmiHeader.biCompression)
1259 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1260 if (dst_info->bmiHeader.biHeight < 0) goto done;
1261 if (bits) goto done; /* can't retrieve compressed bits */
1264 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1265 if (dst_info->bmiHeader.biHeight < 0) goto done;
1266 if (bits) goto done; /* can't retrieve compressed bits */
1269 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1272 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1273 if (dst_info->bmiHeader.biBitCount == 1) break;
1274 if (dst_info->bmiHeader.biBitCount == 4) break;
1275 if (dst_info->bmiHeader.biBitCount == 8) break;
1276 if (dst_info->bmiHeader.biBitCount == 16) break;
1277 if (dst_info->bmiHeader.biBitCount == 24) break;
1278 if (dst_info->bmiHeader.biBitCount == 32) break;
1286 if (dst_info->bmiHeader.biHeight > 0)
1288 dst_to_src_offset = -startscan;
1289 lines = min( lines, dst.visrect.bottom - startscan );
1290 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1294 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1295 if (dst_to_src_offset < 0)
1297 dst_to_src_offset = 0;
1298 lines = dst.visrect.bottom - startscan;
1300 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1303 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1304 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1305 dst.visrect = src.visrect;
1306 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1308 if (dst_info->bmiHeader.biHeight > 0)
1310 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1312 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1313 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1314 memset( bits, 0, pad_bytes );
1315 bits = (char *)bits + pad_bytes;
1320 if (dst.visrect.bottom < lines)
1322 int pad_lines = lines - dst.visrect.bottom;
1323 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1324 int pad_bytes = pad_lines * stride;
1325 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1329 if (empty_rect) bits = NULL;
1331 src.x = src.visrect.left;
1332 src.y = src.visrect.top;
1333 src.width = src.visrect.right - src.visrect.left;
1334 src.height = src.visrect.bottom - src.visrect.top;
1339 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1343 /* fill out the src colour table, if it needs one */
1344 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1345 fill_default_color_table( src_info );
1347 /* if the src and dst are the same depth, copy the colour info across */
1348 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1350 switch (src_info->bmiHeader.biBitCount)
1353 if (src_info->bmiHeader.biCompression == BI_RGB)
1355 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1356 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1360 if (src_info->bmiHeader.biCompression == BI_RGB)
1362 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1363 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1367 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1368 copy_color_info( dst_info, src_info, coloruse );
1370 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1372 if( coloruse == DIB_PAL_COLORS )
1374 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1378 fill_default_color_table( dst_info );
1384 if(dst_info->bmiHeader.biHeight > 0)
1385 dst_info->bmiHeader.biHeight = src.height;
1387 dst_info->bmiHeader.biHeight = -src.height;
1389 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1390 if (src_bits.free) src_bits.free( &src_bits );
1394 ret = empty_rect ? FALSE : TRUE;
1396 if (coloruse == DIB_PAL_COLORS)
1398 WORD *index = (WORD *)dst_info->bmiColors;
1399 for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1403 copy_color_info( info, dst_info, coloruse );
1404 if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1407 release_dc_ptr( dc );
1408 GDI_ReleaseObj( hbitmap );
1413 /***********************************************************************
1414 * CreateDIBitmap (GDI32.@)
1416 * Creates a DDB (device dependent bitmap) from a DIB.
1417 * The DDB will have the same color depth as the reference DC.
1419 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1420 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1423 BITMAPINFOHEADER info;
1427 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1428 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1429 if (info.biWidth < 0) return 0;
1431 /* Top-down DIBs have a negative height */
1432 height = abs( info.biHeight );
1434 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1435 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1436 info.biBitCount, info.biCompression);
1439 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1441 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1445 if (init & CBM_INIT)
1447 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1449 DeleteObject( handle );
1459 /***********************************************************************
1460 * CreateDIBSection (GDI32.@)
1462 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1463 VOID **bits, HANDLE section, DWORD offset)
1465 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1466 BITMAPINFO *info = (BITMAPINFO *)buffer;
1469 BOOL bDesktopDC = FALSE;
1472 RGBQUAD *color_table = NULL;
1473 void *mapBits = NULL;
1475 if (bits) *bits = NULL;
1476 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1477 if (info->bmiHeader.biPlanes != 1)
1479 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1480 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1483 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1485 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1486 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1487 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1488 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1489 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1491 dib->dsBm.bmType = 0;
1492 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1493 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1494 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1495 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1496 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1497 dib->dsBm.bmBits = NULL;
1498 dib->dsBmih = info->bmiHeader;
1500 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1502 if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1504 dib->dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1505 if (!(color_table = HeapAlloc( GetProcessHeap(), 0, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) )))
1507 memcpy( color_table, info->bmiColors, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) );
1510 /* set dsBitfields values */
1511 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1513 dib->dsBmih.biCompression = BI_BITFIELDS;
1514 dib->dsBitfields[0] = 0x7c00;
1515 dib->dsBitfields[1] = 0x03e0;
1516 dib->dsBitfields[2] = 0x001f;
1518 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1520 if (usage == DIB_PAL_COLORS) goto error;
1521 dib->dsBitfields[0] = *(const DWORD *)info->bmiColors;
1522 dib->dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1523 dib->dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1524 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1526 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1528 /* get storage location for DIB bits */
1532 SYSTEM_INFO SystemInfo;
1536 GetSystemInfo( &SystemInfo );
1537 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1538 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1539 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1540 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1545 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1546 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1548 dib->dshSection = section;
1549 dib->dsOffset = offset;
1551 if (!dib->dsBm.bmBits) goto error;
1553 /* If the reference hdc is null, take the desktop dc */
1556 hdc = CreateCompatibleDC(0);
1560 if (!(dc = get_dc_ptr( hdc ))) goto error;
1562 /* create Device Dependent Bitmap and add DIB pointer */
1563 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1564 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1566 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1568 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1570 bmp->funcs = physdev->funcs;
1571 bmp->color_table = color_table;
1572 GDI_ReleaseObj( ret );
1574 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1576 DeleteObject( ret );
1581 release_dc_ptr( dc );
1582 if (bDesktopDC) DeleteDC( hdc );
1583 if (ret && bits) *bits = dib->dsBm.bmBits;
1587 if (bDesktopDC) DeleteDC( hdc );
1588 if (section) UnmapViewOfFile( mapBits );
1589 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1590 HeapFree( GetProcessHeap(), 0, color_table );
1591 HeapFree( GetProcessHeap(), 0, dib );