vbscript: Implemented Sgn.
[wine/multimedia.git] / dlls / gdi32 / dib.c
blobdd7a7f15da6c2026eaff11b09f98773cf33dde09
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 <stdarg.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <assert.h>
67 #include "windef.h"
68 #include "winbase.h"
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 /***********************************************************************
89 * bitmap_info_size
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 /* check for size overflow */
132 if (!info->biBitCount) return FALSE;
133 if (UINT_MAX / info->biBitCount < info->biWidth) return FALSE;
134 if (UINT_MAX / get_dib_stride( info->biWidth, info->biBitCount ) < abs( info->biHeight )) return FALSE;
136 switch (info->biBitCount)
138 case 1:
139 case 4:
140 case 8:
141 case 24:
142 return (info->biCompression == BI_RGB);
143 case 16:
144 case 32:
145 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
146 default:
147 return FALSE;
151 /*******************************************************************************************
152 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
154 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
156 if (!info) return FALSE;
158 if (info->biSize == sizeof(BITMAPCOREHEADER))
160 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
161 dst->biWidth = core->bcWidth;
162 dst->biHeight = core->bcHeight;
163 dst->biPlanes = core->bcPlanes;
164 dst->biBitCount = core->bcBitCount;
165 dst->biCompression = BI_RGB;
166 dst->biXPelsPerMeter = 0;
167 dst->biYPelsPerMeter = 0;
168 dst->biClrUsed = 0;
169 dst->biClrImportant = 0;
171 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
173 *dst = *info;
175 else
177 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
178 return FALSE;
181 dst->biSize = sizeof(*dst);
182 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
183 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
184 return TRUE;
187 /*******************************************************************************************
188 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
190 * The resulting sanitized BITMAPINFO is guaranteed to have:
191 * - biSize set to sizeof(BITMAPINFOHEADER)
192 * - biSizeImage set to the actual image size even for non-compressed DIB
193 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
194 * - color table present only for <= 8 bpp, always starts at info->bmiColors
196 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
197 UINT coloruse, BOOL allow_compression )
199 void *src_colors;
201 if (coloruse > DIB_PAL_COLORS + 1) return FALSE; /* FIXME: handle DIB_PAL_COLORS+1 format */
202 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
203 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
205 src_colors = (char *)info + info->bmiHeader.biSize;
207 if (dst->bmiHeader.biCompression == BI_BITFIELDS)
209 /* bitfields are always at bmiColors even in larger structures */
210 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
211 dst->bmiHeader.biClrUsed = 0;
213 else if (dst->bmiHeader.biBitCount <= 8)
215 unsigned int colors = dst->bmiHeader.biClrUsed;
216 unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
218 if (!colors) colors = max_colors;
219 else colors = min( colors, max_colors );
221 if (coloruse == DIB_PAL_COLORS)
223 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
224 max_colors = colors;
226 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
228 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
230 else
232 unsigned int i;
233 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
234 for (i = 0; i < colors; i++)
236 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
237 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
238 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
239 dst->bmiColors[i].rgbReserved = 0;
242 memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
243 dst->bmiHeader.biClrUsed = max_colors;
245 else dst->bmiHeader.biClrUsed = 0;
247 return TRUE;
250 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
252 PALETTEENTRY palEntry[256];
253 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
254 int i, colors = 1 << info->bmiHeader.biBitCount;
256 info->bmiHeader.biClrUsed = colors;
258 if (!palette) return 0;
260 memset( palEntry, 0, sizeof(palEntry) );
261 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
262 return 0;
264 for (i = 0; i < colors; i++)
266 info->bmiColors[i].rgbRed = palEntry[i].peRed;
267 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
268 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
269 info->bmiColors[i].rgbReserved = 0;
272 return colors;
275 BOOL fill_color_table_from_pal_colors( BITMAPINFO *info, HDC hdc )
277 PALETTEENTRY entries[256];
278 RGBQUAD table[256];
279 HPALETTE palette;
280 const WORD *index = (const WORD *)info->bmiColors;
281 int i, count, colors = info->bmiHeader.biClrUsed;
283 if (!colors) return TRUE;
284 if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return FALSE;
285 if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return FALSE;
287 for (i = 0; i < colors; i++, index++)
289 table[i].rgbRed = entries[*index % count].peRed;
290 table[i].rgbGreen = entries[*index % count].peGreen;
291 table[i].rgbBlue = entries[*index % count].peBlue;
292 table[i].rgbReserved = 0;
294 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
295 memcpy( info->bmiColors, table, colors * sizeof(RGBQUAD) );
296 memset( info->bmiColors + colors, 0, (info->bmiHeader.biClrUsed - colors) * sizeof(RGBQUAD) );
297 return TRUE;
300 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
302 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
303 const int bpp = info->bmiHeader.biBitCount;
305 if (height > 0)
306 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
307 else
308 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
311 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
313 DWORD i = 0;
314 int left, right;
315 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
316 HRGN run = NULL;
317 BYTE skip, num, data;
318 BYTE *out_bits, *in_bits = bits->ptr;
320 if (clip) *clip = NULL;
322 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
324 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
325 if (!out_bits) goto fail;
327 if (clip)
329 *clip = CreateRectRgn( 0, 0, 0, 0 );
330 run = CreateRectRgn( 0, 0, 0, 0 );
331 if (!*clip || !run) goto fail;
334 x = left = right = 0;
335 y = height - 1;
337 while (i < info->bmiHeader.biSizeImage - 1)
339 num = in_bits[i];
340 data = in_bits[i + 1];
341 i += 2;
343 if (num)
345 if (x + num > width) num = width - x;
346 if (num)
348 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
349 if (info->bmiHeader.biBitCount == 8)
350 memset( out_ptr, s, num );
351 else
353 if(x & 1)
355 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
356 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
357 out_ptr++;
358 x++;
359 num--;
361 /* this will write one too many if num is odd, but that doesn't matter */
362 if (num) memset( out_ptr, s, (num + 1) / 2 );
365 x += num;
366 right = x;
368 else
370 if (data < 3)
372 if(left != right && clip)
374 SetRectRgn( run, left, y, right, y + 1 );
375 CombineRgn( *clip, run, *clip, RGN_OR );
377 switch (data)
379 case 0: /* eol */
380 left = right = x = 0;
381 y--;
382 if(y < 0) goto done;
383 break;
385 case 1: /* eod */
386 goto done;
388 case 2: /* delta */
389 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
390 x += in_bits[i];
391 if (x > width) x = width;
392 left = right = x;
393 y -= in_bits[i + 1];
394 if(y < 0) goto done;
395 i += 2;
398 else /* data bytes of data */
400 num = data;
401 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
402 if (skip > info->bmiHeader.biSizeImage - i) goto done;
403 skip = (skip + 1) & ~1;
404 if (x + num > width) num = width - x;
405 if (num)
407 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
408 if (info->bmiHeader.biBitCount == 8)
409 memcpy( out_ptr, in_bits + i, num );
410 else
412 if(x & 1)
414 const BYTE *in_ptr = in_bits + i;
415 for ( ; num; num--, x++)
417 if (x & 1)
419 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
420 out_ptr++;
422 else
423 *out_ptr = (*in_ptr++ << 4) & 0xf0;
426 else
427 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
430 x += num;
431 right = x;
432 i += skip;
437 done:
438 if (run) DeleteObject( run );
439 if (bits->free) bits->free( bits );
441 bits->ptr = out_bits;
442 bits->is_copy = TRUE;
443 bits->free = free_heap_bits;
445 return TRUE;
447 fail:
448 if (run) DeleteObject( run );
449 if (clip && *clip) DeleteObject( *clip );
450 HeapFree( GetProcessHeap(), 0, out_bits );
451 return FALSE;
456 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
457 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
458 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
460 DC *dc = get_nulldrv_dc( dev );
461 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
462 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
463 struct bitblt_coords src, dst;
464 struct gdi_image_bits src_bits;
465 DWORD err;
466 HRGN clip = NULL;
467 INT ret = 0;
468 INT height = abs( src_info->bmiHeader.biHeight );
469 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
470 RECT rect;
472 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
473 xSrc, ySrc, widthSrc, heightSrc, rop);
475 src_bits.ptr = (void*)bits;
476 src_bits.is_copy = FALSE;
477 src_bits.free = NULL;
479 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
481 rect.left = xDst;
482 rect.top = yDst;
483 rect.right = xDst + widthDst;
484 rect.bottom = yDst + heightDst;
485 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
486 dst.x = rect.left;
487 dst.y = rect.top;
488 dst.width = rect.right - rect.left;
489 dst.height = rect.bottom - rect.top;
491 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
493 dst.x += dst.width;
494 dst.width = -dst.width;
496 rop &= ~NOMIRRORBITMAP;
498 src.x = xSrc;
499 src.width = widthSrc;
500 src.y = ySrc;
501 src.height = heightSrc;
503 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
504 non_stretch_from_origin = TRUE;
506 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
508 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
509 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
512 if (rop != SRCCOPY || non_stretch_from_origin)
514 if (dst.width == 1 && src.width > 1) src.width--;
515 if (dst.height == 1 && src.height > 1) src.height--;
518 if (rop != SRCCOPY)
520 if (dst.width < 0 && dst.width == src.width)
522 /* This is off-by-one, but that's what Windows does */
523 dst.x += dst.width;
524 src.x += src.width;
525 dst.width = -dst.width;
526 src.width = -src.width;
528 if (dst.height < 0 && dst.height == src.height)
530 dst.y += dst.height;
531 src.y += src.height;
532 dst.height = -dst.height;
533 src.height = -src.height;
537 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
539 if (src.y >= height && src.y + src.height + 1 < height)
540 src.y = height - 1;
541 else if (src.y > 0 && src.y + src.height + 1 < 0)
542 src.y = -src.height - 1;
544 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
546 src.visrect.left = 0;
547 src.visrect.right = src_info->bmiHeader.biWidth;
548 src.visrect.top = 0;
549 src.visrect.bottom = height;
550 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
552 if (rop == SRCCOPY) ret = height;
553 else ret = src_info->bmiHeader.biHeight;
555 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
557 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
559 if (!intersect_vis_rectangles( &dst, &src )) goto done;
561 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
563 dev = GET_DC_PHYSDEV( dc, pPutImage );
564 copy_bitmapinfo( dst_info, src_info );
565 err = dev->funcs->pPutImage( dev, clip, dst_info, &src_bits, &src, &dst, rop );
566 if (err == ERROR_BAD_FORMAT)
568 /* 1-bpp destination without a color table requires a fake 1-entry table
569 * that contains only the background color */
570 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
572 COLORREF color = GetBkColor( dev->hdc );
573 dst_info->bmiColors[0].rgbRed = GetRValue( color );
574 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
575 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
576 dst_info->bmiColors[0].rgbReserved = 0;
577 dst_info->bmiHeader.biClrUsed = 1;
580 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits )))
582 /* get rid of the fake 1-bpp table */
583 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
584 err = dev->funcs->pPutImage( dev, clip, dst_info, &src_bits, &src, &dst, rop );
588 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
590 copy_bitmapinfo( src_info, dst_info );
591 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
592 if (!err) err = dev->funcs->pPutImage( dev, NULL, dst_info, &src_bits, &src, &dst, rop );
594 if (err) ret = 0;
596 done:
597 if (src_bits.free) src_bits.free( &src_bits );
598 if (clip) DeleteObject( clip );
599 return ret;
602 /***********************************************************************
603 * StretchDIBits (GDI32.@)
605 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
606 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
607 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
609 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
610 BITMAPINFO *info = (BITMAPINFO *)buffer;
611 PHYSDEV physdev;
612 DC *dc;
613 INT ret = 0;
615 if (!bits) return 0;
616 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
618 SetLastError( ERROR_INVALID_PARAMETER );
619 return 0;
622 if ((dc = get_dc_ptr( hdc )))
624 update_dc( dc );
625 physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
626 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
627 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
628 release_dc_ptr( dc );
630 return ret;
634 /******************************************************************************
635 * SetDIBits [GDI32.@]
637 * Sets pixels in a bitmap using colors from DIB.
639 * PARAMS
640 * hdc [I] Handle to device context
641 * hbitmap [I] Handle to bitmap
642 * startscan [I] Starting scan line
643 * lines [I] Number of scan lines
644 * bits [I] Array of bitmap bits
645 * info [I] Address of structure with data
646 * coloruse [I] Type of color indexes to use
648 * RETURNS
649 * Success: Number of scan lines copied
650 * Failure: 0
652 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
653 UINT lines, LPCVOID bits, const BITMAPINFO *info,
654 UINT coloruse )
656 BITMAPOBJ *bitmap;
657 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
658 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
659 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
660 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
661 INT result = 0;
662 DWORD err;
663 struct gdi_image_bits src_bits;
664 struct bitblt_coords src, dst;
665 INT src_to_dst_offset;
666 HRGN clip = 0;
668 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ) || coloruse > DIB_PAL_COLORS)
670 SetLastError( ERROR_INVALID_PARAMETER );
671 return 0;
673 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
675 DWORD *masks = (DWORD *)src_info->bmiColors;
676 if (!masks[0] || !masks[1] || !masks[2])
678 SetLastError( ERROR_INVALID_PARAMETER );
679 return 0;
683 src_bits.ptr = (void *)bits;
684 src_bits.is_copy = FALSE;
685 src_bits.free = NULL;
686 src_bits.param = NULL;
688 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
690 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
692 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
694 if (lines == 0) goto done;
695 else lines = src_info->bmiHeader.biHeight;
696 startscan = 0;
698 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
701 dst.visrect.left = 0;
702 dst.visrect.top = 0;
703 dst.visrect.right = bitmap->dib.dsBm.bmWidth;
704 dst.visrect.bottom = bitmap->dib.dsBm.bmHeight;
706 src.visrect.left = 0;
707 src.visrect.top = 0;
708 src.visrect.right = src_info->bmiHeader.biWidth;
709 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
711 if (src_info->bmiHeader.biHeight > 0)
713 src_to_dst_offset = -startscan;
714 lines = min( lines, src.visrect.bottom - startscan );
715 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
717 else
719 src_to_dst_offset = src.visrect.bottom - lines - startscan;
720 /* Unlike the bottom-up case, Windows doesn't limit lines. */
721 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
724 result = lines;
726 offset_rect( &src.visrect, 0, src_to_dst_offset );
727 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
728 src.visrect = dst.visrect;
729 offset_rect( &src.visrect, 0, -src_to_dst_offset );
731 src.x = src.visrect.left;
732 src.y = src.visrect.top;
733 src.width = src.visrect.right - src.visrect.left;
734 src.height = src.visrect.bottom - src.visrect.top;
736 dst.x = dst.visrect.left;
737 dst.y = dst.visrect.top;
738 dst.width = dst.visrect.right - dst.visrect.left;
739 dst.height = dst.visrect.bottom - dst.visrect.top;
741 copy_bitmapinfo( dst_info, src_info );
743 err = put_image_into_bitmap( bitmap, clip, dst_info, &src_bits, &src, &dst );
744 if (err == ERROR_BAD_FORMAT)
746 err = convert_bits( src_info, &src, dst_info, &src_bits );
747 if (!err) err = put_image_into_bitmap( bitmap, clip, dst_info, &src_bits, &src, &dst );
749 if(err) result = 0;
751 done:
752 if (src_bits.free) src_bits.free( &src_bits );
753 if (clip) DeleteObject( clip );
754 GDI_ReleaseObj( hbitmap );
755 return result;
759 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
760 INT x_src, INT y_src, UINT startscan, UINT lines,
761 const void *bits, BITMAPINFO *src_info, UINT coloruse )
763 DC *dc = get_nulldrv_dc( dev );
764 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
765 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
766 struct bitblt_coords src, dst;
767 struct gdi_image_bits src_bits;
768 HRGN clip = 0;
769 DWORD err;
770 UINT height;
771 BOOL top_down;
772 POINT pt;
773 RECT rect;
775 top_down = (src_info->bmiHeader.biHeight < 0);
776 height = abs( src_info->bmiHeader.biHeight );
778 src_bits.ptr = (void *)bits;
779 src_bits.is_copy = FALSE;
780 src_bits.free = NULL;
782 if (!lines) return 0;
783 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
785 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
787 startscan = 0;
788 lines = height;
789 src_info->bmiHeader.biWidth = x_src + cx;
790 src_info->bmiHeader.biHeight = y_src + cy;
791 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
792 src.x = x_src;
793 src.y = 0;
794 src.width = cx;
795 src.height = cy;
796 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
798 else
800 if (startscan >= height) return 0;
801 if (!top_down && lines > height - startscan) lines = height - startscan;
803 /* map src to top-down coordinates with startscan as origin */
804 src.x = x_src;
805 src.y = startscan + lines - (y_src + cy);
806 src.width = cx;
807 src.height = cy;
808 if (src.y > 0)
810 if (!top_down)
812 /* get rid of unnecessary lines */
813 if (src.y >= lines) return 0;
814 lines -= src.y;
815 src.y = 0;
817 else if (src.y >= lines) return lines;
819 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
822 src.visrect.left = src.x;
823 src.visrect.top = src.y;
824 src.visrect.right = src.x + cx;
825 src.visrect.bottom = src.y + cy;
826 rect.left = 0;
827 rect.top = 0;
828 rect.right = src_info->bmiHeader.biWidth;
829 rect.bottom = abs( src_info->bmiHeader.biHeight );
830 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
832 lines = 0;
833 goto done;
836 pt.x = x_dst;
837 pt.y = y_dst;
838 LPtoDP( dev->hdc, &pt, 1 );
839 dst.x = pt.x;
840 dst.y = pt.y;
841 dst.width = cx;
842 dst.height = cy;
843 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
845 rect.left = dst.x;
846 rect.top = dst.y;
847 rect.right = dst.x + cx;
848 rect.bottom = dst.y + cy;
849 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
851 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
852 intersect_rect( &rect, &src.visrect, &dst.visrect );
853 src.visrect = dst.visrect = rect;
854 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
855 if (is_rect_empty( &dst.visrect )) goto done;
856 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
858 dev = GET_DC_PHYSDEV( dc, pPutImage );
859 copy_bitmapinfo( dst_info, src_info );
860 err = dev->funcs->pPutImage( dev, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
861 if (err == ERROR_BAD_FORMAT)
863 err = convert_bits( src_info, &src, dst_info, &src_bits );
864 if (!err) err = dev->funcs->pPutImage( dev, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
866 if (err) lines = 0;
868 done:
869 if (src_bits.free) src_bits.free( &src_bits );
870 if (clip) DeleteObject( clip );
871 return lines;
874 /***********************************************************************
875 * SetDIBitsToDevice (GDI32.@)
877 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
878 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
879 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
880 UINT coloruse )
882 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
883 BITMAPINFO *info = (BITMAPINFO *)buffer;
884 PHYSDEV physdev;
885 INT ret = 0;
886 DC *dc;
888 if (!bits) return 0;
889 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
891 SetLastError( ERROR_INVALID_PARAMETER );
892 return 0;
895 if ((dc = get_dc_ptr( hdc )))
897 update_dc( dc );
898 physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
899 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
900 ySrc, startscan, lines, bits, info, coloruse );
901 release_dc_ptr( dc );
903 return ret;
906 /***********************************************************************
907 * SetDIBColorTable (GDI32.@)
909 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, const RGBQUAD *colors )
911 DC * dc;
912 UINT result = 0;
913 BITMAPOBJ * bitmap;
915 if (!(dc = get_dc_ptr( hdc ))) return 0;
917 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
919 if (startpos < bitmap->dib.dsBmih.biClrUsed)
921 result = min( entries, bitmap->dib.dsBmih.biClrUsed - startpos );
922 memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
924 GDI_ReleaseObj( dc->hBitmap );
926 if (result) /* update colors of selected objects */
928 SetTextColor( hdc, dc->textColor );
929 SetBkColor( hdc, dc->backgroundColor );
930 SelectObject( hdc, dc->hPen );
931 SelectObject( hdc, dc->hBrush );
934 release_dc_ptr( dc );
935 return result;
939 /***********************************************************************
940 * GetDIBColorTable (GDI32.@)
942 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
944 DC * dc;
945 BITMAPOBJ *bitmap;
946 UINT result = 0;
948 if (!(dc = get_dc_ptr( hdc ))) return 0;
950 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
952 if (startpos < bitmap->dib.dsBmih.biClrUsed)
954 result = min( entries, bitmap->dib.dsBmih.biClrUsed - startpos );
955 memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
957 GDI_ReleaseObj( dc->hBitmap );
959 release_dc_ptr( dc );
960 return result;
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->dib.dsBm.bmWidth;
973 header.biHeight = bmp->dib.dsBm.bmHeight;
974 header.biPlanes = 1;
975 header.biBitCount = bmp->dib.dsBm.bmBitsPixel;
977 switch (header.biBitCount)
979 case 16:
980 case 32:
981 header.biCompression = BI_BITFIELDS;
982 break;
983 default:
984 header.biCompression = BI_RGB;
985 break;
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;
1003 else
1004 info->bmiHeader = header;
1006 return bmp->dib.dsBm.bmHeight;
1009 /************************************************************************
1010 * copy_color_info
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) );
1023 else
1025 unsigned int i;
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;
1034 else
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;
1045 unsigned int size;
1047 if (coloruse == DIB_PAL_COLORS)
1048 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1049 else
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 },
1138 switch (bpp)
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->dib.dsBm.bmWidth;
1158 info->bmiHeader.biHeight = -bmp->dib.dsBm.bmHeight;
1159 info->bmiHeader.biPlanes = 1;
1160 info->bmiHeader.biBitCount = bmp->dib.dsBm.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 );
1183 return ret;
1186 /******************************************************************************
1187 * GetDIBits [GDI32.@]
1189 * Retrieves bits of bitmap and copies to buffer.
1191 * RETURNS
1192 * Success: Number of scan lines copied from bitmap
1193 * Failure: 0
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 */
1204 DC * dc;
1205 BITMAPOBJ * bmp;
1206 int i, dst_to_src_offset, ret = 0;
1207 DWORD err;
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;
1220 if (bits &&
1221 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1222 return 0;
1223 dst_info->bmiHeader.biClrUsed = 0;
1224 dst_info->bmiHeader.biClrImportant = 0;
1226 if (!(dc = get_dc_ptr( hdc )))
1228 SetLastError( ERROR_INVALID_PARAMETER );
1229 return 0;
1231 update_dc( dc );
1232 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1234 release_dc_ptr( dc );
1235 return 0;
1238 src.visrect.left = 0;
1239 src.visrect.top = 0;
1240 src.visrect.right = bmp->dib.dsBm.bmWidth;
1241 src.visrect.bottom = bmp->dib.dsBm.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)
1249 bits = NULL;
1251 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1253 ret = fill_query_info( info, bmp );
1254 goto done;
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)
1264 case BI_RLE4:
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 */
1268 break;
1269 case BI_RLE8:
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 */
1273 break;
1274 case BI_BITFIELDS:
1275 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1276 /* fall through */
1277 case BI_RGB:
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;
1285 /* fall through */
1286 default:
1287 goto done;
1290 if (bits)
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;
1298 else
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;
1324 else
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;
1342 lines = src.height;
1345 err = get_image_from_bitmap( bmp, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1347 if (err) goto done;
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)
1358 case 16:
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) );
1364 break;
1365 case 32:
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) );
1371 break;
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;
1382 else
1384 fill_default_color_table( dst_info );
1388 if (bits)
1390 if(dst_info->bmiHeader.biHeight > 0)
1391 dst_info->bmiHeader.biHeight = src.height;
1392 else
1393 dst_info->bmiHeader.biHeight = -src.height;
1395 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
1396 if (src_bits.free) src_bits.free( &src_bits );
1397 ret = lines;
1399 else
1400 ret = !empty_rect;
1402 if (coloruse == DIB_PAL_COLORS)
1404 WORD *index = (WORD *)dst_info->bmiColors;
1405 for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1406 *index = i;
1409 copy_color_info( info, dst_info, coloruse );
1410 if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1412 done:
1413 release_dc_ptr( dc );
1414 GDI_ReleaseObj( hbitmap );
1415 return ret;
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,
1427 UINT coloruse )
1429 BITMAPINFOHEADER info;
1430 HBITMAP handle;
1431 LONG height;
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);
1445 if (hdc == NULL)
1446 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1447 else
1448 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1450 if (handle)
1452 if (init & CBM_INIT)
1454 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1456 DeleteObject( handle );
1457 handle = 0;
1462 return 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;
1474 HBITMAP ret = 0;
1475 BITMAPOBJ *bmp;
1476 void *mapBits = NULL;
1478 if (bits) *bits = NULL;
1479 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1480 if (usage > DIB_PAL_COLORS) return 0;
1481 if (info->bmiHeader.biPlanes != 1)
1483 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1484 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1487 if (!(bmp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*bmp) ))) return 0;
1489 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1490 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1491 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1492 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1493 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1495 bmp->dib.dsBm.bmType = 0;
1496 bmp->dib.dsBm.bmWidth = info->bmiHeader.biWidth;
1497 bmp->dib.dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1498 bmp->dib.dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1499 bmp->dib.dsBm.bmPlanes = info->bmiHeader.biPlanes;
1500 bmp->dib.dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1501 bmp->dib.dsBmih = info->bmiHeader;
1503 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1505 if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1506 goto error;
1507 bmp->dib.dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1508 if (!(bmp->color_table = HeapAlloc( GetProcessHeap(), 0,
1509 bmp->dib.dsBmih.biClrUsed * sizeof(RGBQUAD) )))
1510 goto error;
1511 memcpy( bmp->color_table, info->bmiColors, bmp->dib.dsBmih.biClrUsed * sizeof(RGBQUAD) );
1514 /* set dsBitfields values */
1515 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1517 bmp->dib.dsBmih.biCompression = BI_BITFIELDS;
1518 bmp->dib.dsBitfields[0] = 0x7c00;
1519 bmp->dib.dsBitfields[1] = 0x03e0;
1520 bmp->dib.dsBitfields[2] = 0x001f;
1522 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1524 if (usage == DIB_PAL_COLORS) goto error;
1525 bmp->dib.dsBitfields[0] = *(const DWORD *)info->bmiColors;
1526 bmp->dib.dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1527 bmp->dib.dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1528 if (!bmp->dib.dsBitfields[0] || !bmp->dib.dsBitfields[1] || !bmp->dib.dsBitfields[2]) goto error;
1530 else bmp->dib.dsBitfields[0] = bmp->dib.dsBitfields[1] = bmp->dib.dsBitfields[2] = 0;
1532 /* get storage location for DIB bits */
1534 if (section)
1536 SYSTEM_INFO SystemInfo;
1537 DWORD mapOffset;
1538 INT mapSize;
1540 GetSystemInfo( &SystemInfo );
1541 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1542 mapSize = bmp->dib.dsBmih.biSizeImage + (offset - mapOffset);
1543 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1544 if (mapBits) bmp->dib.dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1546 else
1548 offset = 0;
1549 bmp->dib.dsBm.bmBits = VirtualAlloc( NULL, bmp->dib.dsBmih.biSizeImage,
1550 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1552 bmp->dib.dshSection = section;
1553 bmp->dib.dsOffset = offset;
1555 if (!bmp->dib.dsBm.bmBits) goto error;
1557 if (!(ret = alloc_gdi_handle( bmp, OBJ_BITMAP, &dib_funcs ))) goto error;
1559 if (bits) *bits = bmp->dib.dsBm.bmBits;
1560 return ret;
1562 error:
1563 if (section) UnmapViewOfFile( mapBits );
1564 else VirtualFree( bmp->dib.dsBm.bmBits, 0, MEM_RELEASE );
1565 HeapFree( GetProcessHeap(), 0, bmp->color_table );
1566 HeapFree( GetProcessHeap(), 0, bmp );
1567 return 0;
1571 /***********************************************************************
1572 * DIB_SelectObject
1574 static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
1576 HGDIOBJ ret;
1577 BITMAPOBJ *bitmap;
1578 DC *dc;
1579 PHYSDEV physdev;
1581 if (!(dc = get_dc_ptr( hdc ))) return 0;
1583 if (GetObjectType( hdc ) != OBJ_MEMDC)
1585 ret = 0;
1586 goto done;
1588 ret = dc->hBitmap;
1589 if (handle == dc->hBitmap) goto done; /* nothing to do */
1591 if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
1593 ret = 0;
1594 goto done;
1597 if (GDI_get_ref_count( handle ))
1599 WARN( "Bitmap already selected in another DC\n" );
1600 GDI_ReleaseObj( handle );
1601 ret = 0;
1602 goto done;
1605 physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
1606 if (!physdev->funcs->pSelectBitmap( physdev, handle ))
1608 GDI_ReleaseObj( handle );
1609 ret = 0;
1611 else
1613 dc->hBitmap = handle;
1614 GDI_inc_ref_count( handle );
1615 dc->dirty = 0;
1616 dc->vis_rect.left = 0;
1617 dc->vis_rect.top = 0;
1618 dc->vis_rect.right = bitmap->dib.dsBm.bmWidth;
1619 dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
1620 dc->device_rect = dc->vis_rect;
1621 GDI_ReleaseObj( handle );
1622 DC_InitDC( dc );
1623 GDI_dec_ref_count( ret );
1626 done:
1627 release_dc_ptr( dc );
1628 return ret;
1632 /***********************************************************************
1633 * DIB_GetObject
1635 static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
1637 INT ret = 0;
1638 BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
1640 if (!bmp) return 0;
1642 if (!buffer) ret = sizeof(BITMAP);
1643 else if (count >= sizeof(DIBSECTION))
1645 DIBSECTION *dib = buffer;
1646 *dib = bmp->dib;
1647 dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
1648 ret = sizeof(DIBSECTION);
1650 else if (count >= sizeof(BITMAP))
1652 BITMAP *bitmap = buffer;
1653 *bitmap = bmp->dib.dsBm;
1654 ret = sizeof(BITMAP);
1657 GDI_ReleaseObj( handle );
1658 return ret;
1662 /***********************************************************************
1663 * DIB_DeleteObject
1665 static BOOL DIB_DeleteObject( HGDIOBJ handle )
1667 BITMAPOBJ *bmp;
1669 if (!(bmp = free_gdi_handle( handle ))) return FALSE;
1671 if (bmp->dib.dshSection)
1673 SYSTEM_INFO SystemInfo;
1674 GetSystemInfo( &SystemInfo );
1675 UnmapViewOfFile( (char *)bmp->dib.dsBm.bmBits -
1676 (bmp->dib.dsOffset % SystemInfo.dwAllocationGranularity) );
1678 else VirtualFree( bmp->dib.dsBm.bmBits, 0, MEM_RELEASE );
1680 HeapFree(GetProcessHeap(), 0, bmp->color_table);
1681 return HeapFree( GetProcessHeap(), 0, bmp );