winmm: Remove redundant code.
[wine/multimedia.git] / dlls / gdi32 / dib.c
blobebc6fe498fad7f9dc804ca71c4ed74d8c4d7e3bc
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 = bitmap->funcs;
587 if (bitmap->dib) funcs = dc->dibdrv.dev.funcs;
589 result = lines;
591 offset_rect( &src.visrect, 0, src_to_dst_offset );
592 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
593 src.visrect = dst.visrect;
594 offset_rect( &src.visrect, 0, -src_to_dst_offset );
596 src.x = src.visrect.left;
597 src.y = src.visrect.top;
598 src.width = src.visrect.right - src.visrect.left;
599 src.height = src.visrect.bottom - src.visrect.top;
601 dst.x = dst.visrect.left;
602 dst.y = dst.visrect.top;
603 dst.width = dst.visrect.right - dst.visrect.left;
604 dst.height = dst.visrect.bottom - dst.visrect.top;
606 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
608 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
609 if (err == ERROR_BAD_FORMAT)
611 void *ptr;
613 dst_info->bmiHeader.biWidth = dst.width;
614 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
615 if (ptr)
617 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr );
619 if (src_bits.free) src_bits.free( &src_bits );
620 src_bits.ptr = ptr;
621 src_bits.is_copy = TRUE;
622 src_bits.free = free_heap_bits;
623 if (!err)
624 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
627 else err = ERROR_OUTOFMEMORY;
629 if(err) result = 0;
631 done:
632 if (src_bits.free) src_bits.free( &src_bits );
633 if (clip) DeleteObject( clip );
634 GDI_ReleaseObj( hbitmap );
635 release_dc_ptr( dc );
636 if (delete_hdc) DeleteDC(hdc);
637 return result;
641 /***********************************************************************
642 * SetDIBitsToDevice (GDI32.@)
644 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
645 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
646 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
647 UINT coloruse )
649 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
650 BITMAPINFO *info = (BITMAPINFO *)buffer;
651 INT ret = 0;
652 DC *dc;
654 if (!bits) return 0;
655 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
657 SetLastError( ERROR_INVALID_PARAMETER );
658 return 0;
661 if ((dc = get_dc_ptr( hdc )))
663 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
664 update_dc( dc );
665 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
666 ySrc, startscan, lines, bits, info, coloruse );
667 release_dc_ptr( dc );
669 return ret;
672 /***********************************************************************
673 * SetDIBColorTable (GDI32.@)
675 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
677 DC * dc;
678 UINT result = 0;
679 BITMAPOBJ * bitmap;
681 if (!(dc = get_dc_ptr( hdc ))) return 0;
683 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
685 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
687 /* Check if currently selected bitmap is a DIB */
688 if (bitmap->color_table)
690 if (startpos < bitmap->nb_colors)
692 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
693 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
694 result = entries;
697 GDI_ReleaseObj( dc->hBitmap );
698 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
700 release_dc_ptr( dc );
701 return result;
705 /***********************************************************************
706 * GetDIBColorTable (GDI32.@)
708 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
710 DC * dc;
711 BITMAPOBJ *bitmap;
712 UINT result = 0;
714 if (!(dc = get_dc_ptr( hdc ))) return 0;
716 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
718 /* Check if currently selected bitmap is a DIB */
719 if (bitmap->color_table)
721 if (startpos < bitmap->nb_colors)
723 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
724 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
725 result = entries;
728 GDI_ReleaseObj( dc->hBitmap );
730 release_dc_ptr( dc );
731 return result;
734 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
735 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
736 { 0x00, 0x00, 0x00, 0x00 },
737 { 0x00, 0x00, 0x80, 0x00 },
738 { 0x00, 0x80, 0x00, 0x00 },
739 { 0x00, 0x80, 0x80, 0x00 },
740 { 0x80, 0x00, 0x00, 0x00 },
741 { 0x80, 0x00, 0x80, 0x00 },
742 { 0x80, 0x80, 0x00, 0x00 },
743 { 0xc0, 0xc0, 0xc0, 0x00 },
744 { 0xc0, 0xdc, 0xc0, 0x00 },
745 { 0xf0, 0xca, 0xa6, 0x00 },
746 { 0xf0, 0xfb, 0xff, 0x00 },
747 { 0xa4, 0xa0, 0xa0, 0x00 },
748 { 0x80, 0x80, 0x80, 0x00 },
749 { 0x00, 0x00, 0xff, 0x00 },
750 { 0x00, 0xff, 0x00, 0x00 },
751 { 0x00, 0xff, 0xff, 0x00 },
752 { 0xff, 0x00, 0x00, 0x00 },
753 { 0xff, 0x00, 0xff, 0x00 },
754 { 0xff, 0xff, 0x00, 0x00 },
755 { 0xff, 0xff, 0xff, 0x00 }
758 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
759 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
760 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
762 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
764 BITMAPINFOHEADER header;
766 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
767 header.biWidth = bmp->bitmap.bmWidth;
768 header.biHeight = bmp->bitmap.bmHeight;
769 header.biPlanes = 1;
771 if (bmp->dib)
773 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
774 switch (bmp->dib->dsBm.bmBitsPixel)
776 case 16:
777 case 32:
778 header.biCompression = BI_BITFIELDS;
779 break;
780 default:
781 header.biCompression = BI_RGB;
782 break;
785 else
787 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
788 header.biBitCount = bmp->bitmap.bmBitsPixel;
791 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
792 header.biXPelsPerMeter = 0;
793 header.biYPelsPerMeter = 0;
794 header.biClrUsed = 0;
795 header.biClrImportant = 0;
797 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
799 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
801 coreheader->bcWidth = header.biWidth;
802 coreheader->bcHeight = header.biHeight;
803 coreheader->bcPlanes = header.biPlanes;
804 coreheader->bcBitCount = header.biBitCount;
806 else
807 info->bmiHeader = header;
809 return abs(bmp->bitmap.bmHeight);
812 /************************************************************************
813 * copy_color_info
815 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
817 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
819 unsigned int colors = get_dib_num_of_colors( src );
820 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
822 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
824 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
826 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
827 if (coloruse == DIB_PAL_COLORS)
828 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
829 else
831 unsigned int i;
832 for (i = 0; i < colors; i++)
834 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
835 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
836 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
840 else
842 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
843 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
845 if (src->bmiHeader.biCompression == BI_BITFIELDS)
846 /* bitfields are always at bmiColors even in larger structures */
847 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
848 else if (colors)
850 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
851 unsigned int size;
853 if (coloruse == DIB_PAL_COLORS)
854 size = colors * sizeof(WORD);
855 else
856 size = colors * sizeof(RGBQUAD);
857 memcpy( colorptr, src_colors, size );
862 static void fill_default_color_table( BITMAPINFO *info )
864 int i;
866 switch (info->bmiHeader.biBitCount)
868 case 1:
869 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
870 info->bmiColors[0].rgbReserved = 0;
871 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
872 info->bmiColors[1].rgbReserved = 0;
873 break;
875 case 4:
876 /* The EGA palette is the first and last 8 colours of the default palette
877 with the innermost pair swapped */
878 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
879 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
880 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
881 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
882 break;
884 case 8:
885 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
886 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
887 for (i = 10; i < 246; i++)
889 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
890 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
891 info->bmiColors[i].rgbBlue = i & 0xc0;
892 info->bmiColors[i].rgbReserved = 0;
894 break;
896 default:
897 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
901 /******************************************************************************
902 * GetDIBits [GDI32.@]
904 * Retrieves bits of bitmap and copies to buffer.
906 * RETURNS
907 * Success: Number of scan lines copied from bitmap
908 * Failure: 0
910 INT WINAPI GetDIBits(
911 HDC hdc, /* [in] Handle to device context */
912 HBITMAP hbitmap, /* [in] Handle to bitmap */
913 UINT startscan, /* [in] First scan line to set in dest bitmap */
914 UINT lines, /* [in] Number of scan lines to copy */
915 LPVOID bits, /* [out] Address of array for bitmap bits */
916 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
917 UINT coloruse) /* [in] RGB or palette index */
919 DC * dc;
920 BITMAPOBJ * bmp;
921 int i, dst_to_src_offset, ret = 0;
922 DWORD err;
923 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
924 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
925 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
926 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
927 const struct gdi_dc_funcs *funcs;
928 struct gdi_image_bits src_bits;
929 struct bitblt_coords src, dst;
930 BOOL empty_rect = FALSE;
932 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
933 own copy and transfer the colour info back at the end */
934 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
935 dst_info->bmiHeader.biClrUsed = 0;
936 dst_info->bmiHeader.biClrImportant = 0;
938 if (!(dc = get_dc_ptr( hdc )))
940 SetLastError( ERROR_INVALID_PARAMETER );
941 return 0;
943 update_dc( dc );
944 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
946 release_dc_ptr( dc );
947 return 0;
950 funcs = bmp->funcs;
951 if (bmp->dib) funcs = dc->dibdrv.dev.funcs;
953 if (dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
955 ret = fill_query_info( info, bmp );
956 goto done;
959 src.visrect.left = 0;
960 src.visrect.top = 0;
961 src.visrect.right = bmp->bitmap.bmWidth;
962 src.visrect.bottom = bmp->bitmap.bmHeight;
964 dst.visrect.left = 0;
965 dst.visrect.top = 0;
966 dst.visrect.right = dst_info->bmiHeader.biWidth;
967 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
969 if (lines == 0 || startscan >= dst.visrect.bottom)
970 bits = NULL;
972 if (bits)
974 if (dst_info->bmiHeader.biHeight > 0)
976 dst_to_src_offset = -startscan;
977 lines = min( lines, dst.visrect.bottom - startscan );
978 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
980 else
982 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
983 if (dst_to_src_offset < 0)
985 dst_to_src_offset = 0;
986 lines = dst.visrect.bottom - startscan;
988 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
991 offset_rect( &dst.visrect, 0, dst_to_src_offset );
992 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
993 dst.visrect = src.visrect;
994 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
996 if (dst_info->bmiHeader.biHeight > 0)
998 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1000 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1001 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1002 memset( bits, 0, pad_bytes );
1003 bits = (char *)bits + pad_bytes;
1006 else
1008 if (dst.visrect.bottom < lines)
1010 int pad_lines = lines - dst.visrect.bottom;
1011 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1012 int pad_bytes = pad_lines * stride;
1013 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1017 if (empty_rect) bits = NULL;
1019 src.x = src.visrect.left;
1020 src.y = src.visrect.top;
1021 src.width = src.visrect.right - src.visrect.left;
1022 src.height = src.visrect.bottom - src.visrect.top;
1024 lines = src.height;
1027 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1029 if (err) goto done;
1031 /* fill out the src colour table, if it needs one */
1032 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1034 fill_default_color_table( src_info );
1035 src_info->bmiHeader.biClrUsed = 1 << src_info->bmiHeader.biBitCount;
1038 /* if the src and dst are the same depth, copy the colour info across */
1039 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1041 switch (src_info->bmiHeader.biBitCount)
1043 case 16:
1044 if (src_info->bmiHeader.biCompression == BI_RGB)
1046 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1047 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1049 break;
1050 case 32:
1051 if (src_info->bmiHeader.biCompression == BI_RGB)
1053 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1054 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1056 break;
1058 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1059 copy_color_info( dst_info, src_info, coloruse );
1061 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1063 if( coloruse == DIB_PAL_COLORS )
1065 if (!fill_color_table_from_palette( dst_info, dc )) goto done;
1067 else
1069 fill_default_color_table( dst_info );
1073 if (bits)
1075 if(dst_info->bmiHeader.biHeight > 0)
1076 dst_info->bmiHeader.biHeight = src.height;
1077 else
1078 dst_info->bmiHeader.biHeight = -src.height;
1080 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
1081 if (src_bits.free) src_bits.free( &src_bits );
1082 ret = lines;
1084 else
1085 ret = empty_rect ? FALSE : TRUE;
1087 if (coloruse == DIB_PAL_COLORS)
1089 WORD *index = (WORD *)dst_info->bmiColors;
1090 int colors = get_dib_num_of_colors( dst_info );
1091 for (i = 0; i < colors; i++, index++)
1092 *index = i;
1095 copy_color_info( info, dst_info, coloruse );
1097 done:
1098 release_dc_ptr( dc );
1099 GDI_ReleaseObj( hbitmap );
1100 return ret;
1104 /***********************************************************************
1105 * CreateDIBitmap (GDI32.@)
1107 * Creates a DDB (device dependent bitmap) from a DIB.
1108 * The DDB will have the same color depth as the reference DC.
1110 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1111 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1112 UINT coloruse )
1114 BITMAPINFOHEADER info;
1115 HBITMAP handle;
1116 LONG height;
1118 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1119 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1120 if (info.biWidth < 0) return 0;
1122 /* Top-down DIBs have a negative height */
1123 height = abs( info.biHeight );
1125 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1126 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1127 info.biBitCount, info.biCompression);
1129 if (hdc == NULL)
1130 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1131 else
1132 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1134 if (handle)
1136 if (init & CBM_INIT)
1138 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1140 DeleteObject( handle );
1141 handle = 0;
1146 return handle;
1149 /* Copy/synthesize RGB palette from BITMAPINFO */
1150 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1152 unsigned int colors, i;
1154 colors = get_dib_num_of_colors( info );
1155 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1156 bmp->nb_colors = colors;
1158 if (coloruse == DIB_RGB_COLORS)
1160 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1162 else
1164 PALETTEENTRY entries[256];
1165 const WORD *index = (const WORD *)info->bmiColors;
1166 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1168 for (i = 0; i < colors; i++, index++)
1170 PALETTEENTRY *entry = &entries[*index % count];
1171 bmp->color_table[i].rgbRed = entry->peRed;
1172 bmp->color_table[i].rgbGreen = entry->peGreen;
1173 bmp->color_table[i].rgbBlue = entry->peBlue;
1174 bmp->color_table[i].rgbReserved = 0;
1179 /***********************************************************************
1180 * CreateDIBSection (GDI32.@)
1182 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1183 VOID **bits, HANDLE section, DWORD offset)
1185 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1186 BITMAPINFO *info = (BITMAPINFO *)buffer;
1187 HBITMAP ret = 0;
1188 DC *dc;
1189 BOOL bDesktopDC = FALSE;
1190 DIBSECTION *dib;
1191 BITMAPOBJ *bmp;
1192 void *mapBits = NULL;
1194 if (bits) *bits = NULL;
1195 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1196 if (info->bmiHeader.biPlanes != 1)
1198 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1199 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1202 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1204 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1205 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1206 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1207 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1208 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1210 dib->dsBm.bmType = 0;
1211 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1212 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1213 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1214 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1215 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1216 dib->dsBm.bmBits = NULL;
1217 dib->dsBmih = info->bmiHeader;
1219 /* set number of entries in bmi.bmiColors table */
1220 if( info->bmiHeader.biBitCount <= 8 )
1221 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1223 /* set dsBitfields values */
1224 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1226 dib->dsBmih.biCompression = BI_BITFIELDS;
1227 dib->dsBitfields[0] = 0x7c00;
1228 dib->dsBitfields[1] = 0x03e0;
1229 dib->dsBitfields[2] = 0x001f;
1231 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1233 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1234 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1235 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1236 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1238 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1240 /* get storage location for DIB bits */
1242 if (section)
1244 SYSTEM_INFO SystemInfo;
1245 DWORD mapOffset;
1246 INT mapSize;
1248 GetSystemInfo( &SystemInfo );
1249 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1250 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1251 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1252 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1254 else
1256 offset = 0;
1257 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1258 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1260 dib->dshSection = section;
1261 dib->dsOffset = offset;
1263 if (!dib->dsBm.bmBits)
1265 HeapFree( GetProcessHeap(), 0, dib );
1266 return 0;
1269 /* If the reference hdc is null, take the desktop dc */
1270 if (hdc == 0)
1272 hdc = CreateCompatibleDC(0);
1273 bDesktopDC = TRUE;
1276 if (!(dc = get_dc_ptr( hdc ))) goto error;
1278 /* create Device Dependent Bitmap and add DIB pointer */
1279 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1280 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1282 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1284 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1285 bmp->dib = dib;
1286 bmp->funcs = physdev->funcs;
1287 /* create local copy of DIB palette */
1288 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1289 GDI_ReleaseObj( ret );
1291 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1293 DeleteObject( ret );
1294 ret = 0;
1298 release_dc_ptr( dc );
1299 if (bDesktopDC) DeleteDC( hdc );
1300 if (ret && bits) *bits = dib->dsBm.bmBits;
1301 return ret;
1303 error:
1304 if (bDesktopDC) DeleteDC( hdc );
1305 if (section) UnmapViewOfFile( mapBits );
1306 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1307 HeapFree( GetProcessHeap(), 0, dib );
1308 return 0;