gdi32: Use the bpp info from the bitmap structure now that it's identical to the...
[wine/multimedia.git] / dlls / gdi32 / dib.c
blob143cc474af57ff4461f50fa3633818b57eab30a2
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 switch (info->biBitCount)
133 case 1:
134 case 4:
135 case 8:
136 case 24:
137 return (info->biCompression == BI_RGB);
138 case 16:
139 case 32:
140 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
141 default:
142 return FALSE;
146 /*******************************************************************************************
147 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
149 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
151 if (!info) return FALSE;
153 if (info->biSize == sizeof(BITMAPCOREHEADER))
155 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
156 dst->biWidth = core->bcWidth;
157 dst->biHeight = core->bcHeight;
158 dst->biPlanes = core->bcPlanes;
159 dst->biBitCount = core->bcBitCount;
160 dst->biCompression = BI_RGB;
161 dst->biXPelsPerMeter = 0;
162 dst->biYPelsPerMeter = 0;
163 dst->biClrUsed = 0;
164 dst->biClrImportant = 0;
166 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
168 *dst = *info;
170 else
172 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
173 return FALSE;
176 dst->biSize = sizeof(*dst);
177 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
178 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
179 return TRUE;
182 /*******************************************************************************************
183 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
185 * The resulting sanitized BITMAPINFO is guaranteed to have:
186 * - biSize set to sizeof(BITMAPINFOHEADER)
187 * - biSizeImage set to the actual image size even for non-compressed DIB
188 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
189 * - color table present only for <= 8 bpp, always starts at info->bmiColors
191 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
192 UINT coloruse, BOOL allow_compression )
194 void *src_colors;
196 if (coloruse > DIB_PAL_COLORS + 1) return FALSE; /* FIXME: handle DIB_PAL_COLORS+1 format */
197 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
198 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
200 src_colors = (char *)info + info->bmiHeader.biSize;
202 if (dst->bmiHeader.biCompression == BI_BITFIELDS)
204 /* bitfields are always at bmiColors even in larger structures */
205 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
206 dst->bmiHeader.biClrUsed = 0;
208 else if (dst->bmiHeader.biBitCount <= 8)
210 unsigned int colors = dst->bmiHeader.biClrUsed;
211 unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
213 if (!colors) colors = max_colors;
214 else colors = min( colors, max_colors );
216 if (coloruse == DIB_PAL_COLORS)
218 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
219 max_colors = colors;
221 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
223 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
225 else
227 unsigned int i;
228 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
229 for (i = 0; i < colors; i++)
231 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
232 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
233 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
234 dst->bmiColors[i].rgbReserved = 0;
237 memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
238 dst->bmiHeader.biClrUsed = max_colors;
240 else dst->bmiHeader.biClrUsed = 0;
242 return TRUE;
245 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
247 PALETTEENTRY palEntry[256];
248 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
249 int i, colors = 1 << info->bmiHeader.biBitCount;
251 info->bmiHeader.biClrUsed = colors;
253 if (!palette) return 0;
255 memset( palEntry, 0, sizeof(palEntry) );
256 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
257 return 0;
259 for (i = 0; i < colors; i++)
261 info->bmiColors[i].rgbRed = palEntry[i].peRed;
262 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
263 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
264 info->bmiColors[i].rgbReserved = 0;
267 return colors;
270 BOOL fill_color_table_from_pal_colors( BITMAPINFO *info, HDC hdc )
272 PALETTEENTRY entries[256];
273 RGBQUAD table[256];
274 HPALETTE palette;
275 const WORD *index = (const WORD *)info->bmiColors;
276 int i, count, colors = info->bmiHeader.biClrUsed;
278 if (!colors) return TRUE;
279 if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return FALSE;
280 if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return FALSE;
282 for (i = 0; i < colors; i++, index++)
284 table[i].rgbRed = entries[*index % count].peRed;
285 table[i].rgbGreen = entries[*index % count].peGreen;
286 table[i].rgbBlue = entries[*index % count].peBlue;
287 table[i].rgbReserved = 0;
289 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
290 memcpy( info->bmiColors, table, colors * sizeof(RGBQUAD) );
291 memset( info->bmiColors + colors, 0, (info->bmiHeader.biClrUsed - colors) * sizeof(RGBQUAD) );
292 return TRUE;
295 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
297 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
298 const int bpp = info->bmiHeader.biBitCount;
300 if (height > 0)
301 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
302 else
303 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
306 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
308 int i = 0;
309 int left, right;
310 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
311 HRGN run = NULL;
312 BYTE skip, num, data;
313 BYTE *out_bits, *in_bits = bits->ptr;
315 if (clip) *clip = NULL;
317 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
319 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
320 if (!out_bits) goto fail;
322 if (clip)
324 *clip = CreateRectRgn( 0, 0, 0, 0 );
325 run = CreateRectRgn( 0, 0, 0, 0 );
326 if (!*clip || !run) goto fail;
329 x = left = right = 0;
330 y = height - 1;
332 while (i < info->bmiHeader.biSizeImage - 1)
334 num = in_bits[i];
335 data = in_bits[i + 1];
336 i += 2;
338 if (num)
340 if (x + num > width) num = width - x;
341 if (num)
343 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
344 if (info->bmiHeader.biBitCount == 8)
345 memset( out_ptr, s, num );
346 else
348 if(x & 1)
350 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
351 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
352 out_ptr++;
353 x++;
354 num--;
356 /* this will write one too many if num is odd, but that doesn't matter */
357 if (num) memset( out_ptr, s, (num + 1) / 2 );
360 x += num;
361 right = x;
363 else
365 if (data < 3)
367 if(left != right && clip)
369 SetRectRgn( run, left, y, right, y + 1 );
370 CombineRgn( *clip, run, *clip, RGN_OR );
372 switch (data)
374 case 0: /* eol */
375 left = right = x = 0;
376 y--;
377 if(y < 0) goto done;
378 break;
380 case 1: /* eod */
381 goto done;
383 case 2: /* delta */
384 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
385 x += in_bits[i];
386 if (x > width) x = width;
387 left = right = x;
388 y -= in_bits[i + 1];
389 if(y < 0) goto done;
390 i += 2;
393 else /* data bytes of data */
395 num = data;
396 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
397 if (skip > info->bmiHeader.biSizeImage - i) goto done;
398 skip = (skip + 1) & ~1;
399 if (x + num > width) num = width - x;
400 if (num)
402 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
403 if (info->bmiHeader.biBitCount == 8)
404 memcpy( out_ptr, in_bits + i, num );
405 else
407 if(x & 1)
409 const BYTE *in_ptr = in_bits + i;
410 for ( ; num; num--, x++)
412 if (x & 1)
414 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
415 out_ptr++;
417 else
418 *out_ptr = (*in_ptr++ << 4) & 0xf0;
421 else
422 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
425 x += num;
426 right = x;
427 i += skip;
432 done:
433 if (run) DeleteObject( run );
434 if (bits->free) bits->free( bits );
436 bits->ptr = out_bits;
437 bits->is_copy = TRUE;
438 bits->free = free_heap_bits;
440 return TRUE;
442 fail:
443 if (run) DeleteObject( run );
444 if (clip && *clip) DeleteObject( *clip );
445 HeapFree( GetProcessHeap(), 0, out_bits );
446 return FALSE;
451 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
452 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
453 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
455 DC *dc = get_nulldrv_dc( dev );
456 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
457 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
458 struct bitblt_coords src, dst;
459 struct gdi_image_bits src_bits;
460 DWORD err;
461 HRGN clip = NULL;
462 INT ret = 0;
463 INT height = abs( src_info->bmiHeader.biHeight );
464 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
465 RECT rect;
467 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
468 xSrc, ySrc, widthSrc, heightSrc, rop);
470 src_bits.ptr = (void*)bits;
471 src_bits.is_copy = FALSE;
472 src_bits.free = NULL;
474 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
476 rect.left = xDst;
477 rect.top = yDst;
478 rect.right = xDst + widthDst;
479 rect.bottom = yDst + heightDst;
480 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
481 dst.x = rect.left;
482 dst.y = rect.top;
483 dst.width = rect.right - rect.left;
484 dst.height = rect.bottom - rect.top;
486 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
488 dst.x += dst.width;
489 dst.width = -dst.width;
491 rop &= ~NOMIRRORBITMAP;
493 src.x = xSrc;
494 src.width = widthSrc;
495 src.y = ySrc;
496 src.height = heightSrc;
498 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
499 non_stretch_from_origin = TRUE;
501 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
503 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
504 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
507 if (rop != SRCCOPY || non_stretch_from_origin)
509 if (dst.width == 1 && src.width > 1) src.width--;
510 if (dst.height == 1 && src.height > 1) src.height--;
513 if (rop != SRCCOPY)
515 if (dst.width < 0 && dst.width == src.width)
517 /* This is off-by-one, but that's what Windows does */
518 dst.x += dst.width;
519 src.x += src.width;
520 dst.width = -dst.width;
521 src.width = -src.width;
523 if (dst.height < 0 && dst.height == src.height)
525 dst.y += dst.height;
526 src.y += src.height;
527 dst.height = -dst.height;
528 src.height = -src.height;
532 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
534 if (src.y >= height && src.y + src.height + 1 < height)
535 src.y = height - 1;
536 else if (src.y > 0 && src.y + src.height + 1 < 0)
537 src.y = -src.height - 1;
539 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
541 src.visrect.left = 0;
542 src.visrect.right = src_info->bmiHeader.biWidth;
543 src.visrect.top = 0;
544 src.visrect.bottom = height;
545 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
547 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
549 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
551 if (!intersect_vis_rectangles( &dst, &src )) goto done;
553 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
555 dev = GET_DC_PHYSDEV( dc, pPutImage );
556 copy_bitmapinfo( dst_info, src_info );
557 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
558 if (err == ERROR_BAD_FORMAT)
560 /* 1-bpp destination without a color table requires a fake 1-entry table
561 * that contains only the background color */
562 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
564 COLORREF color = GetBkColor( dev->hdc );
565 dst_info->bmiColors[0].rgbRed = GetRValue( color );
566 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
567 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
568 dst_info->bmiColors[0].rgbReserved = 0;
569 dst_info->bmiHeader.biClrUsed = 1;
572 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
574 /* get rid of the fake 1-bpp table */
575 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
576 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
580 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
582 copy_bitmapinfo( src_info, dst_info );
583 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
584 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
586 if (err) ret = 0;
587 else if (rop == SRCCOPY) ret = height;
588 else ret = src_info->bmiHeader.biHeight;
590 done:
591 if (src_bits.free) src_bits.free( &src_bits );
592 if (clip) DeleteObject( clip );
593 return ret;
596 /***********************************************************************
597 * StretchDIBits (GDI32.@)
599 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
600 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
601 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
603 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
604 BITMAPINFO *info = (BITMAPINFO *)buffer;
605 DC *dc;
606 INT ret = 0;
608 if (!bits) return 0;
609 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
611 SetLastError( ERROR_INVALID_PARAMETER );
612 return 0;
615 if ((dc = get_dc_ptr( hdc )))
617 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
618 update_dc( dc );
619 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
620 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
621 release_dc_ptr( dc );
623 return ret;
627 /******************************************************************************
628 * SetDIBits [GDI32.@]
630 * Sets pixels in a bitmap using colors from DIB.
632 * PARAMS
633 * hdc [I] Handle to device context
634 * hbitmap [I] Handle to bitmap
635 * startscan [I] Starting scan line
636 * lines [I] Number of scan lines
637 * bits [I] Array of bitmap bits
638 * info [I] Address of structure with data
639 * coloruse [I] Type of color indexes to use
641 * RETURNS
642 * Success: Number of scan lines copied
643 * Failure: 0
645 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
646 UINT lines, LPCVOID bits, const BITMAPINFO *info,
647 UINT coloruse )
649 BITMAPOBJ *bitmap;
650 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
651 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
652 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
653 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
654 INT result = 0;
655 DWORD err;
656 struct gdi_image_bits src_bits;
657 struct bitblt_coords src, dst;
658 INT src_to_dst_offset;
659 HRGN clip = 0;
660 const struct gdi_dc_funcs *funcs;
662 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ) || coloruse > DIB_PAL_COLORS)
664 SetLastError( ERROR_INVALID_PARAMETER );
665 return 0;
667 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
669 DWORD *masks = (DWORD *)src_info->bmiColors;
670 if (!masks[0] || !masks[1] || !masks[2])
672 SetLastError( ERROR_INVALID_PARAMETER );
673 return 0;
677 src_bits.ptr = (void *)bits;
678 src_bits.is_copy = FALSE;
679 src_bits.free = NULL;
680 src_bits.param = NULL;
682 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
684 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
686 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
688 if (lines == 0) goto done;
689 else lines = src_info->bmiHeader.biHeight;
690 startscan = 0;
692 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
695 dst.visrect.left = 0;
696 dst.visrect.top = 0;
697 dst.visrect.right = bitmap->bitmap.bmWidth;
698 dst.visrect.bottom = bitmap->bitmap.bmHeight;
700 src.visrect.left = 0;
701 src.visrect.top = 0;
702 src.visrect.right = src_info->bmiHeader.biWidth;
703 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
705 if (src_info->bmiHeader.biHeight > 0)
707 src_to_dst_offset = -startscan;
708 lines = min( lines, src.visrect.bottom - startscan );
709 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
711 else
713 src_to_dst_offset = src.visrect.bottom - lines - startscan;
714 /* Unlike the bottom-up case, Windows doesn't limit lines. */
715 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
718 funcs = get_bitmap_funcs( bitmap );
720 result = lines;
722 offset_rect( &src.visrect, 0, src_to_dst_offset );
723 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
724 src.visrect = dst.visrect;
725 offset_rect( &src.visrect, 0, -src_to_dst_offset );
727 src.x = src.visrect.left;
728 src.y = src.visrect.top;
729 src.width = src.visrect.right - src.visrect.left;
730 src.height = src.visrect.bottom - src.visrect.top;
732 dst.x = dst.visrect.left;
733 dst.y = dst.visrect.top;
734 dst.width = dst.visrect.right - dst.visrect.left;
735 dst.height = dst.visrect.bottom - dst.visrect.top;
737 copy_bitmapinfo( dst_info, src_info );
739 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
740 if (err == ERROR_BAD_FORMAT)
742 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
743 if (!err) err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
745 if(err) result = 0;
747 done:
748 if (src_bits.free) src_bits.free( &src_bits );
749 if (clip) DeleteObject( clip );
750 GDI_ReleaseObj( hbitmap );
751 return result;
755 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
756 INT x_src, INT y_src, UINT startscan, UINT lines,
757 const void *bits, BITMAPINFO *src_info, UINT coloruse )
759 DC *dc = get_nulldrv_dc( dev );
760 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
761 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
762 struct bitblt_coords src, dst;
763 struct gdi_image_bits src_bits;
764 HRGN clip = 0;
765 DWORD err;
766 UINT height;
767 BOOL top_down;
768 POINT pt;
769 RECT rect;
771 top_down = (src_info->bmiHeader.biHeight < 0);
772 height = abs( src_info->bmiHeader.biHeight );
774 src_bits.ptr = (void *)bits;
775 src_bits.is_copy = FALSE;
776 src_bits.free = NULL;
778 if (!lines) return 0;
779 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
781 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
783 startscan = 0;
784 lines = height;
785 src_info->bmiHeader.biWidth = x_src + cx;
786 src_info->bmiHeader.biHeight = y_src + cy;
787 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
788 src.x = x_src;
789 src.y = 0;
790 src.width = cx;
791 src.height = cy;
792 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
794 else
796 if (startscan >= height) return 0;
797 if (!top_down && lines > height - startscan) lines = height - startscan;
799 /* map src to top-down coordinates with startscan as origin */
800 src.x = x_src;
801 src.y = startscan + lines - (y_src + cy);
802 src.width = cx;
803 src.height = cy;
804 if (src.y > 0)
806 if (!top_down)
808 /* get rid of unnecessary lines */
809 if (src.y >= lines) return 0;
810 lines -= src.y;
811 src.y = 0;
813 else if (src.y >= lines) return lines;
815 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
818 src.visrect.left = src.x;
819 src.visrect.top = src.y;
820 src.visrect.right = src.x + cx;
821 src.visrect.bottom = src.y + cy;
822 rect.left = 0;
823 rect.top = 0;
824 rect.right = src_info->bmiHeader.biWidth;
825 rect.bottom = abs( src_info->bmiHeader.biHeight );
826 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
828 lines = 0;
829 goto done;
832 pt.x = x_dst;
833 pt.y = y_dst;
834 LPtoDP( dev->hdc, &pt, 1 );
835 dst.x = pt.x;
836 dst.y = pt.y;
837 dst.width = cx;
838 dst.height = cy;
839 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
841 rect.left = dst.x;
842 rect.top = dst.y;
843 rect.right = dst.x + cx;
844 rect.bottom = dst.y + cy;
845 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
847 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
848 intersect_rect( &rect, &src.visrect, &dst.visrect );
849 src.visrect = dst.visrect = rect;
850 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
851 if (is_rect_empty( &dst.visrect )) goto done;
852 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
854 dev = GET_DC_PHYSDEV( dc, pPutImage );
855 copy_bitmapinfo( dst_info, src_info );
856 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
857 if (err == ERROR_BAD_FORMAT)
859 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
860 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
862 if (err) lines = 0;
864 done:
865 if (src_bits.free) src_bits.free( &src_bits );
866 if (clip) DeleteObject( clip );
867 return lines;
870 /***********************************************************************
871 * SetDIBitsToDevice (GDI32.@)
873 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
874 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
875 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
876 UINT coloruse )
878 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
879 BITMAPINFO *info = (BITMAPINFO *)buffer;
880 INT ret = 0;
881 DC *dc;
883 if (!bits) return 0;
884 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
886 SetLastError( ERROR_INVALID_PARAMETER );
887 return 0;
890 if ((dc = get_dc_ptr( hdc )))
892 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
893 update_dc( dc );
894 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
895 ySrc, startscan, lines, bits, info, coloruse );
896 release_dc_ptr( dc );
898 return ret;
901 /***********************************************************************
902 * SetDIBColorTable (GDI32.@)
904 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
906 DC * dc;
907 UINT result = 0;
908 BITMAPOBJ * bitmap;
910 if (!(dc = get_dc_ptr( hdc ))) return 0;
912 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
914 /* Check if currently selected bitmap is a DIB */
915 if (bitmap->color_table)
917 if (startpos < bitmap->dib->dsBmih.biClrUsed)
919 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
920 memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
923 GDI_ReleaseObj( dc->hBitmap );
925 if (result) /* update colors of selected objects */
927 SetTextColor( hdc, dc->textColor );
928 SetBkColor( hdc, dc->backgroundColor );
929 SelectObject( hdc, dc->hPen );
930 SelectObject( hdc, dc->hBrush );
933 release_dc_ptr( dc );
934 return result;
938 /***********************************************************************
939 * GetDIBColorTable (GDI32.@)
941 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
943 DC * dc;
944 BITMAPOBJ *bitmap;
945 UINT result = 0;
947 if (!(dc = get_dc_ptr( hdc ))) return 0;
949 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
951 /* Check if currently selected bitmap is a DIB */
952 if (bitmap->color_table)
954 if (startpos < bitmap->dib->dsBmih.biClrUsed)
956 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
957 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_565[3] = {0xf800, 0x07e0, 0x001f};
968 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
970 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
972 BITMAPINFOHEADER header;
974 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
975 header.biWidth = bmp->bitmap.bmWidth;
976 header.biHeight = bmp->bitmap.bmHeight;
977 header.biPlanes = 1;
978 header.biBitCount = bmp->bitmap.bmBitsPixel;
980 switch (header.biBitCount)
982 case 16:
983 case 32:
984 header.biCompression = BI_BITFIELDS;
985 break;
986 default:
987 header.biCompression = BI_RGB;
988 break;
991 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
992 header.biXPelsPerMeter = 0;
993 header.biYPelsPerMeter = 0;
994 header.biClrUsed = 0;
995 header.biClrImportant = 0;
997 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
999 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
1001 coreheader->bcWidth = header.biWidth;
1002 coreheader->bcHeight = header.biHeight;
1003 coreheader->bcPlanes = header.biPlanes;
1004 coreheader->bcBitCount = header.biBitCount;
1006 else
1007 info->bmiHeader = header;
1009 return abs(bmp->bitmap.bmHeight);
1012 /************************************************************************
1013 * copy_color_info
1015 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1017 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1019 assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1021 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1023 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1024 if (coloruse == DIB_PAL_COLORS)
1025 memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1026 else
1028 unsigned int i;
1029 for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1031 core->bmciColors[i].rgbtRed = src->bmiColors[i].rgbRed;
1032 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1033 core->bmciColors[i].rgbtBlue = src->bmiColors[i].rgbBlue;
1037 else
1039 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1040 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1042 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1043 /* bitfields are always at bmiColors even in larger structures */
1044 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1045 else if (src->bmiHeader.biClrUsed)
1047 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1048 unsigned int size;
1050 if (coloruse == DIB_PAL_COLORS)
1051 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1052 else
1053 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1054 memcpy( colorptr, src->bmiColors, size );
1059 const RGBQUAD *get_default_color_table( int bpp )
1061 static const RGBQUAD table_1[2] =
1063 { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff }
1065 static const RGBQUAD table_4[16] =
1067 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1068 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x80 },
1069 { 0xc0, 0xc0, 0xc0 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1070 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1072 static const RGBQUAD table_8[256] =
1074 /* first and last 10 entries are the default system palette entries */
1075 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x80 }, { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x80 },
1076 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x80 }, { 0x80, 0x80, 0x00 }, { 0xc0, 0xc0, 0xc0 },
1077 { 0xc0, 0xdc, 0xc0 }, { 0xf0, 0xca, 0xa6 }, { 0x00, 0x20, 0x40 }, { 0x00, 0x20, 0x60 },
1078 { 0x00, 0x20, 0x80 }, { 0x00, 0x20, 0xa0 }, { 0x00, 0x20, 0xc0 }, { 0x00, 0x20, 0xe0 },
1079 { 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x20 }, { 0x00, 0x40, 0x40 }, { 0x00, 0x40, 0x60 },
1080 { 0x00, 0x40, 0x80 }, { 0x00, 0x40, 0xa0 }, { 0x00, 0x40, 0xc0 }, { 0x00, 0x40, 0xe0 },
1081 { 0x00, 0x60, 0x00 }, { 0x00, 0x60, 0x20 }, { 0x00, 0x60, 0x40 }, { 0x00, 0x60, 0x60 },
1082 { 0x00, 0x60, 0x80 }, { 0x00, 0x60, 0xa0 }, { 0x00, 0x60, 0xc0 }, { 0x00, 0x60, 0xe0 },
1083 { 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x20 }, { 0x00, 0x80, 0x40 }, { 0x00, 0x80, 0x60 },
1084 { 0x00, 0x80, 0x80 }, { 0x00, 0x80, 0xa0 }, { 0x00, 0x80, 0xc0 }, { 0x00, 0x80, 0xe0 },
1085 { 0x00, 0xa0, 0x00 }, { 0x00, 0xa0, 0x20 }, { 0x00, 0xa0, 0x40 }, { 0x00, 0xa0, 0x60 },
1086 { 0x00, 0xa0, 0x80 }, { 0x00, 0xa0, 0xa0 }, { 0x00, 0xa0, 0xc0 }, { 0x00, 0xa0, 0xe0 },
1087 { 0x00, 0xc0, 0x00 }, { 0x00, 0xc0, 0x20 }, { 0x00, 0xc0, 0x40 }, { 0x00, 0xc0, 0x60 },
1088 { 0x00, 0xc0, 0x80 }, { 0x00, 0xc0, 0xa0 }, { 0x00, 0xc0, 0xc0 }, { 0x00, 0xc0, 0xe0 },
1089 { 0x00, 0xe0, 0x00 }, { 0x00, 0xe0, 0x20 }, { 0x00, 0xe0, 0x40 }, { 0x00, 0xe0, 0x60 },
1090 { 0x00, 0xe0, 0x80 }, { 0x00, 0xe0, 0xa0 }, { 0x00, 0xe0, 0xc0 }, { 0x00, 0xe0, 0xe0 },
1091 { 0x40, 0x00, 0x00 }, { 0x40, 0x00, 0x20 }, { 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x60 },
1092 { 0x40, 0x00, 0x80 }, { 0x40, 0x00, 0xa0 }, { 0x40, 0x00, 0xc0 }, { 0x40, 0x00, 0xe0 },
1093 { 0x40, 0x20, 0x00 }, { 0x40, 0x20, 0x20 }, { 0x40, 0x20, 0x40 }, { 0x40, 0x20, 0x60 },
1094 { 0x40, 0x20, 0x80 }, { 0x40, 0x20, 0xa0 }, { 0x40, 0x20, 0xc0 }, { 0x40, 0x20, 0xe0 },
1095 { 0x40, 0x40, 0x00 }, { 0x40, 0x40, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x40, 0x40, 0x60 },
1096 { 0x40, 0x40, 0x80 }, { 0x40, 0x40, 0xa0 }, { 0x40, 0x40, 0xc0 }, { 0x40, 0x40, 0xe0 },
1097 { 0x40, 0x60, 0x00 }, { 0x40, 0x60, 0x20 }, { 0x40, 0x60, 0x40 }, { 0x40, 0x60, 0x60 },
1098 { 0x40, 0x60, 0x80 }, { 0x40, 0x60, 0xa0 }, { 0x40, 0x60, 0xc0 }, { 0x40, 0x60, 0xe0 },
1099 { 0x40, 0x80, 0x00 }, { 0x40, 0x80, 0x20 }, { 0x40, 0x80, 0x40 }, { 0x40, 0x80, 0x60 },
1100 { 0x40, 0x80, 0x80 }, { 0x40, 0x80, 0xa0 }, { 0x40, 0x80, 0xc0 }, { 0x40, 0x80, 0xe0 },
1101 { 0x40, 0xa0, 0x00 }, { 0x40, 0xa0, 0x20 }, { 0x40, 0xa0, 0x40 }, { 0x40, 0xa0, 0x60 },
1102 { 0x40, 0xa0, 0x80 }, { 0x40, 0xa0, 0xa0 }, { 0x40, 0xa0, 0xc0 }, { 0x40, 0xa0, 0xe0 },
1103 { 0x40, 0xc0, 0x00 }, { 0x40, 0xc0, 0x20 }, { 0x40, 0xc0, 0x40 }, { 0x40, 0xc0, 0x60 },
1104 { 0x40, 0xc0, 0x80 }, { 0x40, 0xc0, 0xa0 }, { 0x40, 0xc0, 0xc0 }, { 0x40, 0xc0, 0xe0 },
1105 { 0x40, 0xe0, 0x00 }, { 0x40, 0xe0, 0x20 }, { 0x40, 0xe0, 0x40 }, { 0x40, 0xe0, 0x60 },
1106 { 0x40, 0xe0, 0x80 }, { 0x40, 0xe0, 0xa0 }, { 0x40, 0xe0, 0xc0 }, { 0x40, 0xe0, 0xe0 },
1107 { 0x80, 0x00, 0x00 }, { 0x80, 0x00, 0x20 }, { 0x80, 0x00, 0x40 }, { 0x80, 0x00, 0x60 },
1108 { 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xa0 }, { 0x80, 0x00, 0xc0 }, { 0x80, 0x00, 0xe0 },
1109 { 0x80, 0x20, 0x00 }, { 0x80, 0x20, 0x20 }, { 0x80, 0x20, 0x40 }, { 0x80, 0x20, 0x60 },
1110 { 0x80, 0x20, 0x80 }, { 0x80, 0x20, 0xa0 }, { 0x80, 0x20, 0xc0 }, { 0x80, 0x20, 0xe0 },
1111 { 0x80, 0x40, 0x00 }, { 0x80, 0x40, 0x20 }, { 0x80, 0x40, 0x40 }, { 0x80, 0x40, 0x60 },
1112 { 0x80, 0x40, 0x80 }, { 0x80, 0x40, 0xa0 }, { 0x80, 0x40, 0xc0 }, { 0x80, 0x40, 0xe0 },
1113 { 0x80, 0x60, 0x00 }, { 0x80, 0x60, 0x20 }, { 0x80, 0x60, 0x40 }, { 0x80, 0x60, 0x60 },
1114 { 0x80, 0x60, 0x80 }, { 0x80, 0x60, 0xa0 }, { 0x80, 0x60, 0xc0 }, { 0x80, 0x60, 0xe0 },
1115 { 0x80, 0x80, 0x00 }, { 0x80, 0x80, 0x20 }, { 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x60 },
1116 { 0x80, 0x80, 0x80 }, { 0x80, 0x80, 0xa0 }, { 0x80, 0x80, 0xc0 }, { 0x80, 0x80, 0xe0 },
1117 { 0x80, 0xa0, 0x00 }, { 0x80, 0xa0, 0x20 }, { 0x80, 0xa0, 0x40 }, { 0x80, 0xa0, 0x60 },
1118 { 0x80, 0xa0, 0x80 }, { 0x80, 0xa0, 0xa0 }, { 0x80, 0xa0, 0xc0 }, { 0x80, 0xa0, 0xe0 },
1119 { 0x80, 0xc0, 0x00 }, { 0x80, 0xc0, 0x20 }, { 0x80, 0xc0, 0x40 }, { 0x80, 0xc0, 0x60 },
1120 { 0x80, 0xc0, 0x80 }, { 0x80, 0xc0, 0xa0 }, { 0x80, 0xc0, 0xc0 }, { 0x80, 0xc0, 0xe0 },
1121 { 0x80, 0xe0, 0x00 }, { 0x80, 0xe0, 0x20 }, { 0x80, 0xe0, 0x40 }, { 0x80, 0xe0, 0x60 },
1122 { 0x80, 0xe0, 0x80 }, { 0x80, 0xe0, 0xa0 }, { 0x80, 0xe0, 0xc0 }, { 0x80, 0xe0, 0xe0 },
1123 { 0xc0, 0x00, 0x00 }, { 0xc0, 0x00, 0x20 }, { 0xc0, 0x00, 0x40 }, { 0xc0, 0x00, 0x60 },
1124 { 0xc0, 0x00, 0x80 }, { 0xc0, 0x00, 0xa0 }, { 0xc0, 0x00, 0xc0 }, { 0xc0, 0x00, 0xe0 },
1125 { 0xc0, 0x20, 0x00 }, { 0xc0, 0x20, 0x20 }, { 0xc0, 0x20, 0x40 }, { 0xc0, 0x20, 0x60 },
1126 { 0xc0, 0x20, 0x80 }, { 0xc0, 0x20, 0xa0 }, { 0xc0, 0x20, 0xc0 }, { 0xc0, 0x20, 0xe0 },
1127 { 0xc0, 0x40, 0x00 }, { 0xc0, 0x40, 0x20 }, { 0xc0, 0x40, 0x40 }, { 0xc0, 0x40, 0x60 },
1128 { 0xc0, 0x40, 0x80 }, { 0xc0, 0x40, 0xa0 }, { 0xc0, 0x40, 0xc0 }, { 0xc0, 0x40, 0xe0 },
1129 { 0xc0, 0x60, 0x00 }, { 0xc0, 0x60, 0x20 }, { 0xc0, 0x60, 0x40 }, { 0xc0, 0x60, 0x60 },
1130 { 0xc0, 0x60, 0x80 }, { 0xc0, 0x60, 0xa0 }, { 0xc0, 0x60, 0xc0 }, { 0xc0, 0x60, 0xe0 },
1131 { 0xc0, 0x80, 0x00 }, { 0xc0, 0x80, 0x20 }, { 0xc0, 0x80, 0x40 }, { 0xc0, 0x80, 0x60 },
1132 { 0xc0, 0x80, 0x80 }, { 0xc0, 0x80, 0xa0 }, { 0xc0, 0x80, 0xc0 }, { 0xc0, 0x80, 0xe0 },
1133 { 0xc0, 0xa0, 0x00 }, { 0xc0, 0xa0, 0x20 }, { 0xc0, 0xa0, 0x40 }, { 0xc0, 0xa0, 0x60 },
1134 { 0xc0, 0xa0, 0x80 }, { 0xc0, 0xa0, 0xa0 }, { 0xc0, 0xa0, 0xc0 }, { 0xc0, 0xa0, 0xe0 },
1135 { 0xc0, 0xc0, 0x00 }, { 0xc0, 0xc0, 0x20 }, { 0xc0, 0xc0, 0x40 }, { 0xc0, 0xc0, 0x60 },
1136 { 0xc0, 0xc0, 0x80 }, { 0xc0, 0xc0, 0xa0 }, { 0xf0, 0xfb, 0xff }, { 0xa4, 0xa0, 0xa0 },
1137 { 0x80, 0x80, 0x80 }, { 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff },
1138 { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff },
1141 switch (bpp)
1143 case 1: return table_1;
1144 case 4: return table_4;
1145 case 8: return table_8;
1146 default: return NULL;
1150 void fill_default_color_table( BITMAPINFO *info )
1152 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1153 memcpy( info->bmiColors, get_default_color_table( info->bmiHeader.biBitCount ),
1154 info->bmiHeader.biClrUsed * sizeof(RGBQUAD) );
1157 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1159 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1160 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1161 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1162 info->bmiHeader.biPlanes = 1;
1163 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1164 info->bmiHeader.biCompression = BI_RGB;
1165 info->bmiHeader.biXPelsPerMeter = 0;
1166 info->bmiHeader.biYPelsPerMeter = 0;
1167 info->bmiHeader.biClrUsed = 0;
1168 info->bmiHeader.biClrImportant = 0;
1171 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1173 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1174 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1175 unsigned int info_size;
1177 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1179 info_size = get_dib_info_size( info, usage );
1180 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + info->bmiHeader.biSizeImage )))
1182 memcpy( ret, info, info_size );
1183 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size( src_info, usage ),
1184 info->bmiHeader.biSizeImage );
1186 return ret;
1189 /******************************************************************************
1190 * GetDIBits [GDI32.@]
1192 * Retrieves bits of bitmap and copies to buffer.
1194 * RETURNS
1195 * Success: Number of scan lines copied from bitmap
1196 * Failure: 0
1198 INT WINAPI GetDIBits(
1199 HDC hdc, /* [in] Handle to device context */
1200 HBITMAP hbitmap, /* [in] Handle to bitmap */
1201 UINT startscan, /* [in] First scan line to set in dest bitmap */
1202 UINT lines, /* [in] Number of scan lines to copy */
1203 LPVOID bits, /* [out] Address of array for bitmap bits */
1204 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1205 UINT coloruse) /* [in] RGB or palette index */
1207 DC * dc;
1208 BITMAPOBJ * bmp;
1209 int i, dst_to_src_offset, ret = 0;
1210 DWORD err;
1211 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1212 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1213 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1214 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1215 const struct gdi_dc_funcs *funcs;
1216 struct gdi_image_bits src_bits;
1217 struct bitblt_coords src, dst;
1218 BOOL empty_rect = FALSE;
1220 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1221 own copy and transfer the colour info back at the end */
1222 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1223 if (coloruse > DIB_PAL_COLORS) return 0;
1224 if (bits &&
1225 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1226 return 0;
1227 dst_info->bmiHeader.biClrUsed = 0;
1228 dst_info->bmiHeader.biClrImportant = 0;
1230 if (!(dc = get_dc_ptr( hdc )))
1232 SetLastError( ERROR_INVALID_PARAMETER );
1233 return 0;
1235 update_dc( dc );
1236 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1238 release_dc_ptr( dc );
1239 return 0;
1242 funcs = get_bitmap_funcs( bmp );
1244 src.visrect.left = 0;
1245 src.visrect.top = 0;
1246 src.visrect.right = bmp->bitmap.bmWidth;
1247 src.visrect.bottom = bmp->bitmap.bmHeight;
1249 dst.visrect.left = 0;
1250 dst.visrect.top = 0;
1251 dst.visrect.right = dst_info->bmiHeader.biWidth;
1252 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1254 if (lines == 0 || startscan >= dst.visrect.bottom)
1255 bits = NULL;
1257 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1259 ret = fill_query_info( info, bmp );
1260 goto done;
1263 /* validate parameters */
1265 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1266 if (dst_info->bmiHeader.biHeight == 0) goto done;
1268 switch (dst_info->bmiHeader.biCompression)
1270 case BI_RLE4:
1271 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1272 if (dst_info->bmiHeader.biHeight < 0) goto done;
1273 if (bits) goto done; /* can't retrieve compressed bits */
1274 break;
1275 case BI_RLE8:
1276 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1277 if (dst_info->bmiHeader.biHeight < 0) goto done;
1278 if (bits) goto done; /* can't retrieve compressed bits */
1279 break;
1280 case BI_BITFIELDS:
1281 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1282 /* fall through */
1283 case BI_RGB:
1284 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1285 if (dst_info->bmiHeader.biBitCount == 1) break;
1286 if (dst_info->bmiHeader.biBitCount == 4) break;
1287 if (dst_info->bmiHeader.biBitCount == 8) break;
1288 if (dst_info->bmiHeader.biBitCount == 16) break;
1289 if (dst_info->bmiHeader.biBitCount == 24) break;
1290 if (dst_info->bmiHeader.biBitCount == 32) break;
1291 /* fall through */
1292 default:
1293 goto done;
1296 if (bits)
1298 if (dst_info->bmiHeader.biHeight > 0)
1300 dst_to_src_offset = -startscan;
1301 lines = min( lines, dst.visrect.bottom - startscan );
1302 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1304 else
1306 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1307 if (dst_to_src_offset < 0)
1309 dst_to_src_offset = 0;
1310 lines = dst.visrect.bottom - startscan;
1312 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1315 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1316 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1317 dst.visrect = src.visrect;
1318 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1320 if (dst_info->bmiHeader.biHeight > 0)
1322 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1324 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1325 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1326 memset( bits, 0, pad_bytes );
1327 bits = (char *)bits + pad_bytes;
1330 else
1332 if (dst.visrect.bottom < lines)
1334 int pad_lines = lines - dst.visrect.bottom;
1335 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1336 int pad_bytes = pad_lines * stride;
1337 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1341 if (empty_rect) bits = NULL;
1343 src.x = src.visrect.left;
1344 src.y = src.visrect.top;
1345 src.width = src.visrect.right - src.visrect.left;
1346 src.height = src.visrect.bottom - src.visrect.top;
1348 lines = src.height;
1351 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1353 if (err) goto done;
1355 /* fill out the src colour table, if it needs one */
1356 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1357 fill_default_color_table( src_info );
1359 /* if the src and dst are the same depth, copy the colour info across */
1360 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1362 switch (src_info->bmiHeader.biBitCount)
1364 case 16:
1365 if (src_info->bmiHeader.biCompression == BI_RGB)
1367 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1368 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1370 break;
1371 case 32:
1372 if (src_info->bmiHeader.biCompression == BI_RGB)
1374 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1375 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1377 break;
1379 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1380 copy_color_info( dst_info, src_info, coloruse );
1382 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1384 if( coloruse == DIB_PAL_COLORS )
1386 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1388 else
1390 fill_default_color_table( dst_info );
1394 if (bits)
1396 if(dst_info->bmiHeader.biHeight > 0)
1397 dst_info->bmiHeader.biHeight = src.height;
1398 else
1399 dst_info->bmiHeader.biHeight = -src.height;
1401 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1402 if (src_bits.free) src_bits.free( &src_bits );
1403 ret = lines;
1405 else
1406 ret = empty_rect ? FALSE : TRUE;
1408 if (coloruse == DIB_PAL_COLORS)
1410 WORD *index = (WORD *)dst_info->bmiColors;
1411 for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1412 *index = i;
1415 copy_color_info( info, dst_info, coloruse );
1416 if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1418 done:
1419 release_dc_ptr( dc );
1420 GDI_ReleaseObj( hbitmap );
1421 return ret;
1425 /***********************************************************************
1426 * CreateDIBitmap (GDI32.@)
1428 * Creates a DDB (device dependent bitmap) from a DIB.
1429 * The DDB will have the same color depth as the reference DC.
1431 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1432 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1433 UINT coloruse )
1435 BITMAPINFOHEADER info;
1436 HBITMAP handle;
1437 LONG height;
1439 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1440 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1441 if (coloruse > DIB_PAL_COLORS + 1) return 0;
1442 if (info.biWidth < 0) return 0;
1444 /* Top-down DIBs have a negative height */
1445 height = abs( info.biHeight );
1447 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1448 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1449 info.biBitCount, info.biCompression);
1451 if (hdc == NULL)
1452 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1453 else
1454 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1456 if (handle)
1458 if (init & CBM_INIT)
1460 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1462 DeleteObject( handle );
1463 handle = 0;
1468 return handle;
1472 /***********************************************************************
1473 * CreateDIBSection (GDI32.@)
1475 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1476 VOID **bits, HANDLE section, DWORD offset)
1478 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1479 BITMAPINFO *info = (BITMAPINFO *)buffer;
1480 HBITMAP ret = 0;
1481 DIBSECTION *dib;
1482 BITMAPOBJ *bmp;
1483 void *mapBits = NULL;
1485 if (bits) *bits = NULL;
1486 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1487 if (usage > DIB_PAL_COLORS) return 0;
1488 if (info->bmiHeader.biPlanes != 1)
1490 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1491 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1494 if (!(bmp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*bmp) ))) return 0;
1495 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) goto error;
1497 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1498 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1499 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1500 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1501 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1503 dib->dsBm.bmType = 0;
1504 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1505 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1506 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1507 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1508 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1509 dib->dsBm.bmBits = NULL;
1510 dib->dsBmih = info->bmiHeader;
1512 bmp->funcs = &dib_driver;
1513 bmp->dib = dib;
1515 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1517 if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1518 goto error;
1519 dib->dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1520 if (!(bmp->color_table = HeapAlloc( GetProcessHeap(), 0, dib->dsBmih.biClrUsed*sizeof(RGBQUAD) )))
1521 goto error;
1522 memcpy( bmp->color_table, info->bmiColors, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) );
1525 /* set dsBitfields values */
1526 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1528 dib->dsBmih.biCompression = BI_BITFIELDS;
1529 dib->dsBitfields[0] = 0x7c00;
1530 dib->dsBitfields[1] = 0x03e0;
1531 dib->dsBitfields[2] = 0x001f;
1533 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1535 if (usage == DIB_PAL_COLORS) goto error;
1536 dib->dsBitfields[0] = *(const DWORD *)info->bmiColors;
1537 dib->dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1538 dib->dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1539 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1541 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1543 /* get storage location for DIB bits */
1545 if (section)
1547 SYSTEM_INFO SystemInfo;
1548 DWORD mapOffset;
1549 INT mapSize;
1551 GetSystemInfo( &SystemInfo );
1552 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1553 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1554 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1555 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1557 else
1559 offset = 0;
1560 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1561 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1563 dib->dshSection = section;
1564 dib->dsOffset = offset;
1566 if (!dib->dsBm.bmBits) goto error;
1568 bmp->bitmap = dib->dsBm;
1569 bmp->bitmap.bmWidthBytes = get_bitmap_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1570 bmp->bitmap.bmBits = NULL;
1572 if (!(ret = alloc_gdi_handle( &bmp->header, OBJ_BITMAP, &dib_funcs ))) goto error;
1574 if (bits) *bits = dib->dsBm.bmBits;
1575 return ret;
1577 error:
1578 if (section) UnmapViewOfFile( mapBits );
1579 else VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1580 HeapFree( GetProcessHeap(), 0, bmp->color_table );
1581 HeapFree( GetProcessHeap(), 0, dib );
1582 HeapFree( GetProcessHeap(), 0, bmp );
1583 return 0;
1587 /***********************************************************************
1588 * DIB_SelectObject
1590 static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
1592 HGDIOBJ ret;
1593 BITMAPOBJ *bitmap;
1594 DC *dc;
1595 PHYSDEV physdev = NULL, old_physdev = NULL, pathdev = NULL;
1597 if (!(dc = get_dc_ptr( hdc ))) return 0;
1599 if (GetObjectType( hdc ) != OBJ_MEMDC)
1601 ret = 0;
1602 goto done;
1604 ret = dc->hBitmap;
1605 if (handle == dc->hBitmap) goto done; /* nothing to do */
1607 if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
1609 ret = 0;
1610 goto done;
1613 if (bitmap->header.selcount)
1615 WARN( "Bitmap already selected in another DC\n" );
1616 GDI_ReleaseObj( handle );
1617 ret = 0;
1618 goto done;
1621 if (dc->physDev->funcs == &path_driver) pathdev = pop_dc_driver( &dc->physDev );
1623 old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
1624 physdev = dc->dibdrv;
1625 if (old_physdev != dc->dibdrv)
1627 if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs );
1628 else
1630 if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) goto done;
1631 dc->dibdrv = physdev = dc->physDev;
1635 if (!physdev->funcs->pSelectBitmap( physdev, handle ))
1637 GDI_ReleaseObj( handle );
1638 ret = 0;
1640 else
1642 dc->hBitmap = handle;
1643 GDI_inc_ref_count( handle );
1644 dc->dirty = 0;
1645 dc->vis_rect.left = 0;
1646 dc->vis_rect.top = 0;
1647 dc->vis_rect.right = bitmap->bitmap.bmWidth;
1648 dc->vis_rect.bottom = bitmap->bitmap.bmHeight;
1649 GDI_ReleaseObj( handle );
1650 DC_InitDC( dc );
1651 GDI_dec_ref_count( ret );
1654 done:
1655 if(!ret)
1657 if (old_physdev && old_physdev != dc->dibdrv) pop_dc_driver( &dc->physDev );
1659 if (pathdev) push_dc_driver( &dc->physDev, pathdev, pathdev->funcs );
1660 release_dc_ptr( dc );
1661 return ret;
1665 /***********************************************************************
1666 * DIB_GetObject
1668 static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
1670 INT ret = 0;
1671 BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
1673 if (!bmp) return 0;
1675 if (!buffer) ret = sizeof(BITMAP);
1676 else if (count >= sizeof(DIBSECTION))
1678 DIBSECTION *dib = buffer;
1679 *dib = *bmp->dib;
1680 dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
1681 ret = sizeof(DIBSECTION);
1683 else if (count >= sizeof(BITMAP))
1685 BITMAP *bitmap = buffer;
1686 *bitmap = bmp->dib->dsBm;
1687 ret = sizeof(BITMAP);
1690 GDI_ReleaseObj( handle );
1691 return ret;
1695 /***********************************************************************
1696 * DIB_DeleteObject
1698 static BOOL DIB_DeleteObject( HGDIOBJ handle )
1700 BITMAPOBJ *bmp;
1702 if (!(bmp = free_gdi_handle( handle ))) return FALSE;
1704 if (bmp->dib->dshSection)
1706 SYSTEM_INFO SystemInfo;
1707 GetSystemInfo( &SystemInfo );
1708 UnmapViewOfFile( (char *)bmp->dib->dsBm.bmBits -
1709 (bmp->dib->dsOffset % SystemInfo.dwAllocationGranularity) );
1711 else VirtualFree( bmp->dib->dsBm.bmBits, 0, MEM_RELEASE );
1713 HeapFree(GetProcessHeap(), 0, bmp->dib);
1714 HeapFree(GetProcessHeap(), 0, bmp->color_table);
1715 return HeapFree( GetProcessHeap(), 0, bmp );