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 static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc );
76 static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer );
77 static BOOL DIB_DeleteObject( HGDIOBJ handle );
79 static const struct gdi_obj_funcs dib_funcs =
81 DIB_SelectObject, /* pSelectObject */
82 DIB_GetObject, /* pGetObjectA */
83 DIB_GetObject, /* pGetObjectW */
84 NULL, /* pUnrealizeObject */
85 DIB_DeleteObject /* pDeleteObject */
88 /***********************************************************************
91 * Return the size of the bitmap info structure including color table.
93 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
95 unsigned int colors, size, masks = 0;
97 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
99 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
100 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
101 return sizeof(BITMAPCOREHEADER) + colors *
102 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
104 else /* assume BITMAPINFOHEADER */
106 if (info->bmiHeader.biClrUsed) colors = min( info->bmiHeader.biClrUsed, 256 );
107 else colors = info->bmiHeader.biBitCount > 8 ? 0 : 1 << info->bmiHeader.biBitCount;
108 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
109 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
110 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
114 /*******************************************************************************************
115 * Verify that the DIB parameters are valid.
117 static BOOL is_valid_dib_format( const BITMAPINFOHEADER *info, BOOL allow_compression )
119 if (info->biWidth <= 0) return FALSE;
120 if (info->biHeight == 0) return FALSE;
122 if (allow_compression && (info->biCompression == BI_RLE4 || info->biCompression == BI_RLE8))
124 if (info->biHeight < 0) return FALSE;
125 if (!info->biSizeImage) return FALSE;
126 return info->biBitCount == (info->biCompression == BI_RLE4 ? 4 : 8);
129 if (!info->biPlanes) return FALSE;
131 switch (info->biBitCount)
137 return (info->biCompression == BI_RGB);
140 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
146 /*******************************************************************************************
147 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
149 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
151 if (!info) return FALSE;
153 if (info->biSize == sizeof(BITMAPCOREHEADER))
155 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
156 dst->biWidth = core->bcWidth;
157 dst->biHeight = core->bcHeight;
158 dst->biPlanes = core->bcPlanes;
159 dst->biBitCount = core->bcBitCount;
160 dst->biCompression = BI_RGB;
161 dst->biXPelsPerMeter = 0;
162 dst->biYPelsPerMeter = 0;
164 dst->biClrImportant = 0;
166 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
172 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
176 dst->biSize = sizeof(*dst);
177 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
178 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
182 /*******************************************************************************************
183 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
185 * The resulting sanitized BITMAPINFO is guaranteed to have:
186 * - biSize set to sizeof(BITMAPINFOHEADER)
187 * - biSizeImage set to the actual image size even for non-compressed DIB
188 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
189 * - color table present only for <= 8 bpp, always starts at info->bmiColors
191 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
192 UINT coloruse, BOOL allow_compression )
196 if (coloruse > DIB_PAL_COLORS + 1) return FALSE; /* FIXME: handle DIB_PAL_COLORS+1 format */
197 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
198 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
200 src_colors = (char *)info + info->bmiHeader.biSize;
202 if (dst->bmiHeader.biCompression == BI_BITFIELDS)
204 /* bitfields are always at bmiColors even in larger structures */
205 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
206 dst->bmiHeader.biClrUsed = 0;
208 else if (dst->bmiHeader.biBitCount <= 8)
210 unsigned int colors = dst->bmiHeader.biClrUsed;
211 unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
213 if (!colors) colors = max_colors;
214 else colors = min( colors, max_colors );
216 if (coloruse == DIB_PAL_COLORS)
218 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
221 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
223 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
228 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
229 for (i = 0; i < colors; i++)
231 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
232 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
233 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
234 dst->bmiColors[i].rgbReserved = 0;
237 memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
238 dst->bmiHeader.biClrUsed = max_colors;
240 else dst->bmiHeader.biClrUsed = 0;
245 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
247 PALETTEENTRY palEntry[256];
248 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
249 int i, colors = 1 << info->bmiHeader.biBitCount;
251 info->bmiHeader.biClrUsed = colors;
253 if (!palette) return 0;
255 memset( palEntry, 0, sizeof(palEntry) );
256 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
259 for (i = 0; i < colors; i++)
261 info->bmiColors[i].rgbRed = palEntry[i].peRed;
262 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
263 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
264 info->bmiColors[i].rgbReserved = 0;
270 BOOL fill_color_table_from_pal_colors( BITMAPINFO *info, HDC hdc )
272 PALETTEENTRY entries[256];
275 const WORD *index = (const WORD *)info->bmiColors;
276 int i, count, colors = info->bmiHeader.biClrUsed;
278 if (!colors) return TRUE;
279 if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return FALSE;
280 if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return FALSE;
282 for (i = 0; i < colors; i++, index++)
284 table[i].rgbRed = entries[*index % count].peRed;
285 table[i].rgbGreen = entries[*index % count].peGreen;
286 table[i].rgbBlue = entries[*index % count].peBlue;
287 table[i].rgbReserved = 0;
289 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
290 memcpy( info->bmiColors, table, colors * sizeof(RGBQUAD) );
291 memset( info->bmiColors + colors, 0, (info->bmiHeader.biClrUsed - colors) * sizeof(RGBQUAD) );
295 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
297 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
298 const int bpp = info->bmiHeader.biBitCount;
301 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
303 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
306 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
310 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
312 BYTE skip, num, data;
313 BYTE *out_bits, *in_bits = bits->ptr;
315 if (clip) *clip = NULL;
317 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
319 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
320 if (!out_bits) goto fail;
324 *clip = CreateRectRgn( 0, 0, 0, 0 );
325 run = CreateRectRgn( 0, 0, 0, 0 );
326 if (!*clip || !run) goto fail;
329 x = left = right = 0;
332 while (i < info->bmiHeader.biSizeImage - 1)
335 data = in_bits[i + 1];
340 if (x + num > width) num = width - x;
343 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
344 if (info->bmiHeader.biBitCount == 8)
345 memset( out_ptr, s, num );
350 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
351 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
356 /* this will write one too many if num is odd, but that doesn't matter */
357 if (num) memset( out_ptr, s, (num + 1) / 2 );
367 if(left != right && clip)
369 SetRectRgn( run, left, y, right, y + 1 );
370 CombineRgn( *clip, run, *clip, RGN_OR );
375 left = right = x = 0;
384 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
386 if (x > width) x = width;
393 else /* data bytes of data */
396 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
397 if (skip > info->bmiHeader.biSizeImage - i) goto done;
398 skip = (skip + 1) & ~1;
399 if (x + num > width) num = width - x;
402 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
403 if (info->bmiHeader.biBitCount == 8)
404 memcpy( out_ptr, in_bits + i, num );
409 const BYTE *in_ptr = in_bits + i;
410 for ( ; num; num--, x++)
414 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
418 *out_ptr = (*in_ptr++ << 4) & 0xf0;
422 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
433 if (run) DeleteObject( run );
434 if (bits->free) bits->free( bits );
436 bits->ptr = out_bits;
437 bits->is_copy = TRUE;
438 bits->free = free_heap_bits;
443 if (run) DeleteObject( run );
444 if (clip && *clip) DeleteObject( *clip );
445 HeapFree( GetProcessHeap(), 0, out_bits );
451 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
452 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
453 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
455 DC *dc = get_nulldrv_dc( dev );
456 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
457 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
458 struct bitblt_coords src, dst;
459 struct gdi_image_bits src_bits;
463 INT height = abs( src_info->bmiHeader.biHeight );
464 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
467 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
468 xSrc, ySrc, widthSrc, heightSrc, rop);
470 src_bits.ptr = (void*)bits;
471 src_bits.is_copy = FALSE;
472 src_bits.free = NULL;
474 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
478 rect.right = xDst + widthDst;
479 rect.bottom = yDst + heightDst;
480 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
483 dst.width = rect.right - rect.left;
484 dst.height = rect.bottom - rect.top;
486 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
489 dst.width = -dst.width;
491 rop &= ~NOMIRRORBITMAP;
494 src.width = widthSrc;
496 src.height = heightSrc;
498 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
499 non_stretch_from_origin = TRUE;
501 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
503 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
504 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
507 if (rop != SRCCOPY || non_stretch_from_origin)
509 if (dst.width == 1 && src.width > 1) src.width--;
510 if (dst.height == 1 && src.height > 1) src.height--;
515 if (dst.width < 0 && dst.width == src.width)
517 /* This is off-by-one, but that's what Windows does */
520 dst.width = -dst.width;
521 src.width = -src.width;
523 if (dst.height < 0 && dst.height == src.height)
527 dst.height = -dst.height;
528 src.height = -src.height;
532 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
534 if (src.y >= height && src.y + src.height + 1 < height)
536 else if (src.y > 0 && src.y + src.height + 1 < 0)
537 src.y = -src.height - 1;
539 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
541 src.visrect.left = 0;
542 src.visrect.right = src_info->bmiHeader.biWidth;
544 src.visrect.bottom = height;
545 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
547 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
549 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
551 if (!intersect_vis_rectangles( &dst, &src )) goto done;
553 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
555 dev = GET_DC_PHYSDEV( dc, pPutImage );
556 copy_bitmapinfo( dst_info, src_info );
557 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
558 if (err == ERROR_BAD_FORMAT)
560 /* 1-bpp destination without a color table requires a fake 1-entry table
561 * that contains only the background color */
562 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
564 COLORREF color = GetBkColor( dev->hdc );
565 dst_info->bmiColors[0].rgbRed = GetRValue( color );
566 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
567 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
568 dst_info->bmiColors[0].rgbReserved = 0;
569 dst_info->bmiHeader.biClrUsed = 1;
572 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
574 /* get rid of the fake 1-bpp table */
575 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
576 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
580 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
582 copy_bitmapinfo( src_info, dst_info );
583 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
584 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
587 else if (rop == SRCCOPY) ret = height;
588 else ret = src_info->bmiHeader.biHeight;
591 if (src_bits.free) src_bits.free( &src_bits );
592 if (clip) DeleteObject( clip );
596 /***********************************************************************
597 * StretchDIBits (GDI32.@)
599 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
600 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
601 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
603 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
604 BITMAPINFO *info = (BITMAPINFO *)buffer;
609 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
611 SetLastError( ERROR_INVALID_PARAMETER );
615 if ((dc = get_dc_ptr( hdc )))
617 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
619 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
620 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
621 release_dc_ptr( dc );
627 /******************************************************************************
628 * SetDIBits [GDI32.@]
630 * Sets pixels in a bitmap using colors from DIB.
633 * hdc [I] Handle to device context
634 * hbitmap [I] Handle to bitmap
635 * startscan [I] Starting scan line
636 * lines [I] Number of scan lines
637 * bits [I] Array of bitmap bits
638 * info [I] Address of structure with data
639 * coloruse [I] Type of color indexes to use
642 * Success: Number of scan lines copied
645 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
646 UINT lines, LPCVOID bits, const BITMAPINFO *info,
650 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
651 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
652 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
653 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
656 struct gdi_image_bits src_bits;
657 struct bitblt_coords src, dst;
658 INT src_to_dst_offset;
661 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ) || coloruse > DIB_PAL_COLORS)
663 SetLastError( ERROR_INVALID_PARAMETER );
666 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
668 DWORD *masks = (DWORD *)src_info->bmiColors;
669 if (!masks[0] || !masks[1] || !masks[2])
671 SetLastError( ERROR_INVALID_PARAMETER );
676 src_bits.ptr = (void *)bits;
677 src_bits.is_copy = FALSE;
678 src_bits.free = NULL;
679 src_bits.param = NULL;
681 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
683 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
685 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
687 if (lines == 0) goto done;
688 else lines = src_info->bmiHeader.biHeight;
691 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
694 dst.visrect.left = 0;
696 dst.visrect.right = bitmap->bitmap.bmWidth;
697 dst.visrect.bottom = bitmap->bitmap.bmHeight;
699 src.visrect.left = 0;
701 src.visrect.right = src_info->bmiHeader.biWidth;
702 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
704 if (src_info->bmiHeader.biHeight > 0)
706 src_to_dst_offset = -startscan;
707 lines = min( lines, src.visrect.bottom - startscan );
708 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
712 src_to_dst_offset = src.visrect.bottom - lines - startscan;
713 /* Unlike the bottom-up case, Windows doesn't limit lines. */
714 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
719 offset_rect( &src.visrect, 0, src_to_dst_offset );
720 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
721 src.visrect = dst.visrect;
722 offset_rect( &src.visrect, 0, -src_to_dst_offset );
724 src.x = src.visrect.left;
725 src.y = src.visrect.top;
726 src.width = src.visrect.right - src.visrect.left;
727 src.height = src.visrect.bottom - src.visrect.top;
729 dst.x = dst.visrect.left;
730 dst.y = dst.visrect.top;
731 dst.width = dst.visrect.right - dst.visrect.left;
732 dst.height = dst.visrect.bottom - dst.visrect.top;
734 copy_bitmapinfo( dst_info, src_info );
736 err = bitmap->funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
737 if (err == ERROR_BAD_FORMAT)
739 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
740 if (!err) err = bitmap->funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
745 if (src_bits.free) src_bits.free( &src_bits );
746 if (clip) DeleteObject( clip );
747 GDI_ReleaseObj( hbitmap );
752 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
753 INT x_src, INT y_src, UINT startscan, UINT lines,
754 const void *bits, BITMAPINFO *src_info, UINT coloruse )
756 DC *dc = get_nulldrv_dc( dev );
757 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
758 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
759 struct bitblt_coords src, dst;
760 struct gdi_image_bits src_bits;
768 top_down = (src_info->bmiHeader.biHeight < 0);
769 height = abs( src_info->bmiHeader.biHeight );
771 src_bits.ptr = (void *)bits;
772 src_bits.is_copy = FALSE;
773 src_bits.free = NULL;
775 if (!lines) return 0;
776 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
778 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
782 src_info->bmiHeader.biWidth = x_src + cx;
783 src_info->bmiHeader.biHeight = y_src + cy;
784 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
789 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
793 if (startscan >= height) return 0;
794 if (!top_down && lines > height - startscan) lines = height - startscan;
796 /* map src to top-down coordinates with startscan as origin */
798 src.y = startscan + lines - (y_src + cy);
805 /* get rid of unnecessary lines */
806 if (src.y >= lines) return 0;
810 else if (src.y >= lines) return lines;
812 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
815 src.visrect.left = src.x;
816 src.visrect.top = src.y;
817 src.visrect.right = src.x + cx;
818 src.visrect.bottom = src.y + cy;
821 rect.right = src_info->bmiHeader.biWidth;
822 rect.bottom = abs( src_info->bmiHeader.biHeight );
823 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
831 LPtoDP( dev->hdc, &pt, 1 );
836 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
840 rect.right = dst.x + cx;
841 rect.bottom = dst.y + cy;
842 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
844 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
845 intersect_rect( &rect, &src.visrect, &dst.visrect );
846 src.visrect = dst.visrect = rect;
847 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
848 if (is_rect_empty( &dst.visrect )) goto done;
849 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
851 dev = GET_DC_PHYSDEV( dc, pPutImage );
852 copy_bitmapinfo( dst_info, src_info );
853 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
854 if (err == ERROR_BAD_FORMAT)
856 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
857 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
862 if (src_bits.free) src_bits.free( &src_bits );
863 if (clip) DeleteObject( clip );
867 /***********************************************************************
868 * SetDIBitsToDevice (GDI32.@)
870 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
871 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
872 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
875 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
876 BITMAPINFO *info = (BITMAPINFO *)buffer;
881 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
883 SetLastError( ERROR_INVALID_PARAMETER );
887 if ((dc = get_dc_ptr( hdc )))
889 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
891 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
892 ySrc, startscan, lines, bits, info, coloruse );
893 release_dc_ptr( dc );
898 /***********************************************************************
899 * SetDIBColorTable (GDI32.@)
901 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
907 if (!(dc = get_dc_ptr( hdc ))) return 0;
909 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
911 /* Check if currently selected bitmap is a DIB */
912 if (bitmap->color_table)
914 if (startpos < bitmap->dib->dsBmih.biClrUsed)
916 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
917 memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
920 GDI_ReleaseObj( dc->hBitmap );
922 if (result) /* update colors of selected objects */
924 SetTextColor( hdc, dc->textColor );
925 SetBkColor( hdc, dc->backgroundColor );
926 SelectObject( hdc, dc->hPen );
927 SelectObject( hdc, dc->hBrush );
930 release_dc_ptr( dc );
935 /***********************************************************************
936 * GetDIBColorTable (GDI32.@)
938 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
944 if (!(dc = get_dc_ptr( hdc ))) return 0;
946 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
948 /* Check if currently selected bitmap is a DIB */
949 if (bitmap->color_table)
951 if (startpos < bitmap->dib->dsBmih.biClrUsed)
953 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
954 memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
957 GDI_ReleaseObj( dc->hBitmap );
959 release_dc_ptr( dc );
963 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
964 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
965 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
967 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
969 BITMAPINFOHEADER header;
971 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
972 header.biWidth = bmp->bitmap.bmWidth;
973 header.biHeight = bmp->bitmap.bmHeight;
975 header.biBitCount = bmp->bitmap.bmBitsPixel;
977 switch (header.biBitCount)
981 header.biCompression = BI_BITFIELDS;
984 header.biCompression = BI_RGB;
988 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
989 header.biXPelsPerMeter = 0;
990 header.biYPelsPerMeter = 0;
991 header.biClrUsed = 0;
992 header.biClrImportant = 0;
994 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
996 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
998 coreheader->bcWidth = header.biWidth;
999 coreheader->bcHeight = header.biHeight;
1000 coreheader->bcPlanes = header.biPlanes;
1001 coreheader->bcBitCount = header.biBitCount;
1004 info->bmiHeader = header;
1006 return abs(bmp->bitmap.bmHeight);
1009 /************************************************************************
1012 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1014 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1016 assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1018 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1020 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1021 if (coloruse == DIB_PAL_COLORS)
1022 memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1026 for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1028 core->bmciColors[i].rgbtRed = src->bmiColors[i].rgbRed;
1029 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1030 core->bmciColors[i].rgbtBlue = src->bmiColors[i].rgbBlue;
1036 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1037 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1039 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1040 /* bitfields are always at bmiColors even in larger structures */
1041 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1042 else if (src->bmiHeader.biClrUsed)
1044 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1047 if (coloruse == DIB_PAL_COLORS)
1048 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1050 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1051 memcpy( colorptr, src->bmiColors, size );
1056 const RGBQUAD *get_default_color_table( int bpp )
1058 static const RGBQUAD table_1[2] =
1060 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1062 static const RGBQUAD table_4[16] =
1064 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1065 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1066 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1067 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1069 static const RGBQUAD table_8[256] =
1071 /* first and last 10 entries are the default system palette entries */
1072 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1073 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1074 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1075 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1076 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1077 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1078 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1079 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1080 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1081 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1082 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1083 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1084 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1085 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1086 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1087 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1088 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1089 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1090 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1091 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1092 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1093 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1094 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1095 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1096 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1097 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1098 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1099 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1100 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1101 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1102 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1103 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1104 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1105 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1106 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1107 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1108 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1109 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1110 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1111 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1112 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1113 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1114 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1115 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1116 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1117 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1118 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1119 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1120 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1121 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1122 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1123 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1124 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1125 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1126 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1127 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1128 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1129 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1130 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1131 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1132 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1133 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1134 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1135 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1140 case 1: return table_1;
1141 case 4: return table_4;
1142 case 8: return table_8;
1143 default: return NULL;
1147 void fill_default_color_table( BITMAPINFO *info )
1149 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1150 memcpy( info->bmiColors, get_default_color_table( info->bmiHeader.biBitCount ),
1151 info->bmiHeader.biClrUsed * sizeof(RGBQUAD) );
1154 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1156 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1157 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1158 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1159 info->bmiHeader.biPlanes = 1;
1160 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1161 info->bmiHeader.biCompression = BI_RGB;
1162 info->bmiHeader.biXPelsPerMeter = 0;
1163 info->bmiHeader.biYPelsPerMeter = 0;
1164 info->bmiHeader.biClrUsed = 0;
1165 info->bmiHeader.biClrImportant = 0;
1168 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1170 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1171 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1172 unsigned int info_size;
1174 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1176 info_size = get_dib_info_size( info, usage );
1177 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + info->bmiHeader.biSizeImage )))
1179 memcpy( ret, info, info_size );
1180 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size( src_info, usage ),
1181 info->bmiHeader.biSizeImage );
1186 /******************************************************************************
1187 * GetDIBits [GDI32.@]
1189 * Retrieves bits of bitmap and copies to buffer.
1192 * Success: Number of scan lines copied from bitmap
1195 INT WINAPI GetDIBits(
1196 HDC hdc, /* [in] Handle to device context */
1197 HBITMAP hbitmap, /* [in] Handle to bitmap */
1198 UINT startscan, /* [in] First scan line to set in dest bitmap */
1199 UINT lines, /* [in] Number of scan lines to copy */
1200 LPVOID bits, /* [out] Address of array for bitmap bits */
1201 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1202 UINT coloruse) /* [in] RGB or palette index */
1206 int i, dst_to_src_offset, ret = 0;
1208 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1209 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1210 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1211 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1212 struct gdi_image_bits src_bits;
1213 struct bitblt_coords src, dst;
1214 BOOL empty_rect = FALSE;
1216 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1217 own copy and transfer the colour info back at the end */
1218 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1219 if (coloruse > DIB_PAL_COLORS) return 0;
1221 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1223 dst_info->bmiHeader.biClrUsed = 0;
1224 dst_info->bmiHeader.biClrImportant = 0;
1226 if (!(dc = get_dc_ptr( hdc )))
1228 SetLastError( ERROR_INVALID_PARAMETER );
1232 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1234 release_dc_ptr( dc );
1238 src.visrect.left = 0;
1239 src.visrect.top = 0;
1240 src.visrect.right = bmp->bitmap.bmWidth;
1241 src.visrect.bottom = bmp->bitmap.bmHeight;
1243 dst.visrect.left = 0;
1244 dst.visrect.top = 0;
1245 dst.visrect.right = dst_info->bmiHeader.biWidth;
1246 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1248 if (lines == 0 || startscan >= dst.visrect.bottom)
1251 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1253 ret = fill_query_info( info, bmp );
1257 /* validate parameters */
1259 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1260 if (dst_info->bmiHeader.biHeight == 0) goto done;
1262 switch (dst_info->bmiHeader.biCompression)
1265 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1266 if (dst_info->bmiHeader.biHeight < 0) goto done;
1267 if (bits) goto done; /* can't retrieve compressed bits */
1270 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1271 if (dst_info->bmiHeader.biHeight < 0) goto done;
1272 if (bits) goto done; /* can't retrieve compressed bits */
1275 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1278 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1279 if (dst_info->bmiHeader.biBitCount == 1) break;
1280 if (dst_info->bmiHeader.biBitCount == 4) break;
1281 if (dst_info->bmiHeader.biBitCount == 8) break;
1282 if (dst_info->bmiHeader.biBitCount == 16) break;
1283 if (dst_info->bmiHeader.biBitCount == 24) break;
1284 if (dst_info->bmiHeader.biBitCount == 32) break;
1292 if (dst_info->bmiHeader.biHeight > 0)
1294 dst_to_src_offset = -startscan;
1295 lines = min( lines, dst.visrect.bottom - startscan );
1296 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1300 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1301 if (dst_to_src_offset < 0)
1303 dst_to_src_offset = 0;
1304 lines = dst.visrect.bottom - startscan;
1306 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1309 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1310 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1311 dst.visrect = src.visrect;
1312 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1314 if (dst_info->bmiHeader.biHeight > 0)
1316 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1318 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1319 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1320 memset( bits, 0, pad_bytes );
1321 bits = (char *)bits + pad_bytes;
1326 if (dst.visrect.bottom < lines)
1328 int pad_lines = lines - dst.visrect.bottom;
1329 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1330 int pad_bytes = pad_lines * stride;
1331 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1335 if (empty_rect) bits = NULL;
1337 src.x = src.visrect.left;
1338 src.y = src.visrect.top;
1339 src.width = src.visrect.right - src.visrect.left;
1340 src.height = src.visrect.bottom - src.visrect.top;
1345 err = bmp->funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1349 /* fill out the src colour table, if it needs one */
1350 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1351 fill_default_color_table( src_info );
1353 /* if the src and dst are the same depth, copy the colour info across */
1354 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1356 switch (src_info->bmiHeader.biBitCount)
1359 if (src_info->bmiHeader.biCompression == BI_RGB)
1361 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1362 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1366 if (src_info->bmiHeader.biCompression == BI_RGB)
1368 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1369 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1373 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1374 copy_color_info( dst_info, src_info, coloruse );
1376 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1378 if( coloruse == DIB_PAL_COLORS )
1380 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1384 fill_default_color_table( dst_info );
1390 if(dst_info->bmiHeader.biHeight > 0)
1391 dst_info->bmiHeader.biHeight = src.height;
1393 dst_info->bmiHeader.biHeight = -src.height;
1395 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1396 if (src_bits.free) src_bits.free( &src_bits );
1400 ret = empty_rect ? FALSE : TRUE;
1402 if (coloruse == DIB_PAL_COLORS)
1404 WORD *index = (WORD *)dst_info->bmiColors;
1405 for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1409 copy_color_info( info, dst_info, coloruse );
1410 if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1413 release_dc_ptr( dc );
1414 GDI_ReleaseObj( hbitmap );
1419 /***********************************************************************
1420 * CreateDIBitmap (GDI32.@)
1422 * Creates a DDB (device dependent bitmap) from a DIB.
1423 * The DDB will have the same color depth as the reference DC.
1425 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1426 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1429 BITMAPINFOHEADER info;
1433 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1434 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1435 if (coloruse > DIB_PAL_COLORS + 1) return 0;
1436 if (info.biWidth < 0) return 0;
1438 /* Top-down DIBs have a negative height */
1439 height = abs( info.biHeight );
1441 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1442 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1443 info.biBitCount, info.biCompression);
1446 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1448 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1452 if (init & CBM_INIT)
1454 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1456 DeleteObject( handle );
1466 /***********************************************************************
1467 * CreateDIBSection (GDI32.@)
1469 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1470 VOID **bits, HANDLE section, DWORD offset)
1472 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1473 BITMAPINFO *info = (BITMAPINFO *)buffer;
1477 void *mapBits = NULL;
1479 if (bits) *bits = NULL;
1480 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1481 if (usage > DIB_PAL_COLORS) return 0;
1482 if (info->bmiHeader.biPlanes != 1)
1484 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1485 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1488 if (!(bmp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*bmp) ))) return 0;
1489 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) goto error;
1491 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1492 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1493 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1494 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1495 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1497 dib->dsBm.bmType = 0;
1498 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1499 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1500 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1501 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1502 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1503 dib->dsBm.bmBits = NULL;
1504 dib->dsBmih = info->bmiHeader;
1506 bmp->funcs = &dib_driver;
1509 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1511 if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1513 dib->dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1514 if (!(bmp->color_table = HeapAlloc( GetProcessHeap(), 0, dib->dsBmih.biClrUsed*sizeof(RGBQUAD) )))
1516 memcpy( bmp->color_table, info->bmiColors, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) );
1519 /* set dsBitfields values */
1520 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1522 dib->dsBmih.biCompression = BI_BITFIELDS;
1523 dib->dsBitfields[0] = 0x7c00;
1524 dib->dsBitfields[1] = 0x03e0;
1525 dib->dsBitfields[2] = 0x001f;
1527 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1529 if (usage == DIB_PAL_COLORS) goto error;
1530 dib->dsBitfields[0] = *(const DWORD *)info->bmiColors;
1531 dib->dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1532 dib->dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1533 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1535 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1537 /* get storage location for DIB bits */
1541 SYSTEM_INFO SystemInfo;
1545 GetSystemInfo( &SystemInfo );
1546 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1547 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1548 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1549 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1554 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1555 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1557 dib->dshSection = section;
1558 dib->dsOffset = offset;
1560 if (!dib->dsBm.bmBits) goto error;
1562 bmp->bitmap = dib->dsBm;
1563 bmp->bitmap.bmWidthBytes = get_bitmap_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1564 bmp->bitmap.bmBits = NULL;
1566 if (!(ret = alloc_gdi_handle( &bmp->header, OBJ_BITMAP, &dib_funcs ))) goto error;
1568 if (bits) *bits = dib->dsBm.bmBits;
1572 if (section) UnmapViewOfFile( mapBits );
1573 else VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1574 HeapFree( GetProcessHeap(), 0, bmp->color_table );
1575 HeapFree( GetProcessHeap(), 0, dib );
1576 HeapFree( GetProcessHeap(), 0, bmp );
1581 /***********************************************************************
1584 static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
1589 PHYSDEV physdev = NULL, old_physdev = NULL, pathdev = NULL;
1591 if (!(dc = get_dc_ptr( hdc ))) return 0;
1593 if (GetObjectType( hdc ) != OBJ_MEMDC)
1599 if (handle == dc->hBitmap) goto done; /* nothing to do */
1601 if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
1607 if (bitmap->header.selcount)
1609 WARN( "Bitmap already selected in another DC\n" );
1610 GDI_ReleaseObj( handle );
1615 if (dc->physDev->funcs == &path_driver) pathdev = pop_dc_driver( &dc->physDev );
1617 old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
1618 physdev = dc->dibdrv;
1619 if (old_physdev != dc->dibdrv)
1621 if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs );
1624 if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) goto done;
1625 dc->dibdrv = physdev = dc->physDev;
1629 if (!physdev->funcs->pSelectBitmap( physdev, handle ))
1631 GDI_ReleaseObj( handle );
1636 dc->hBitmap = handle;
1637 GDI_inc_ref_count( handle );
1639 dc->vis_rect.left = 0;
1640 dc->vis_rect.top = 0;
1641 dc->vis_rect.right = bitmap->bitmap.bmWidth;
1642 dc->vis_rect.bottom = bitmap->bitmap.bmHeight;
1643 GDI_ReleaseObj( handle );
1645 GDI_dec_ref_count( ret );
1651 if (old_physdev && old_physdev != dc->dibdrv) pop_dc_driver( &dc->physDev );
1653 if (pathdev) push_dc_driver( &dc->physDev, pathdev, pathdev->funcs );
1654 release_dc_ptr( dc );
1659 /***********************************************************************
1662 static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
1665 BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
1669 if (!buffer) ret = sizeof(BITMAP);
1670 else if (count >= sizeof(DIBSECTION))
1672 DIBSECTION *dib = buffer;
1674 dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
1675 ret = sizeof(DIBSECTION);
1677 else if (count >= sizeof(BITMAP))
1679 BITMAP *bitmap = buffer;
1680 *bitmap = bmp->dib->dsBm;
1681 ret = sizeof(BITMAP);
1684 GDI_ReleaseObj( handle );
1689 /***********************************************************************
1692 static BOOL DIB_DeleteObject( HGDIOBJ handle )
1696 if (!(bmp = free_gdi_handle( handle ))) return FALSE;
1698 if (bmp->dib->dshSection)
1700 SYSTEM_INFO SystemInfo;
1701 GetSystemInfo( &SystemInfo );
1702 UnmapViewOfFile( (char *)bmp->dib->dsBm.bmBits -
1703 (bmp->dib->dsOffset % SystemInfo.dwAllocationGranularity) );
1705 else VirtualFree( bmp->dib->dsBm.bmBits, 0, MEM_RELEASE );
1707 HeapFree(GetProcessHeap(), 0, bmp->dib);
1708 HeapFree(GetProcessHeap(), 0, bmp->color_table);
1709 return HeapFree( GetProcessHeap(), 0, bmp );