msvfw32: Lpckid and lpdwFlags must be valid memory addresses.
[wine/multimedia.git] / dlls / gdi32 / dib.c
blob2817ede11bb771355e70ebaab995264715acc133
1 /*
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:
54 BITMAPINFO* info;
55 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
58 * More information:
59 Search for "Bitmap Structures" in MSDN
62 #include "config.h"
64 #include <stdarg.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <assert.h>
69 #include "windef.h"
70 #include "winbase.h"
71 #include "gdi_private.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
77 static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc );
78 static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer );
79 static BOOL DIB_DeleteObject( HGDIOBJ handle );
81 static const struct gdi_obj_funcs dib_funcs =
83 DIB_SelectObject, /* pSelectObject */
84 DIB_GetObject, /* pGetObjectA */
85 DIB_GetObject, /* pGetObjectW */
86 NULL, /* pUnrealizeObject */
87 DIB_DeleteObject /* pDeleteObject */
90 /***********************************************************************
91 * bitmap_info_size
93 * Return the size of the bitmap info structure including color table.
95 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
97 unsigned int colors, size, masks = 0;
99 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
101 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
102 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
103 return sizeof(BITMAPCOREHEADER) + colors *
104 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
106 else /* assume BITMAPINFOHEADER */
108 if (info->bmiHeader.biClrUsed) colors = min( info->bmiHeader.biClrUsed, 256 );
109 else colors = info->bmiHeader.biBitCount > 8 ? 0 : 1 << info->bmiHeader.biBitCount;
110 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
111 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
112 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
116 /*******************************************************************************************
117 * Verify that the DIB parameters are valid.
119 static BOOL is_valid_dib_format( const BITMAPINFOHEADER *info, BOOL allow_compression )
121 if (info->biWidth <= 0) return FALSE;
122 if (info->biHeight == 0) return FALSE;
124 if (allow_compression && (info->biCompression == BI_RLE4 || info->biCompression == BI_RLE8))
126 if (info->biHeight < 0) return FALSE;
127 if (!info->biSizeImage) return FALSE;
128 return info->biBitCount == (info->biCompression == BI_RLE4 ? 4 : 8);
131 if (!info->biPlanes) return FALSE;
133 /* check for size overflow */
134 if (!info->biBitCount) return FALSE;
135 if (UINT_MAX / info->biBitCount < info->biWidth) return FALSE;
136 if (UINT_MAX / get_dib_stride( info->biWidth, info->biBitCount ) < abs( info->biHeight )) return FALSE;
138 switch (info->biBitCount)
140 case 1:
141 case 4:
142 case 8:
143 case 24:
144 return (info->biCompression == BI_RGB);
145 case 16:
146 case 32:
147 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
148 default:
149 return FALSE;
153 /*******************************************************************************************
154 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
156 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
158 if (!info) return FALSE;
160 if (info->biSize == sizeof(BITMAPCOREHEADER))
162 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
163 dst->biWidth = core->bcWidth;
164 dst->biHeight = core->bcHeight;
165 dst->biPlanes = core->bcPlanes;
166 dst->biBitCount = core->bcBitCount;
167 dst->biCompression = BI_RGB;
168 dst->biXPelsPerMeter = 0;
169 dst->biYPelsPerMeter = 0;
170 dst->biClrUsed = 0;
171 dst->biClrImportant = 0;
173 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
175 *dst = *info;
177 else
179 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
180 return FALSE;
183 dst->biSize = sizeof(*dst);
184 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
185 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
186 return TRUE;
189 /*******************************************************************************************
190 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
192 * The resulting sanitized BITMAPINFO is guaranteed to have:
193 * - biSize set to sizeof(BITMAPINFOHEADER)
194 * - biSizeImage set to the actual image size even for non-compressed DIB
195 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
196 * - color table present only for <= 8 bpp, always starts at info->bmiColors
198 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
199 UINT coloruse, BOOL allow_compression )
201 void *src_colors;
203 if (coloruse > DIB_PAL_COLORS + 1) return FALSE; /* FIXME: handle DIB_PAL_COLORS+1 format */
204 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
205 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
207 src_colors = (char *)info + info->bmiHeader.biSize;
209 if (dst->bmiHeader.biCompression == BI_BITFIELDS)
211 /* bitfields are always at bmiColors even in larger structures */
212 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
213 dst->bmiHeader.biClrUsed = 0;
215 else if (dst->bmiHeader.biBitCount <= 8)
217 unsigned int colors = dst->bmiHeader.biClrUsed;
218 unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
220 if (!colors) colors = max_colors;
221 else colors = min( colors, max_colors );
223 if (coloruse == DIB_PAL_COLORS)
225 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
226 max_colors = colors;
228 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
230 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
232 else
234 unsigned int i;
235 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
236 for (i = 0; i < colors; i++)
238 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
239 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
240 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
241 dst->bmiColors[i].rgbReserved = 0;
244 memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
245 dst->bmiHeader.biClrUsed = max_colors;
247 else dst->bmiHeader.biClrUsed = 0;
249 return TRUE;
252 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
254 PALETTEENTRY palEntry[256];
255 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
256 int i, colors = 1 << info->bmiHeader.biBitCount;
258 info->bmiHeader.biClrUsed = colors;
260 if (!palette) return 0;
262 memset( palEntry, 0, sizeof(palEntry) );
263 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
264 return 0;
266 for (i = 0; i < colors; i++)
268 info->bmiColors[i].rgbRed = palEntry[i].peRed;
269 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
270 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
271 info->bmiColors[i].rgbReserved = 0;
274 return colors;
277 BOOL fill_color_table_from_pal_colors( BITMAPINFO *info, HDC hdc )
279 PALETTEENTRY entries[256];
280 RGBQUAD table[256];
281 HPALETTE palette;
282 const WORD *index = (const WORD *)info->bmiColors;
283 int i, count, colors = info->bmiHeader.biClrUsed;
285 if (!colors) return TRUE;
286 if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return FALSE;
287 if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return FALSE;
289 for (i = 0; i < colors; i++, index++)
291 table[i].rgbRed = entries[*index % count].peRed;
292 table[i].rgbGreen = entries[*index % count].peGreen;
293 table[i].rgbBlue = entries[*index % count].peBlue;
294 table[i].rgbReserved = 0;
296 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
297 memcpy( info->bmiColors, table, colors * sizeof(RGBQUAD) );
298 memset( info->bmiColors + colors, 0, (info->bmiHeader.biClrUsed - colors) * sizeof(RGBQUAD) );
299 return TRUE;
302 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
304 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
305 const int bpp = info->bmiHeader.biBitCount;
307 if (height > 0)
308 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
309 else
310 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
313 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
315 DWORD i = 0;
316 int left, right;
317 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
318 HRGN run = NULL;
319 BYTE skip, num, data;
320 BYTE *out_bits, *in_bits = bits->ptr;
322 if (clip) *clip = NULL;
324 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
326 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
327 if (!out_bits) goto fail;
329 if (clip)
331 *clip = CreateRectRgn( 0, 0, 0, 0 );
332 run = CreateRectRgn( 0, 0, 0, 0 );
333 if (!*clip || !run) goto fail;
336 x = left = right = 0;
337 y = height - 1;
339 while (i < info->bmiHeader.biSizeImage - 1)
341 num = in_bits[i];
342 data = in_bits[i + 1];
343 i += 2;
345 if (num)
347 if (x + num > width) num = width - x;
348 if (num)
350 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
351 if (info->bmiHeader.biBitCount == 8)
352 memset( out_ptr, s, num );
353 else
355 if(x & 1)
357 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
358 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
359 out_ptr++;
360 x++;
361 num--;
363 /* this will write one too many if num is odd, but that doesn't matter */
364 if (num) memset( out_ptr, s, (num + 1) / 2 );
367 x += num;
368 right = x;
370 else
372 if (data < 3)
374 if(left != right && clip)
376 SetRectRgn( run, left, y, right, y + 1 );
377 CombineRgn( *clip, run, *clip, RGN_OR );
379 switch (data)
381 case 0: /* eol */
382 left = right = x = 0;
383 y--;
384 if(y < 0) goto done;
385 break;
387 case 1: /* eod */
388 goto done;
390 case 2: /* delta */
391 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
392 x += in_bits[i];
393 if (x > width) x = width;
394 left = right = x;
395 y -= in_bits[i + 1];
396 if(y < 0) goto done;
397 i += 2;
400 else /* data bytes of data */
402 num = data;
403 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
404 if (skip > info->bmiHeader.biSizeImage - i) goto done;
405 skip = (skip + 1) & ~1;
406 if (x + num > width) num = width - x;
407 if (num)
409 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
410 if (info->bmiHeader.biBitCount == 8)
411 memcpy( out_ptr, in_bits + i, num );
412 else
414 if(x & 1)
416 const BYTE *in_ptr = in_bits + i;
417 for ( ; num; num--, x++)
419 if (x & 1)
421 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
422 out_ptr++;
424 else
425 *out_ptr = (*in_ptr++ << 4) & 0xf0;
428 else
429 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
432 x += num;
433 right = x;
434 i += skip;
439 done:
440 if (run) DeleteObject( run );
441 if (bits->free) bits->free( bits );
443 bits->ptr = out_bits;
444 bits->is_copy = TRUE;
445 bits->free = free_heap_bits;
447 return TRUE;
449 fail:
450 if (run) DeleteObject( run );
451 if (clip && *clip) DeleteObject( *clip );
452 HeapFree( GetProcessHeap(), 0, out_bits );
453 return FALSE;
458 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
459 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
460 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
462 DC *dc = get_nulldrv_dc( dev );
463 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
464 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
465 struct bitblt_coords src, dst;
466 struct gdi_image_bits src_bits;
467 DWORD err;
468 HRGN clip = NULL;
469 INT ret = 0;
470 INT height = abs( src_info->bmiHeader.biHeight );
471 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
472 RECT rect;
474 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
475 xSrc, ySrc, widthSrc, heightSrc, rop);
477 src_bits.ptr = (void*)bits;
478 src_bits.is_copy = FALSE;
479 src_bits.free = NULL;
481 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
483 rect.left = xDst;
484 rect.top = yDst;
485 rect.right = xDst + widthDst;
486 rect.bottom = yDst + heightDst;
487 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
488 dst.x = rect.left;
489 dst.y = rect.top;
490 dst.width = rect.right - rect.left;
491 dst.height = rect.bottom - rect.top;
493 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
495 dst.x += dst.width;
496 dst.width = -dst.width;
498 rop &= ~NOMIRRORBITMAP;
500 src.x = xSrc;
501 src.width = widthSrc;
502 src.y = ySrc;
503 src.height = heightSrc;
505 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
506 non_stretch_from_origin = TRUE;
508 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
510 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
511 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
514 if (rop != SRCCOPY || non_stretch_from_origin)
516 if (dst.width == 1 && src.width > 1) src.width--;
517 if (dst.height == 1 && src.height > 1) src.height--;
520 if (rop != SRCCOPY)
522 if (dst.width < 0 && dst.width == src.width)
524 /* This is off-by-one, but that's what Windows does */
525 dst.x += dst.width;
526 src.x += src.width;
527 dst.width = -dst.width;
528 src.width = -src.width;
530 if (dst.height < 0 && dst.height == src.height)
532 dst.y += dst.height;
533 src.y += src.height;
534 dst.height = -dst.height;
535 src.height = -src.height;
539 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
541 if (src.y >= height && src.y + src.height + 1 < height)
542 src.y = height - 1;
543 else if (src.y > 0 && src.y + src.height + 1 < 0)
544 src.y = -src.height - 1;
546 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
548 src.visrect.left = 0;
549 src.visrect.right = src_info->bmiHeader.biWidth;
550 src.visrect.top = 0;
551 src.visrect.bottom = height;
552 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
554 if (rop == SRCCOPY) ret = height;
555 else ret = src_info->bmiHeader.biHeight;
557 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
559 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
561 if (!intersect_vis_rectangles( &dst, &src )) goto done;
563 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
565 dev = GET_DC_PHYSDEV( dc, pPutImage );
566 copy_bitmapinfo( dst_info, src_info );
567 err = dev->funcs->pPutImage( dev, clip, dst_info, &src_bits, &src, &dst, rop );
568 if (err == ERROR_BAD_FORMAT)
570 /* 1-bpp destination without a color table requires a fake 1-entry table
571 * that contains only the background color */
572 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
574 COLORREF color = GetBkColor( dev->hdc );
575 dst_info->bmiColors[0].rgbRed = GetRValue( color );
576 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
577 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
578 dst_info->bmiColors[0].rgbReserved = 0;
579 dst_info->bmiHeader.biClrUsed = 1;
582 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits )))
584 /* get rid of the fake 1-bpp table */
585 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
586 err = dev->funcs->pPutImage( dev, clip, dst_info, &src_bits, &src, &dst, rop );
590 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
592 copy_bitmapinfo( src_info, dst_info );
593 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
594 if (!err) err = dev->funcs->pPutImage( dev, NULL, dst_info, &src_bits, &src, &dst, rop );
596 if (err) ret = 0;
598 done:
599 if (src_bits.free) src_bits.free( &src_bits );
600 if (clip) DeleteObject( clip );
601 return ret;
604 /***********************************************************************
605 * StretchDIBits (GDI32.@)
607 INT WINAPI DECLSPEC_HOTPATCH StretchDIBits( HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
608 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
609 const void *bits, const BITMAPINFO *bmi, UINT coloruse,
610 DWORD rop )
612 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
613 BITMAPINFO *info = (BITMAPINFO *)buffer;
614 PHYSDEV physdev;
615 DC *dc;
616 INT ret = 0;
618 if (!bits) return 0;
619 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
621 SetLastError( ERROR_INVALID_PARAMETER );
622 return 0;
625 if ((dc = get_dc_ptr( hdc )))
627 update_dc( dc );
628 physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
629 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
630 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
631 release_dc_ptr( dc );
633 return ret;
637 /******************************************************************************
638 * SetDIBits [GDI32.@]
640 * Sets pixels in a bitmap using colors from DIB.
642 * PARAMS
643 * hdc [I] Handle to device context
644 * hbitmap [I] Handle to bitmap
645 * startscan [I] Starting scan line
646 * lines [I] Number of scan lines
647 * bits [I] Array of bitmap bits
648 * info [I] Address of structure with data
649 * coloruse [I] Type of color indexes to use
651 * RETURNS
652 * Success: Number of scan lines copied
653 * Failure: 0
655 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
656 UINT lines, LPCVOID bits, const BITMAPINFO *info,
657 UINT coloruse )
659 BITMAPOBJ *bitmap;
660 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
661 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
662 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
663 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
664 INT result = 0;
665 DWORD err;
666 struct gdi_image_bits src_bits;
667 struct bitblt_coords src, dst;
668 INT src_to_dst_offset;
669 HRGN clip = 0;
671 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ) || coloruse > DIB_PAL_COLORS)
673 SetLastError( ERROR_INVALID_PARAMETER );
674 return 0;
676 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
678 DWORD *masks = (DWORD *)src_info->bmiColors;
679 if (!masks[0] || !masks[1] || !masks[2])
681 SetLastError( ERROR_INVALID_PARAMETER );
682 return 0;
686 src_bits.ptr = (void *)bits;
687 src_bits.is_copy = FALSE;
688 src_bits.free = NULL;
689 src_bits.param = NULL;
691 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
693 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
695 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
697 if (lines == 0) goto done;
698 else lines = src_info->bmiHeader.biHeight;
699 startscan = 0;
701 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
704 dst.visrect.left = 0;
705 dst.visrect.top = 0;
706 dst.visrect.right = bitmap->dib.dsBm.bmWidth;
707 dst.visrect.bottom = bitmap->dib.dsBm.bmHeight;
709 src.visrect.left = 0;
710 src.visrect.top = 0;
711 src.visrect.right = src_info->bmiHeader.biWidth;
712 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
714 if (src_info->bmiHeader.biHeight > 0)
716 src_to_dst_offset = -startscan;
717 lines = min( lines, src.visrect.bottom - startscan );
718 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
720 else
722 src_to_dst_offset = src.visrect.bottom - lines - startscan;
723 /* Unlike the bottom-up case, Windows doesn't limit lines. */
724 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
727 result = lines;
729 offset_rect( &src.visrect, 0, src_to_dst_offset );
730 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
731 src.visrect = dst.visrect;
732 offset_rect( &src.visrect, 0, -src_to_dst_offset );
734 src.x = src.visrect.left;
735 src.y = src.visrect.top;
736 src.width = src.visrect.right - src.visrect.left;
737 src.height = src.visrect.bottom - src.visrect.top;
739 dst.x = dst.visrect.left;
740 dst.y = dst.visrect.top;
741 dst.width = dst.visrect.right - dst.visrect.left;
742 dst.height = dst.visrect.bottom - dst.visrect.top;
744 copy_bitmapinfo( dst_info, src_info );
746 err = put_image_into_bitmap( bitmap, clip, dst_info, &src_bits, &src, &dst );
747 if (err == ERROR_BAD_FORMAT)
749 err = convert_bits( src_info, &src, dst_info, &src_bits );
750 if (!err) err = put_image_into_bitmap( bitmap, clip, dst_info, &src_bits, &src, &dst );
752 if(err) result = 0;
754 done:
755 if (src_bits.free) src_bits.free( &src_bits );
756 if (clip) DeleteObject( clip );
757 GDI_ReleaseObj( hbitmap );
758 return result;
762 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
763 INT x_src, INT y_src, UINT startscan, UINT lines,
764 const void *bits, BITMAPINFO *src_info, UINT coloruse )
766 DC *dc = get_nulldrv_dc( dev );
767 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
768 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
769 struct bitblt_coords src, dst;
770 struct gdi_image_bits src_bits;
771 HRGN clip = 0;
772 DWORD err;
773 UINT height;
774 BOOL top_down;
775 POINT pt;
776 RECT rect;
778 top_down = (src_info->bmiHeader.biHeight < 0);
779 height = abs( src_info->bmiHeader.biHeight );
781 src_bits.ptr = (void *)bits;
782 src_bits.is_copy = FALSE;
783 src_bits.free = NULL;
785 if (!lines) return 0;
786 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
788 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
790 startscan = 0;
791 lines = height;
792 src_info->bmiHeader.biWidth = x_src + cx;
793 src_info->bmiHeader.biHeight = y_src + cy;
794 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
795 src.x = x_src;
796 src.y = 0;
797 src.width = cx;
798 src.height = cy;
799 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
801 else
803 if (startscan >= height) return 0;
804 if (!top_down && lines > height - startscan) lines = height - startscan;
806 /* map src to top-down coordinates with startscan as origin */
807 src.x = x_src;
808 src.y = startscan + lines - (y_src + cy);
809 src.width = cx;
810 src.height = cy;
811 if (src.y > 0)
813 if (!top_down)
815 /* get rid of unnecessary lines */
816 if (src.y >= lines) return 0;
817 lines -= src.y;
818 src.y = 0;
820 else if (src.y >= lines) return lines;
822 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
825 src.visrect.left = src.x;
826 src.visrect.top = src.y;
827 src.visrect.right = src.x + cx;
828 src.visrect.bottom = src.y + cy;
829 rect.left = 0;
830 rect.top = 0;
831 rect.right = src_info->bmiHeader.biWidth;
832 rect.bottom = abs( src_info->bmiHeader.biHeight );
833 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
835 lines = 0;
836 goto done;
839 pt.x = x_dst;
840 pt.y = y_dst;
841 LPtoDP( dev->hdc, &pt, 1 );
842 dst.x = pt.x;
843 dst.y = pt.y;
844 dst.width = cx;
845 dst.height = cy;
846 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
848 rect.left = dst.x;
849 rect.top = dst.y;
850 rect.right = dst.x + cx;
851 rect.bottom = dst.y + cy;
852 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
854 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
855 intersect_rect( &rect, &src.visrect, &dst.visrect );
856 src.visrect = dst.visrect = rect;
857 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
858 if (is_rect_empty( &dst.visrect )) goto done;
859 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
861 dev = GET_DC_PHYSDEV( dc, pPutImage );
862 copy_bitmapinfo( dst_info, src_info );
863 err = dev->funcs->pPutImage( dev, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
864 if (err == ERROR_BAD_FORMAT)
866 err = convert_bits( src_info, &src, dst_info, &src_bits );
867 if (!err) err = dev->funcs->pPutImage( dev, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
869 if (err) lines = 0;
871 done:
872 if (src_bits.free) src_bits.free( &src_bits );
873 if (clip) DeleteObject( clip );
874 return lines;
877 /***********************************************************************
878 * SetDIBitsToDevice (GDI32.@)
880 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
881 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
882 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
883 UINT coloruse )
885 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
886 BITMAPINFO *info = (BITMAPINFO *)buffer;
887 PHYSDEV physdev;
888 INT ret = 0;
889 DC *dc;
891 if (!bits) return 0;
892 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
894 SetLastError( ERROR_INVALID_PARAMETER );
895 return 0;
898 if ((dc = get_dc_ptr( hdc )))
900 update_dc( dc );
901 physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
902 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
903 ySrc, startscan, lines, bits, info, coloruse );
904 release_dc_ptr( dc );
906 return ret;
909 /***********************************************************************
910 * SetDIBColorTable (GDI32.@)
912 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, const RGBQUAD *colors )
914 DC * dc;
915 UINT result = 0;
916 BITMAPOBJ * bitmap;
918 if (!(dc = get_dc_ptr( hdc ))) return 0;
920 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
922 if (startpos < bitmap->dib.dsBmih.biClrUsed)
924 result = min( entries, bitmap->dib.dsBmih.biClrUsed - startpos );
925 memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
927 GDI_ReleaseObj( dc->hBitmap );
929 if (result) /* update colors of selected objects */
931 SetTextColor( hdc, dc->textColor );
932 SetBkColor( hdc, dc->backgroundColor );
933 SelectObject( hdc, dc->hPen );
934 SelectObject( hdc, dc->hBrush );
937 release_dc_ptr( dc );
938 return result;
942 /***********************************************************************
943 * GetDIBColorTable (GDI32.@)
945 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
947 DC * dc;
948 BITMAPOBJ *bitmap;
949 UINT result = 0;
951 if (!(dc = get_dc_ptr( hdc ))) return 0;
953 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
955 if (startpos < bitmap->dib.dsBmih.biClrUsed)
957 result = min( entries, bitmap->dib.dsBmih.biClrUsed - startpos );
958 memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
960 GDI_ReleaseObj( dc->hBitmap );
962 release_dc_ptr( dc );
963 return result;
966 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
967 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
969 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
971 BITMAPINFOHEADER header;
973 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
974 header.biWidth = bmp->dib.dsBm.bmWidth;
975 header.biHeight = bmp->dib.dsBm.bmHeight;
976 header.biPlanes = 1;
977 header.biBitCount = bmp->dib.dsBm.bmBitsPixel;
979 switch (header.biBitCount)
981 case 16:
982 case 32:
983 header.biCompression = BI_BITFIELDS;
984 break;
985 default:
986 header.biCompression = BI_RGB;
987 break;
990 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
991 header.biXPelsPerMeter = 0;
992 header.biYPelsPerMeter = 0;
993 header.biClrUsed = 0;
994 header.biClrImportant = 0;
996 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
998 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
1000 coreheader->bcWidth = header.biWidth;
1001 coreheader->bcHeight = header.biHeight;
1002 coreheader->bcPlanes = header.biPlanes;
1003 coreheader->bcBitCount = header.biBitCount;
1005 else
1006 info->bmiHeader = header;
1008 return bmp->dib.dsBm.bmHeight;
1011 /************************************************************************
1012 * copy_color_info
1014 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1016 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1018 assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1020 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1022 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1023 if (coloruse == DIB_PAL_COLORS)
1024 memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1025 else
1027 unsigned int i;
1028 for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1030 core->bmciColors[i].rgbtRed = src->bmiColors[i].rgbRed;
1031 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1032 core->bmciColors[i].rgbtBlue = src->bmiColors[i].rgbBlue;
1036 else
1038 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1039 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1041 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1042 /* bitfields are always at bmiColors even in larger structures */
1043 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1044 else if (src->bmiHeader.biClrUsed)
1046 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1047 unsigned int size;
1049 if (coloruse == DIB_PAL_COLORS)
1050 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1051 else
1052 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1053 memcpy( colorptr, src->bmiColors, size );
1058 const RGBQUAD *get_default_color_table( int bpp )
1060 static const RGBQUAD table_1[2] =
1062 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1064 static const RGBQUAD table_4[16] =
1066 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1067 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1068 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1069 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1071 static const RGBQUAD table_8[256] =
1073 /* first and last 10 entries are the default system palette entries */
1074 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1075 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1076 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1077 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1078 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1079 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1080 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1081 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1082 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1083 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1084 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1085 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1086 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1087 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1088 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1089 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1090 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1091 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1092 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1093 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1094 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1095 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1096 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1097 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1098 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1099 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1100 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1101 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1102 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1103 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1104 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1105 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1106 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1107 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1108 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1109 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1110 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1111 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1112 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1113 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1114 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1115 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1116 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1117 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1118 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1119 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1120 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1121 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1122 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1123 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1124 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1125 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1126 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1127 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1128 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1129 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1130 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1131 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1132 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1133 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1134 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1135 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1136 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1137 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1140 switch (bpp)
1142 case 1: return table_1;
1143 case 4: return table_4;
1144 case 8: return table_8;
1145 default: return NULL;
1149 void fill_default_color_table( BITMAPINFO *info )
1151 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1152 memcpy( info->bmiColors, get_default_color_table( info->bmiHeader.biBitCount ),
1153 info->bmiHeader.biClrUsed * sizeof(RGBQUAD) );
1156 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1158 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1159 info->bmiHeader.biWidth = bmp->dib.dsBm.bmWidth;
1160 info->bmiHeader.biHeight = -bmp->dib.dsBm.bmHeight;
1161 info->bmiHeader.biPlanes = 1;
1162 info->bmiHeader.biBitCount = bmp->dib.dsBm.bmBitsPixel;
1163 info->bmiHeader.biCompression = BI_RGB;
1164 info->bmiHeader.biXPelsPerMeter = 0;
1165 info->bmiHeader.biYPelsPerMeter = 0;
1166 info->bmiHeader.biClrUsed = 0;
1167 info->bmiHeader.biClrImportant = 0;
1170 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1172 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1173 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1174 unsigned int info_size;
1176 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1178 info_size = get_dib_info_size( info, usage );
1179 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + info->bmiHeader.biSizeImage )))
1181 memcpy( ret, info, info_size );
1182 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size( src_info, usage ),
1183 info->bmiHeader.biSizeImage );
1185 return ret;
1188 /******************************************************************************
1189 * GetDIBits [GDI32.@]
1191 * Retrieves bits of bitmap and copies to buffer.
1193 * RETURNS
1194 * Success: Number of scan lines copied from bitmap
1195 * Failure: 0
1197 INT WINAPI GetDIBits(
1198 HDC hdc, /* [in] Handle to device context */
1199 HBITMAP hbitmap, /* [in] Handle to bitmap */
1200 UINT startscan, /* [in] First scan line to set in dest bitmap */
1201 UINT lines, /* [in] Number of scan lines to copy */
1202 LPVOID bits, /* [out] Address of array for bitmap bits */
1203 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1204 UINT coloruse) /* [in] RGB or palette index */
1206 DC * dc;
1207 BITMAPOBJ * bmp;
1208 int i, dst_to_src_offset, ret = 0;
1209 DWORD err;
1210 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1211 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1212 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1213 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1214 struct gdi_image_bits src_bits;
1215 struct bitblt_coords src, dst;
1216 BOOL empty_rect = FALSE;
1218 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1219 own copy and transfer the colour info back at the end */
1220 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1221 if (coloruse > DIB_PAL_COLORS) return 0;
1222 if (bits &&
1223 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1224 return 0;
1225 dst_info->bmiHeader.biClrUsed = 0;
1226 dst_info->bmiHeader.biClrImportant = 0;
1228 if (!(dc = get_dc_ptr( hdc )))
1230 SetLastError( ERROR_INVALID_PARAMETER );
1231 return 0;
1233 update_dc( dc );
1234 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1236 release_dc_ptr( dc );
1237 return 0;
1240 src.visrect.left = 0;
1241 src.visrect.top = 0;
1242 src.visrect.right = bmp->dib.dsBm.bmWidth;
1243 src.visrect.bottom = bmp->dib.dsBm.bmHeight;
1245 dst.visrect.left = 0;
1246 dst.visrect.top = 0;
1247 dst.visrect.right = dst_info->bmiHeader.biWidth;
1248 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1250 if (lines == 0 || startscan >= dst.visrect.bottom)
1251 bits = NULL;
1253 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1255 ret = fill_query_info( info, bmp );
1256 goto done;
1259 /* validate parameters */
1261 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1262 if (dst_info->bmiHeader.biHeight == 0) goto done;
1264 switch (dst_info->bmiHeader.biCompression)
1266 case BI_RLE4:
1267 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1268 if (dst_info->bmiHeader.biHeight < 0) goto done;
1269 if (bits) goto done; /* can't retrieve compressed bits */
1270 break;
1271 case BI_RLE8:
1272 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1273 if (dst_info->bmiHeader.biHeight < 0) goto done;
1274 if (bits) goto done; /* can't retrieve compressed bits */
1275 break;
1276 case BI_BITFIELDS:
1277 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1278 /* fall through */
1279 case BI_RGB:
1280 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1281 if (dst_info->bmiHeader.biBitCount == 1) break;
1282 if (dst_info->bmiHeader.biBitCount == 4) break;
1283 if (dst_info->bmiHeader.biBitCount == 8) break;
1284 if (dst_info->bmiHeader.biBitCount == 16) break;
1285 if (dst_info->bmiHeader.biBitCount == 24) break;
1286 if (dst_info->bmiHeader.biBitCount == 32) break;
1287 /* fall through */
1288 default:
1289 goto done;
1292 if (bits)
1294 if (dst_info->bmiHeader.biHeight > 0)
1296 dst_to_src_offset = -startscan;
1297 lines = min( lines, dst.visrect.bottom - startscan );
1298 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1300 else
1302 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1303 if (dst_to_src_offset < 0)
1305 dst_to_src_offset = 0;
1306 lines = dst.visrect.bottom - startscan;
1308 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1311 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1312 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1313 dst.visrect = src.visrect;
1314 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1316 if (dst_info->bmiHeader.biHeight > 0)
1318 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1320 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1321 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1322 memset( bits, 0, pad_bytes );
1323 bits = (char *)bits + pad_bytes;
1326 else
1328 if (dst.visrect.bottom < lines)
1330 int pad_lines = lines - dst.visrect.bottom;
1331 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1332 int pad_bytes = pad_lines * stride;
1333 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1337 if (empty_rect) bits = NULL;
1339 src.x = src.visrect.left;
1340 src.y = src.visrect.top;
1341 src.width = src.visrect.right - src.visrect.left;
1342 src.height = src.visrect.bottom - src.visrect.top;
1344 lines = src.height;
1347 err = get_image_from_bitmap( bmp, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1349 if (err) goto done;
1351 /* fill out the src colour table, if it needs one */
1352 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1353 fill_default_color_table( src_info );
1355 /* if the src and dst are the same depth, copy the colour info across */
1356 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1358 switch (src_info->bmiHeader.biBitCount)
1360 case 16:
1361 if (src_info->bmiHeader.biCompression == BI_RGB)
1363 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1364 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1366 break;
1367 case 32:
1368 if (src_info->bmiHeader.biCompression == BI_RGB)
1370 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1371 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1373 break;
1375 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1376 copy_color_info( dst_info, src_info, coloruse );
1378 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1380 if( coloruse == DIB_PAL_COLORS )
1382 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1384 else
1386 fill_default_color_table( dst_info );
1390 if (bits)
1392 if(dst_info->bmiHeader.biHeight > 0)
1393 dst_info->bmiHeader.biHeight = src.height;
1394 else
1395 dst_info->bmiHeader.biHeight = -src.height;
1397 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
1398 if (src_bits.free) src_bits.free( &src_bits );
1399 ret = lines;
1401 else
1402 ret = !empty_rect;
1404 if (coloruse == DIB_PAL_COLORS)
1406 WORD *index = (WORD *)dst_info->bmiColors;
1407 for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1408 *index = i;
1411 copy_color_info( info, dst_info, coloruse );
1412 if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1414 done:
1415 release_dc_ptr( dc );
1416 GDI_ReleaseObj( hbitmap );
1417 return ret;
1421 /***********************************************************************
1422 * CreateDIBitmap (GDI32.@)
1424 * Creates a DDB (device dependent bitmap) from a DIB.
1425 * The DDB will have the same color depth as the reference DC.
1427 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1428 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1429 UINT coloruse )
1431 BITMAPINFOHEADER info;
1432 HBITMAP handle;
1433 LONG height;
1435 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1436 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1437 if (coloruse > DIB_PAL_COLORS + 1) return 0;
1438 if (info.biWidth < 0) return 0;
1440 /* Top-down DIBs have a negative height */
1441 height = abs( info.biHeight );
1443 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1444 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1445 info.biBitCount, info.biCompression);
1447 if (hdc == NULL)
1448 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1449 else
1450 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1452 if (handle)
1454 if (init & CBM_INIT)
1456 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1458 DeleteObject( handle );
1459 handle = 0;
1464 return handle;
1468 /***********************************************************************
1469 * CreateDIBSection (GDI32.@)
1471 HBITMAP WINAPI CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
1472 VOID **bits, HANDLE section, DWORD offset)
1474 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1475 BITMAPINFO *info = (BITMAPINFO *)buffer;
1476 HBITMAP ret = 0;
1477 BITMAPOBJ *bmp;
1478 void *mapBits = NULL;
1480 if (bits) *bits = NULL;
1481 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1482 if (usage > DIB_PAL_COLORS) return 0;
1483 if (info->bmiHeader.biPlanes != 1)
1485 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1486 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1489 if (!(bmp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*bmp) ))) return 0;
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 bmp->dib.dsBm.bmType = 0;
1498 bmp->dib.dsBm.bmWidth = info->bmiHeader.biWidth;
1499 bmp->dib.dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1500 bmp->dib.dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1501 bmp->dib.dsBm.bmPlanes = info->bmiHeader.biPlanes;
1502 bmp->dib.dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1503 bmp->dib.dsBmih = info->bmiHeader;
1505 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1507 if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1508 goto error;
1509 bmp->dib.dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1510 if (!(bmp->color_table = HeapAlloc( GetProcessHeap(), 0,
1511 bmp->dib.dsBmih.biClrUsed * sizeof(RGBQUAD) )))
1512 goto error;
1513 memcpy( bmp->color_table, info->bmiColors, bmp->dib.dsBmih.biClrUsed * sizeof(RGBQUAD) );
1516 /* set dsBitfields values */
1517 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1519 bmp->dib.dsBmih.biCompression = BI_BITFIELDS;
1520 bmp->dib.dsBitfields[0] = 0x7c00;
1521 bmp->dib.dsBitfields[1] = 0x03e0;
1522 bmp->dib.dsBitfields[2] = 0x001f;
1524 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1526 if (usage == DIB_PAL_COLORS) goto error;
1527 bmp->dib.dsBitfields[0] = *(const DWORD *)info->bmiColors;
1528 bmp->dib.dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1529 bmp->dib.dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1530 if (!bmp->dib.dsBitfields[0] || !bmp->dib.dsBitfields[1] || !bmp->dib.dsBitfields[2]) goto error;
1532 else bmp->dib.dsBitfields[0] = bmp->dib.dsBitfields[1] = bmp->dib.dsBitfields[2] = 0;
1534 /* get storage location for DIB bits */
1536 if (section)
1538 SYSTEM_INFO SystemInfo;
1539 DWORD mapOffset;
1540 INT mapSize;
1542 GetSystemInfo( &SystemInfo );
1543 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1544 mapSize = bmp->dib.dsBmih.biSizeImage + (offset - mapOffset);
1545 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1546 if (mapBits) bmp->dib.dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1548 else
1550 offset = 0;
1551 bmp->dib.dsBm.bmBits = VirtualAlloc( NULL, bmp->dib.dsBmih.biSizeImage,
1552 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1554 bmp->dib.dshSection = section;
1555 bmp->dib.dsOffset = offset;
1557 if (!bmp->dib.dsBm.bmBits) goto error;
1559 if (!(ret = alloc_gdi_handle( bmp, OBJ_BITMAP, &dib_funcs ))) goto error;
1561 if (bits) *bits = bmp->dib.dsBm.bmBits;
1562 return ret;
1564 error:
1565 if (section) UnmapViewOfFile( mapBits );
1566 else VirtualFree( bmp->dib.dsBm.bmBits, 0, MEM_RELEASE );
1567 HeapFree( GetProcessHeap(), 0, bmp->color_table );
1568 HeapFree( GetProcessHeap(), 0, bmp );
1569 return 0;
1573 /***********************************************************************
1574 * DIB_SelectObject
1576 static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
1578 HGDIOBJ ret;
1579 BITMAPOBJ *bitmap;
1580 DC *dc;
1581 PHYSDEV physdev;
1583 if (!(dc = get_dc_ptr( hdc ))) return 0;
1585 if (GetObjectType( hdc ) != OBJ_MEMDC)
1587 ret = 0;
1588 goto done;
1590 ret = dc->hBitmap;
1591 if (handle == dc->hBitmap) goto done; /* nothing to do */
1593 if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
1595 ret = 0;
1596 goto done;
1599 if (GDI_get_ref_count( handle ))
1601 WARN( "Bitmap already selected in another DC\n" );
1602 GDI_ReleaseObj( handle );
1603 ret = 0;
1604 goto done;
1607 physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
1608 if (!physdev->funcs->pSelectBitmap( physdev, handle ))
1610 GDI_ReleaseObj( handle );
1611 ret = 0;
1613 else
1615 dc->hBitmap = handle;
1616 GDI_inc_ref_count( handle );
1617 dc->dirty = 0;
1618 dc->vis_rect.left = 0;
1619 dc->vis_rect.top = 0;
1620 dc->vis_rect.right = bitmap->dib.dsBm.bmWidth;
1621 dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
1622 dc->device_rect = dc->vis_rect;
1623 GDI_ReleaseObj( handle );
1624 DC_InitDC( dc );
1625 GDI_dec_ref_count( ret );
1628 done:
1629 release_dc_ptr( dc );
1630 return ret;
1634 /***********************************************************************
1635 * DIB_GetObject
1637 static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
1639 INT ret = 0;
1640 BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
1642 if (!bmp) return 0;
1644 if (!buffer) ret = sizeof(BITMAP);
1645 else if (count >= sizeof(DIBSECTION))
1647 DIBSECTION *dib = buffer;
1648 *dib = bmp->dib;
1649 dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
1650 ret = sizeof(DIBSECTION);
1652 else if (count >= sizeof(BITMAP))
1654 BITMAP *bitmap = buffer;
1655 *bitmap = bmp->dib.dsBm;
1656 ret = sizeof(BITMAP);
1659 GDI_ReleaseObj( handle );
1660 return ret;
1664 /***********************************************************************
1665 * DIB_DeleteObject
1667 static BOOL DIB_DeleteObject( HGDIOBJ handle )
1669 BITMAPOBJ *bmp;
1671 if (!(bmp = free_gdi_handle( handle ))) return FALSE;
1673 if (bmp->dib.dshSection)
1675 SYSTEM_INFO SystemInfo;
1676 GetSystemInfo( &SystemInfo );
1677 UnmapViewOfFile( (char *)bmp->dib.dsBm.bmBits -
1678 (bmp->dib.dsOffset % SystemInfo.dwAllocationGranularity) );
1680 else VirtualFree( bmp->dib.dsBm.bmBits, 0, MEM_RELEASE );
1682 HeapFree(GetProcessHeap(), 0, bmp->color_table);
1683 return HeapFree( GetProcessHeap(), 0, bmp );