gdi32: Remove an unneeded level of indentation.
[wine.git] / dlls / gdi32 / dib.c
blob65e9e1b8ea7fa0bb0ad25fffa8098ba62f53c276
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 /***********************************************************************
76 * bitmap_info_size
78 * Return the size of the bitmap info structure including color table.
80 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
82 unsigned int colors, size, masks = 0;
84 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
86 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
87 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
88 return sizeof(BITMAPCOREHEADER) + colors *
89 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
91 else /* assume BITMAPINFOHEADER */
93 colors = get_dib_num_of_colors( info );
94 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
95 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
96 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
100 /*******************************************************************************************
101 * Verify that the DIB parameters are valid.
103 static BOOL is_valid_dib_format( const BITMAPINFOHEADER *info, BOOL allow_compression )
105 if (info->biWidth <= 0) return FALSE;
106 if (info->biHeight == 0) return FALSE;
108 if (allow_compression && (info->biCompression == BI_RLE4 || info->biCompression == BI_RLE8))
110 if (info->biHeight < 0) return FALSE;
111 if (!info->biSizeImage) return FALSE;
112 return info->biBitCount == (info->biCompression == BI_RLE4 ? 4 : 8);
115 if (!info->biPlanes) return FALSE;
117 switch (info->biBitCount)
119 case 1:
120 case 4:
121 case 8:
122 case 24:
123 return (info->biCompression == BI_RGB);
124 case 16:
125 case 32:
126 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
127 default:
128 return FALSE;
132 /*******************************************************************************************
133 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
135 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
137 if (!info) return FALSE;
139 if (info->biSize == sizeof(BITMAPCOREHEADER))
141 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
142 dst->biWidth = core->bcWidth;
143 dst->biHeight = core->bcHeight;
144 dst->biPlanes = core->bcPlanes;
145 dst->biBitCount = core->bcBitCount;
146 dst->biCompression = BI_RGB;
147 dst->biXPelsPerMeter = 0;
148 dst->biYPelsPerMeter = 0;
149 dst->biClrUsed = 0;
150 dst->biClrImportant = 0;
152 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
154 *dst = *info;
156 else
158 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
159 return FALSE;
162 dst->biSize = sizeof(*dst);
163 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
164 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
165 return TRUE;
168 /*******************************************************************************************
169 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
171 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
172 UINT coloruse, BOOL allow_compression )
174 void *src_colors;
175 unsigned int colors;
177 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
178 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
180 src_colors = (char *)info + info->bmiHeader.biSize;
181 colors = get_dib_num_of_colors( dst );
183 if (info->bmiHeader.biCompression == BI_BITFIELDS)
185 /* bitfields are always at bmiColors even in larger structures */
186 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
188 else if (colors)
190 if (coloruse == DIB_PAL_COLORS)
191 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
192 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
193 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
194 else
196 unsigned int i;
197 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
198 for (i = 0; i < colors; i++)
200 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
201 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
202 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
203 dst->bmiColors[i].rgbReserved = 0;
207 return TRUE;
210 static int fill_color_table_from_palette( BITMAPINFO *info, DC *dc )
212 PALETTEENTRY palEntry[256];
213 int i, colors = get_dib_num_of_colors( info );
215 if (!colors) return 0;
217 memset( palEntry, 0, sizeof(palEntry) );
218 if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
219 return 0;
221 for (i = 0; i < colors; i++)
223 info->bmiColors[i].rgbRed = palEntry[i].peRed;
224 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
225 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
226 info->bmiColors[i].rgbReserved = 0;
229 return colors;
232 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
234 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
235 const int bpp = info->bmiHeader.biBitCount;
237 if (height > 0)
238 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
239 else
240 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
243 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
245 int i = 0;
246 int left, right;
247 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
248 HRGN run = NULL;
249 BYTE skip, num, data;
250 BYTE *out_bits, *in_bits = bits->ptr;
252 *clip = NULL;
254 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
256 out_bits = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ) );
257 *clip = CreateRectRgn( 0, 0, 0, 0 );
258 run = CreateRectRgn( 0, 0, 0, 0 );
259 if (!out_bits || !*clip || !run) goto fail;
261 x = left = right = 0;
262 y = height - 1;
264 while (i < info->bmiHeader.biSizeImage - 1)
266 num = in_bits[i];
267 data = in_bits[i + 1];
268 i += 2;
270 if (num)
272 if (x + num > width) num = width - x;
273 if (num)
275 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
276 if (info->bmiHeader.biBitCount == 8)
277 memset( out_ptr, s, num );
278 else
280 if(x & 1)
282 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
283 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
284 out_ptr++;
285 x++;
286 num--;
288 /* this will write one too many if num is odd, but that doesn't matter */
289 if (num) memset( out_ptr, s, (num + 1) / 2 );
292 x += num;
293 right = x;
295 else
297 if (data < 3)
299 if(left != right)
301 SetRectRgn( run, left, y, right, y + 1 );
302 CombineRgn( *clip, run, *clip, RGN_OR );
304 switch (data)
306 case 0: /* eol */
307 left = right = x = 0;
308 y--;
309 if(y < 0) goto done;
310 break;
312 case 1: /* eod */
313 goto done;
315 case 2: /* delta */
316 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
317 x += in_bits[i];
318 if (x > width) x = width;
319 left = right = x;
320 y -= in_bits[i + 1];
321 if(y < 0) goto done;
322 i += 2;
325 else /* data bytes of data */
327 num = data;
328 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
329 if (skip > info->bmiHeader.biSizeImage - i) goto done;
330 skip = (skip + 1) & ~1;
331 if (x + num > width) num = width - x;
332 if (num)
334 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
335 if (info->bmiHeader.biBitCount == 8)
336 memcpy( out_ptr, in_bits + i, num );
337 else
339 if(x & 1)
341 const BYTE *in_ptr = in_bits + i;
342 for ( ; num; num--, x++)
344 if (x & 1)
346 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
347 out_ptr++;
349 else
350 *out_ptr = (*in_ptr++ << 4) & 0xf0;
353 else
354 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
357 x += num;
358 right = x;
359 i += skip;
364 done:
365 DeleteObject( run );
366 if (bits->free) bits->free( bits );
368 bits->ptr = out_bits;
369 bits->is_copy = TRUE;
370 bits->free = free_heap_bits;
372 return TRUE;
374 fail:
375 if (run) DeleteObject( run );
376 if (*clip) DeleteObject( *clip );
377 HeapFree( GetProcessHeap(), 0, out_bits );
378 return FALSE;
383 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
384 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
385 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
386 const BITMAPINFO *info, UINT coloruse, DWORD rop )
388 DC *dc = get_nulldrv_dc( dev );
389 INT ret;
390 LONG height;
391 HBITMAP hBitmap;
392 HDC hdcMem;
394 /* make sure we have a real implementation for StretchBlt and PutImage */
395 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pPutImage ) == dev)
396 return 0;
398 height = info->bmiHeader.biHeight;
400 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
401 info->bmiHeader.biCompression == BI_RGB)
403 /* Windows appears to have a fast case optimization
404 * that uses the wrong origin for top-down DIBs */
405 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
407 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
409 BITMAP bm;
410 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
411 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
412 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
413 bm.bmBitsPixel == info->bmiHeader.biBitCount && bm.bmPlanes == 1)
415 /* fast path */
416 return SetDIBits( dev->hdc, hBitmap, 0, abs( height ), bits, info, coloruse );
421 hdcMem = CreateCompatibleDC( dev->hdc );
422 hBitmap = CreateCompatibleBitmap( dev->hdc, info->bmiHeader.biWidth, height );
423 SelectObject( hdcMem, hBitmap );
424 if (coloruse == DIB_PAL_COLORS)
425 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
427 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
429 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
430 * contain all the rectangle described in bmiHeader, but only part of it.
431 * This mean that those undescribed pixels must be left untouched.
432 * So, we first copy on a memory bitmap the current content of the
433 * destination rectangle, blit the DIB bits on top of it - hence leaving
434 * the gaps untouched -, and blitting the rectangle back.
435 * This insure that gaps are untouched on the destination rectangle
437 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
438 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
440 ret = SetDIBits( hdcMem, hBitmap, 0, abs( height ), bits, info, coloruse );
441 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
442 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
443 DeleteDC( hdcMem );
444 DeleteObject( hBitmap );
445 return ret;
448 /***********************************************************************
449 * StretchDIBits (GDI32.@)
451 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
452 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
453 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
455 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
456 BITMAPINFO *info = (BITMAPINFO *)buffer;
457 DC *dc;
458 INT ret = 0;
460 if (!bits) return 0;
461 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
463 SetLastError( ERROR_INVALID_PARAMETER );
464 return 0;
467 if ((dc = get_dc_ptr( hdc )))
469 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
470 update_dc( dc );
471 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
472 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
473 release_dc_ptr( dc );
475 return ret;
479 /******************************************************************************
480 * SetDIBits [GDI32.@]
482 * Sets pixels in a bitmap using colors from DIB.
484 * PARAMS
485 * hdc [I] Handle to device context
486 * hbitmap [I] Handle to bitmap
487 * startscan [I] Starting scan line
488 * lines [I] Number of scan lines
489 * bits [I] Array of bitmap bits
490 * info [I] Address of structure with data
491 * coloruse [I] Type of color indexes to use
493 * RETURNS
494 * Success: Number of scan lines copied
495 * Failure: 0
497 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
498 UINT lines, LPCVOID bits, const BITMAPINFO *info,
499 UINT coloruse )
501 DC *dc = get_dc_ptr( hdc );
502 BOOL delete_hdc = FALSE;
503 PHYSDEV physdev;
504 BITMAPOBJ *bitmap;
505 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
506 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
507 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
508 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
509 INT result = 0;
510 DWORD err;
511 struct gdi_image_bits src_bits;
512 struct bitblt_coords src, dst;
513 INT src_to_dst_offset;
514 HRGN clip = 0;
515 const struct gdi_dc_funcs *funcs;
517 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
519 SetLastError( ERROR_INVALID_PARAMETER );
520 return 0;
523 src_bits.ptr = (void *)bits;
524 src_bits.is_copy = FALSE;
525 src_bits.free = NULL;
526 src_bits.param = NULL;
528 if (coloruse == DIB_RGB_COLORS && !dc)
530 hdc = CreateCompatibleDC(0);
531 dc = get_dc_ptr( hdc );
532 delete_hdc = TRUE;
535 if (!dc) return 0;
537 update_dc( dc );
539 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
541 release_dc_ptr( dc );
542 if (delete_hdc) DeleteDC(hdc);
543 return 0;
546 if (coloruse == DIB_PAL_COLORS)
547 if (!fill_color_table_from_palette( src_info, dc )) goto done;
549 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
551 if (lines == 0) goto done;
552 else lines = src_info->bmiHeader.biHeight;
553 startscan = 0;
555 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
558 dst.visrect.left = 0;
559 dst.visrect.top = 0;
560 dst.visrect.right = bitmap->bitmap.bmWidth;
561 dst.visrect.bottom = bitmap->bitmap.bmHeight;
563 src.visrect.left = 0;
564 src.visrect.top = 0;
565 src.visrect.right = src_info->bmiHeader.biWidth;
566 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
568 if (src_info->bmiHeader.biHeight > 0)
570 src_to_dst_offset = -startscan;
571 lines = min( lines, src.visrect.bottom - startscan );
572 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
574 else
576 src_to_dst_offset = src.visrect.bottom - lines - startscan;
577 /* Unlike the bottom-up case, Windows doesn't limit lines. */
578 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
581 /* Hack to ensure we don't get the nulldrv if the bmp hasn't been selected
582 into a dc yet */
583 physdev = GET_DC_PHYSDEV( dc, pCreateBitmap );
584 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) goto done;
586 funcs = get_bitmap_funcs( bitmap );
588 result = lines;
590 offset_rect( &src.visrect, 0, src_to_dst_offset );
591 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
592 src.visrect = dst.visrect;
593 offset_rect( &src.visrect, 0, -src_to_dst_offset );
595 src.x = src.visrect.left;
596 src.y = src.visrect.top;
597 src.width = src.visrect.right - src.visrect.left;
598 src.height = src.visrect.bottom - src.visrect.top;
600 dst.x = dst.visrect.left;
601 dst.y = dst.visrect.top;
602 dst.width = dst.visrect.right - dst.visrect.left;
603 dst.height = dst.visrect.bottom - dst.visrect.top;
605 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
607 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
608 if (err == ERROR_BAD_FORMAT)
610 void *ptr;
612 dst_info->bmiHeader.biWidth = dst.width;
613 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
614 if (ptr)
616 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr );
617 if (src_bits.free) src_bits.free( &src_bits );
618 src_bits.ptr = ptr;
619 src_bits.is_copy = TRUE;
620 src_bits.free = free_heap_bits;
621 if (!err)
622 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
624 else err = ERROR_OUTOFMEMORY;
626 if(err) result = 0;
628 done:
629 if (src_bits.free) src_bits.free( &src_bits );
630 if (clip) DeleteObject( clip );
631 GDI_ReleaseObj( hbitmap );
632 release_dc_ptr( dc );
633 if (delete_hdc) DeleteDC(hdc);
634 return result;
638 /***********************************************************************
639 * SetDIBitsToDevice (GDI32.@)
641 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
642 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
643 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
644 UINT coloruse )
646 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
647 BITMAPINFO *info = (BITMAPINFO *)buffer;
648 INT ret = 0;
649 DC *dc;
651 if (!bits) return 0;
652 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
654 SetLastError( ERROR_INVALID_PARAMETER );
655 return 0;
658 if ((dc = get_dc_ptr( hdc )))
660 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
661 update_dc( dc );
662 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
663 ySrc, startscan, lines, bits, info, coloruse );
664 release_dc_ptr( dc );
666 return ret;
669 /***********************************************************************
670 * SetDIBColorTable (GDI32.@)
672 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
674 DC * dc;
675 UINT result = 0;
676 BITMAPOBJ * bitmap;
678 if (!(dc = get_dc_ptr( hdc ))) return 0;
680 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
682 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
684 /* Check if currently selected bitmap is a DIB */
685 if (bitmap->color_table)
687 if (startpos < bitmap->nb_colors)
689 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
690 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
691 result = entries;
694 GDI_ReleaseObj( dc->hBitmap );
695 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
697 release_dc_ptr( dc );
698 return result;
702 /***********************************************************************
703 * GetDIBColorTable (GDI32.@)
705 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
707 DC * dc;
708 BITMAPOBJ *bitmap;
709 UINT result = 0;
711 if (!(dc = get_dc_ptr( hdc ))) return 0;
713 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
715 /* Check if currently selected bitmap is a DIB */
716 if (bitmap->color_table)
718 if (startpos < bitmap->nb_colors)
720 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
721 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
722 result = entries;
725 GDI_ReleaseObj( dc->hBitmap );
727 release_dc_ptr( dc );
728 return result;
731 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
732 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
733 { 0x00, 0x00, 0x00, 0x00 },
734 { 0x00, 0x00, 0x80, 0x00 },
735 { 0x00, 0x80, 0x00, 0x00 },
736 { 0x00, 0x80, 0x80, 0x00 },
737 { 0x80, 0x00, 0x00, 0x00 },
738 { 0x80, 0x00, 0x80, 0x00 },
739 { 0x80, 0x80, 0x00, 0x00 },
740 { 0xc0, 0xc0, 0xc0, 0x00 },
741 { 0xc0, 0xdc, 0xc0, 0x00 },
742 { 0xf0, 0xca, 0xa6, 0x00 },
743 { 0xf0, 0xfb, 0xff, 0x00 },
744 { 0xa4, 0xa0, 0xa0, 0x00 },
745 { 0x80, 0x80, 0x80, 0x00 },
746 { 0x00, 0x00, 0xff, 0x00 },
747 { 0x00, 0xff, 0x00, 0x00 },
748 { 0x00, 0xff, 0xff, 0x00 },
749 { 0xff, 0x00, 0x00, 0x00 },
750 { 0xff, 0x00, 0xff, 0x00 },
751 { 0xff, 0xff, 0x00, 0x00 },
752 { 0xff, 0xff, 0xff, 0x00 }
755 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
756 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
757 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
759 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
761 BITMAPINFOHEADER header;
763 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
764 header.biWidth = bmp->bitmap.bmWidth;
765 header.biHeight = bmp->bitmap.bmHeight;
766 header.biPlanes = 1;
768 if (bmp->dib)
770 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
771 switch (bmp->dib->dsBm.bmBitsPixel)
773 case 16:
774 case 32:
775 header.biCompression = BI_BITFIELDS;
776 break;
777 default:
778 header.biCompression = BI_RGB;
779 break;
782 else
784 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
785 header.biBitCount = bmp->bitmap.bmBitsPixel;
788 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
789 header.biXPelsPerMeter = 0;
790 header.biYPelsPerMeter = 0;
791 header.biClrUsed = 0;
792 header.biClrImportant = 0;
794 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
796 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
798 coreheader->bcWidth = header.biWidth;
799 coreheader->bcHeight = header.biHeight;
800 coreheader->bcPlanes = header.biPlanes;
801 coreheader->bcBitCount = header.biBitCount;
803 else
804 info->bmiHeader = header;
806 return abs(bmp->bitmap.bmHeight);
809 /************************************************************************
810 * copy_color_info
812 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
814 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
816 unsigned int colors = get_dib_num_of_colors( src );
817 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
819 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
821 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
823 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
824 if (coloruse == DIB_PAL_COLORS)
825 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
826 else
828 unsigned int i;
829 for (i = 0; i < colors; i++)
831 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
832 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
833 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
837 else
839 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
840 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
842 if (src->bmiHeader.biCompression == BI_BITFIELDS)
843 /* bitfields are always at bmiColors even in larger structures */
844 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
845 else if (colors)
847 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
848 unsigned int size;
850 if (coloruse == DIB_PAL_COLORS)
851 size = colors * sizeof(WORD);
852 else
853 size = colors * sizeof(RGBQUAD);
854 memcpy( colorptr, src_colors, size );
859 static void fill_default_color_table( BITMAPINFO *info )
861 int i;
863 switch (info->bmiHeader.biBitCount)
865 case 1:
866 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
867 info->bmiColors[0].rgbReserved = 0;
868 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
869 info->bmiColors[1].rgbReserved = 0;
870 break;
872 case 4:
873 /* The EGA palette is the first and last 8 colours of the default palette
874 with the innermost pair swapped */
875 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
876 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
877 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
878 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
879 break;
881 case 8:
882 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
883 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
884 for (i = 10; i < 246; i++)
886 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
887 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
888 info->bmiColors[i].rgbBlue = i & 0xc0;
889 info->bmiColors[i].rgbReserved = 0;
891 break;
893 default:
894 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
898 /******************************************************************************
899 * GetDIBits [GDI32.@]
901 * Retrieves bits of bitmap and copies to buffer.
903 * RETURNS
904 * Success: Number of scan lines copied from bitmap
905 * Failure: 0
907 INT WINAPI GetDIBits(
908 HDC hdc, /* [in] Handle to device context */
909 HBITMAP hbitmap, /* [in] Handle to bitmap */
910 UINT startscan, /* [in] First scan line to set in dest bitmap */
911 UINT lines, /* [in] Number of scan lines to copy */
912 LPVOID bits, /* [out] Address of array for bitmap bits */
913 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
914 UINT coloruse) /* [in] RGB or palette index */
916 DC * dc;
917 BITMAPOBJ * bmp;
918 int i, dst_to_src_offset, ret = 0;
919 DWORD err;
920 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
921 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
922 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
923 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
924 const struct gdi_dc_funcs *funcs;
925 struct gdi_image_bits src_bits;
926 struct bitblt_coords src, dst;
927 BOOL empty_rect = FALSE;
929 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
930 own copy and transfer the colour info back at the end */
931 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
932 dst_info->bmiHeader.biClrUsed = 0;
933 dst_info->bmiHeader.biClrImportant = 0;
935 if (!(dc = get_dc_ptr( hdc )))
937 SetLastError( ERROR_INVALID_PARAMETER );
938 return 0;
940 update_dc( dc );
941 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
943 release_dc_ptr( dc );
944 return 0;
947 funcs = get_bitmap_funcs( bmp );
949 if (dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
951 ret = fill_query_info( info, bmp );
952 goto done;
955 src.visrect.left = 0;
956 src.visrect.top = 0;
957 src.visrect.right = bmp->bitmap.bmWidth;
958 src.visrect.bottom = bmp->bitmap.bmHeight;
960 dst.visrect.left = 0;
961 dst.visrect.top = 0;
962 dst.visrect.right = dst_info->bmiHeader.biWidth;
963 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
965 if (lines == 0 || startscan >= dst.visrect.bottom)
966 bits = NULL;
968 if (bits)
970 if (dst_info->bmiHeader.biHeight > 0)
972 dst_to_src_offset = -startscan;
973 lines = min( lines, dst.visrect.bottom - startscan );
974 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
976 else
978 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
979 if (dst_to_src_offset < 0)
981 dst_to_src_offset = 0;
982 lines = dst.visrect.bottom - startscan;
984 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
987 offset_rect( &dst.visrect, 0, dst_to_src_offset );
988 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
989 dst.visrect = src.visrect;
990 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
992 if (dst_info->bmiHeader.biHeight > 0)
994 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
996 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
997 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
998 memset( bits, 0, pad_bytes );
999 bits = (char *)bits + pad_bytes;
1002 else
1004 if (dst.visrect.bottom < lines)
1006 int pad_lines = lines - dst.visrect.bottom;
1007 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1008 int pad_bytes = pad_lines * stride;
1009 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1013 if (empty_rect) bits = NULL;
1015 src.x = src.visrect.left;
1016 src.y = src.visrect.top;
1017 src.width = src.visrect.right - src.visrect.left;
1018 src.height = src.visrect.bottom - src.visrect.top;
1020 lines = src.height;
1023 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1025 if (err) goto done;
1027 /* fill out the src colour table, if it needs one */
1028 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1030 fill_default_color_table( src_info );
1031 src_info->bmiHeader.biClrUsed = 1 << src_info->bmiHeader.biBitCount;
1034 /* if the src and dst are the same depth, copy the colour info across */
1035 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1037 switch (src_info->bmiHeader.biBitCount)
1039 case 16:
1040 if (src_info->bmiHeader.biCompression == BI_RGB)
1042 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1043 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1045 break;
1046 case 32:
1047 if (src_info->bmiHeader.biCompression == BI_RGB)
1049 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1050 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1052 break;
1054 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1055 copy_color_info( dst_info, src_info, coloruse );
1057 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1059 if( coloruse == DIB_PAL_COLORS )
1061 if (!fill_color_table_from_palette( dst_info, dc )) goto done;
1063 else
1065 fill_default_color_table( dst_info );
1069 if (bits)
1071 if(dst_info->bmiHeader.biHeight > 0)
1072 dst_info->bmiHeader.biHeight = src.height;
1073 else
1074 dst_info->bmiHeader.biHeight = -src.height;
1076 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
1077 if (src_bits.free) src_bits.free( &src_bits );
1078 ret = lines;
1080 else
1081 ret = empty_rect ? FALSE : TRUE;
1083 if (coloruse == DIB_PAL_COLORS)
1085 WORD *index = (WORD *)dst_info->bmiColors;
1086 int colors = get_dib_num_of_colors( dst_info );
1087 for (i = 0; i < colors; i++, index++)
1088 *index = i;
1091 copy_color_info( info, dst_info, coloruse );
1093 done:
1094 release_dc_ptr( dc );
1095 GDI_ReleaseObj( hbitmap );
1096 return ret;
1100 /***********************************************************************
1101 * CreateDIBitmap (GDI32.@)
1103 * Creates a DDB (device dependent bitmap) from a DIB.
1104 * The DDB will have the same color depth as the reference DC.
1106 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1107 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1108 UINT coloruse )
1110 BITMAPINFOHEADER info;
1111 HBITMAP handle;
1112 LONG height;
1114 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1115 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1116 if (info.biWidth < 0) return 0;
1118 /* Top-down DIBs have a negative height */
1119 height = abs( info.biHeight );
1121 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1122 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1123 info.biBitCount, info.biCompression);
1125 if (hdc == NULL)
1126 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1127 else
1128 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1130 if (handle)
1132 if (init & CBM_INIT)
1134 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1136 DeleteObject( handle );
1137 handle = 0;
1142 return handle;
1145 /* Copy/synthesize RGB palette from BITMAPINFO */
1146 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1148 unsigned int colors, i;
1150 colors = get_dib_num_of_colors( info );
1151 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1152 bmp->nb_colors = colors;
1154 if (coloruse == DIB_RGB_COLORS)
1156 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1158 else
1160 PALETTEENTRY entries[256];
1161 const WORD *index = (const WORD *)info->bmiColors;
1162 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1164 for (i = 0; i < colors; i++, index++)
1166 PALETTEENTRY *entry = &entries[*index % count];
1167 bmp->color_table[i].rgbRed = entry->peRed;
1168 bmp->color_table[i].rgbGreen = entry->peGreen;
1169 bmp->color_table[i].rgbBlue = entry->peBlue;
1170 bmp->color_table[i].rgbReserved = 0;
1175 /***********************************************************************
1176 * CreateDIBSection (GDI32.@)
1178 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1179 VOID **bits, HANDLE section, DWORD offset)
1181 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1182 BITMAPINFO *info = (BITMAPINFO *)buffer;
1183 HBITMAP ret = 0;
1184 DC *dc;
1185 BOOL bDesktopDC = FALSE;
1186 DIBSECTION *dib;
1187 BITMAPOBJ *bmp;
1188 void *mapBits = NULL;
1190 if (bits) *bits = NULL;
1191 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1192 if (info->bmiHeader.biPlanes != 1)
1194 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1195 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1198 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1200 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1201 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1202 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1203 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1204 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1206 dib->dsBm.bmType = 0;
1207 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1208 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1209 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1210 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1211 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1212 dib->dsBm.bmBits = NULL;
1213 dib->dsBmih = info->bmiHeader;
1215 /* set number of entries in bmi.bmiColors table */
1216 if( info->bmiHeader.biBitCount <= 8 )
1217 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1219 /* set dsBitfields values */
1220 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1222 dib->dsBmih.biCompression = BI_BITFIELDS;
1223 dib->dsBitfields[0] = 0x7c00;
1224 dib->dsBitfields[1] = 0x03e0;
1225 dib->dsBitfields[2] = 0x001f;
1227 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1229 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1230 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1231 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1232 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1234 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1236 /* get storage location for DIB bits */
1238 if (section)
1240 SYSTEM_INFO SystemInfo;
1241 DWORD mapOffset;
1242 INT mapSize;
1244 GetSystemInfo( &SystemInfo );
1245 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1246 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1247 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1248 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1250 else
1252 offset = 0;
1253 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1254 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1256 dib->dshSection = section;
1257 dib->dsOffset = offset;
1259 if (!dib->dsBm.bmBits)
1261 HeapFree( GetProcessHeap(), 0, dib );
1262 return 0;
1265 /* If the reference hdc is null, take the desktop dc */
1266 if (hdc == 0)
1268 hdc = CreateCompatibleDC(0);
1269 bDesktopDC = TRUE;
1272 if (!(dc = get_dc_ptr( hdc ))) goto error;
1274 /* create Device Dependent Bitmap and add DIB pointer */
1275 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1276 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1278 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1280 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1281 bmp->dib = dib;
1282 bmp->funcs = physdev->funcs;
1283 /* create local copy of DIB palette */
1284 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1285 GDI_ReleaseObj( ret );
1287 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1289 DeleteObject( ret );
1290 ret = 0;
1294 release_dc_ptr( dc );
1295 if (bDesktopDC) DeleteDC( hdc );
1296 if (ret && bits) *bits = dib->dsBm.bmBits;
1297 return ret;
1299 error:
1300 if (bDesktopDC) DeleteDC( hdc );
1301 if (section) UnmapViewOfFile( mapBits );
1302 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1303 HeapFree( GetProcessHeap(), 0, dib );
1304 return 0;