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:
55 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 Search for "Bitmap Structures" in MSDN
69 #include "gdi_private.h"
70 #include "wine/debug.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
75 /***********************************************************************
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)
123 return (info->biCompression == BI_RGB);
126 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
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;
150 dst->biClrImportant = 0;
152 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
158 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
162 dst->biSize = sizeof(*dst);
163 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
164 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
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 )
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 (dst->bmiHeader.biCompression == BI_BITFIELDS)
185 /* bitfields are always at bmiColors even in larger structures */
186 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
187 dst->bmiHeader.biClrUsed = 0;
191 if (coloruse == DIB_PAL_COLORS)
192 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
193 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
194 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
198 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
199 for (i = 0; i < colors; i++)
201 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
202 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
203 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
204 dst->bmiColors[i].rgbReserved = 0;
207 dst->bmiHeader.biClrUsed = colors;
212 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
214 PALETTEENTRY palEntry[256];
215 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
216 int i, colors = get_dib_num_of_colors( info );
218 if (!palette) return 0;
219 if (!colors) return 0;
221 memset( palEntry, 0, sizeof(palEntry) );
222 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
225 for (i = 0; i < colors; i++)
227 info->bmiColors[i].rgbRed = palEntry[i].peRed;
228 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
229 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
230 info->bmiColors[i].rgbReserved = 0;
236 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
238 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
239 const int bpp = info->bmiHeader.biBitCount;
242 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
244 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
247 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
251 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
253 BYTE skip, num, data;
254 BYTE *out_bits, *in_bits = bits->ptr;
256 if (clip) *clip = NULL;
258 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
260 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
261 if (!out_bits) goto fail;
265 *clip = CreateRectRgn( 0, 0, 0, 0 );
266 run = CreateRectRgn( 0, 0, 0, 0 );
267 if (!*clip || !run) goto fail;
270 x = left = right = 0;
273 while (i < info->bmiHeader.biSizeImage - 1)
276 data = in_bits[i + 1];
281 if (x + num > width) num = width - x;
284 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
285 if (info->bmiHeader.biBitCount == 8)
286 memset( out_ptr, s, num );
291 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
292 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
297 /* this will write one too many if num is odd, but that doesn't matter */
298 if (num) memset( out_ptr, s, (num + 1) / 2 );
308 if(left != right && clip)
310 SetRectRgn( run, left, y, right, y + 1 );
311 CombineRgn( *clip, run, *clip, RGN_OR );
316 left = right = x = 0;
325 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
327 if (x > width) x = width;
334 else /* data bytes of data */
337 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
338 if (skip > info->bmiHeader.biSizeImage - i) goto done;
339 skip = (skip + 1) & ~1;
340 if (x + num > width) num = width - x;
343 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
344 if (info->bmiHeader.biBitCount == 8)
345 memcpy( out_ptr, in_bits + i, num );
350 const BYTE *in_ptr = in_bits + i;
351 for ( ; num; num--, x++)
355 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
359 *out_ptr = (*in_ptr++ << 4) & 0xf0;
363 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
374 if (run) DeleteObject( run );
375 if (bits->free) bits->free( bits );
377 bits->ptr = out_bits;
378 bits->is_copy = TRUE;
379 bits->free = free_heap_bits;
384 if (run) DeleteObject( run );
385 if (clip && *clip) DeleteObject( *clip );
386 HeapFree( GetProcessHeap(), 0, out_bits );
392 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
393 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
394 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
396 DC *dc = get_nulldrv_dc( dev );
397 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
398 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
399 struct bitblt_coords src, dst;
400 struct gdi_image_bits src_bits;
404 INT height = abs( src_info->bmiHeader.biHeight );
405 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
406 RECT rect, clip_rect;
408 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
409 xSrc, ySrc, widthSrc, heightSrc, rop);
411 src_bits.ptr = (void*)bits;
412 src_bits.is_copy = FALSE;
413 src_bits.free = NULL;
415 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
419 rect.right = xDst + widthDst;
420 rect.bottom = yDst + heightDst;
421 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
424 dst.width = rect.right - rect.left;
425 dst.height = rect.bottom - rect.top;
427 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
430 dst.width = -dst.width;
432 rop &= ~NOMIRRORBITMAP;
435 src.width = widthSrc;
437 src.height = heightSrc;
439 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
440 non_stretch_from_origin = TRUE;
442 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
444 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
445 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
448 if (rop != SRCCOPY || non_stretch_from_origin)
450 if (dst.width == 1 && src.width > 1) src.width--;
451 if (dst.height == 1 && src.height > 1) src.height--;
456 if (dst.width < 0 && dst.width == src.width)
458 /* This is off-by-one, but that's what Windows does */
461 dst.width = -dst.width;
462 src.width = -src.width;
464 if (dst.height < 0 && dst.height == src.height)
468 dst.height = -dst.height;
469 src.height = -src.height;
473 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
475 if (src.y >= height && src.y + src.height + 1 < height)
477 else if (src.y > 0 && src.y + src.height + 1 < 0)
478 src.y = -src.height - 1;
480 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
482 src.visrect.left = 0;
483 src.visrect.right = src_info->bmiHeader.biWidth;
485 src.visrect.bottom = height;
486 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
488 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
490 if (get_clip_box( dc, &clip_rect ))
491 intersect_rect( &dst.visrect, &rect, &clip_rect );
494 if (is_rect_empty( &dst.visrect )) goto done;
496 if (!intersect_vis_rectangles( &dst, &src )) goto done;
498 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
500 dev = GET_DC_PHYSDEV( dc, pPutImage );
501 copy_bitmapinfo( dst_info, src_info );
502 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
503 if (err == ERROR_BAD_FORMAT)
505 /* 1-bpp destination without a color table requires a fake 1-entry table
506 * that contains only the background color */
507 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
509 COLORREF color = GetBkColor( dev->hdc );
510 dst_info->bmiColors[0].rgbRed = GetRValue( color );
511 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
512 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
513 dst_info->bmiColors[0].rgbReserved = 0;
514 dst_info->bmiHeader.biClrUsed = 1;
517 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
519 /* get rid of the fake 1-bpp table */
520 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
521 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
525 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
527 copy_bitmapinfo( src_info, dst_info );
528 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
529 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
532 else if (rop == SRCCOPY) ret = height;
533 else ret = src_info->bmiHeader.biHeight;
536 if (src_bits.free) src_bits.free( &src_bits );
537 if (clip) DeleteObject( clip );
541 /***********************************************************************
542 * StretchDIBits (GDI32.@)
544 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
545 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
546 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
548 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
549 BITMAPINFO *info = (BITMAPINFO *)buffer;
554 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
556 SetLastError( ERROR_INVALID_PARAMETER );
560 if ((dc = get_dc_ptr( hdc )))
562 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
564 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
565 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
566 release_dc_ptr( dc );
572 /******************************************************************************
573 * SetDIBits [GDI32.@]
575 * Sets pixels in a bitmap using colors from DIB.
578 * hdc [I] Handle to device context
579 * hbitmap [I] Handle to bitmap
580 * startscan [I] Starting scan line
581 * lines [I] Number of scan lines
582 * bits [I] Array of bitmap bits
583 * info [I] Address of structure with data
584 * coloruse [I] Type of color indexes to use
587 * Success: Number of scan lines copied
590 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
591 UINT lines, LPCVOID bits, const BITMAPINFO *info,
595 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
596 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
597 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
598 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
601 struct gdi_image_bits src_bits;
602 struct bitblt_coords src, dst;
603 INT src_to_dst_offset;
605 const struct gdi_dc_funcs *funcs;
607 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
609 SetLastError( ERROR_INVALID_PARAMETER );
612 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
614 DWORD *masks = (DWORD *)src_info->bmiColors;
615 if (!masks[0] || !masks[1] || !masks[2])
617 SetLastError( ERROR_INVALID_PARAMETER );
622 src_bits.ptr = (void *)bits;
623 src_bits.is_copy = FALSE;
624 src_bits.free = NULL;
625 src_bits.param = NULL;
627 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, hdc )) return 0;
629 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
631 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
633 if (lines == 0) goto done;
634 else lines = src_info->bmiHeader.biHeight;
637 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
640 dst.visrect.left = 0;
642 dst.visrect.right = bitmap->bitmap.bmWidth;
643 dst.visrect.bottom = bitmap->bitmap.bmHeight;
645 src.visrect.left = 0;
647 src.visrect.right = src_info->bmiHeader.biWidth;
648 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
650 if (src_info->bmiHeader.biHeight > 0)
652 src_to_dst_offset = -startscan;
653 lines = min( lines, src.visrect.bottom - startscan );
654 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
658 src_to_dst_offset = src.visrect.bottom - lines - startscan;
659 /* Unlike the bottom-up case, Windows doesn't limit lines. */
660 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
663 funcs = get_bitmap_funcs( bitmap );
667 offset_rect( &src.visrect, 0, src_to_dst_offset );
668 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
669 src.visrect = dst.visrect;
670 offset_rect( &src.visrect, 0, -src_to_dst_offset );
672 src.x = src.visrect.left;
673 src.y = src.visrect.top;
674 src.width = src.visrect.right - src.visrect.left;
675 src.height = src.visrect.bottom - src.visrect.top;
677 dst.x = dst.visrect.left;
678 dst.y = dst.visrect.top;
679 dst.width = dst.visrect.right - dst.visrect.left;
680 dst.height = dst.visrect.bottom - dst.visrect.top;
682 copy_bitmapinfo( dst_info, src_info );
684 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
685 if (err == ERROR_BAD_FORMAT)
689 dst_info->bmiHeader.biWidth = dst.width;
690 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
693 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
694 if (src_bits.free) src_bits.free( &src_bits );
696 src_bits.is_copy = TRUE;
697 src_bits.free = free_heap_bits;
699 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
701 else err = ERROR_OUTOFMEMORY;
706 if (src_bits.free) src_bits.free( &src_bits );
707 if (clip) DeleteObject( clip );
708 GDI_ReleaseObj( hbitmap );
713 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
714 INT x_src, INT y_src, UINT startscan, UINT lines,
715 const void *bits, BITMAPINFO *src_info, UINT coloruse )
717 DC *dc = get_nulldrv_dc( dev );
718 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
719 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
720 struct bitblt_coords src, dst;
721 struct gdi_image_bits src_bits;
729 top_down = (src_info->bmiHeader.biHeight < 0);
730 height = abs( src_info->bmiHeader.biHeight );
732 src_bits.ptr = (void *)bits;
733 src_bits.is_copy = FALSE;
734 src_bits.free = NULL;
736 if (!lines) return 0;
737 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
739 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
743 src_info->bmiHeader.biWidth = x_src + cx;
744 src_info->bmiHeader.biHeight = y_src + cy;
745 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
750 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
754 if (startscan >= height) return 0;
755 if (!top_down && lines > height - startscan) lines = height - startscan;
757 /* map src to top-down coordinates with startscan as origin */
759 src.y = startscan + lines - (y_src + cy);
766 /* get rid of unnecessary lines */
767 if (src.y >= lines) return 0;
771 else if (src.y >= lines) return lines;
773 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
776 src.visrect.left = src.x;
777 src.visrect.top = src.y;
778 src.visrect.right = src.x + cx;
779 src.visrect.bottom = src.y + cy;
782 rect.right = src_info->bmiHeader.biWidth;
783 rect.bottom = abs( src_info->bmiHeader.biHeight );
784 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
792 LPtoDP( dev->hdc, &pt, 1 );
797 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
799 dst.visrect.left = dst.x;
800 dst.visrect.top = dst.y;
801 dst.visrect.right = dst.x + cx;
802 dst.visrect.bottom = dst.y + cy;
803 if (get_clip_box( dc, &rect )) intersect_rect( &dst.visrect, &dst.visrect, &rect );
805 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
806 intersect_rect( &rect, &src.visrect, &dst.visrect );
807 src.visrect = dst.visrect = rect;
808 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
809 if (is_rect_empty( &dst.visrect )) goto done;
810 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
812 dev = GET_DC_PHYSDEV( dc, pPutImage );
813 copy_bitmapinfo( dst_info, src_info );
814 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
815 if (err == ERROR_BAD_FORMAT)
819 dst_info->bmiHeader.biWidth = src.visrect.right - src.visrect.left;
820 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
823 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
824 if (src_bits.free) src_bits.free( &src_bits );
826 src_bits.is_copy = TRUE;
827 src_bits.free = free_heap_bits;
828 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
830 else err = ERROR_OUTOFMEMORY;
835 if (src_bits.free) src_bits.free( &src_bits );
836 if (clip) DeleteObject( clip );
840 /***********************************************************************
841 * SetDIBitsToDevice (GDI32.@)
843 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
844 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
845 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
848 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
849 BITMAPINFO *info = (BITMAPINFO *)buffer;
854 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
856 SetLastError( ERROR_INVALID_PARAMETER );
860 if ((dc = get_dc_ptr( hdc )))
862 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
864 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
865 ySrc, startscan, lines, bits, info, coloruse );
866 release_dc_ptr( dc );
871 /***********************************************************************
872 * SetDIBColorTable (GDI32.@)
874 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
880 if (!(dc = get_dc_ptr( hdc ))) return 0;
882 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
884 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
886 /* Check if currently selected bitmap is a DIB */
887 if (bitmap->color_table)
889 if (startpos < bitmap->nb_colors)
891 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
892 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
896 GDI_ReleaseObj( dc->hBitmap );
897 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
899 release_dc_ptr( dc );
904 /***********************************************************************
905 * GetDIBColorTable (GDI32.@)
907 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
913 if (!(dc = get_dc_ptr( hdc ))) return 0;
915 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
917 /* Check if currently selected bitmap is a DIB */
918 if (bitmap->color_table)
920 if (startpos < bitmap->nb_colors)
922 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
923 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
927 GDI_ReleaseObj( dc->hBitmap );
929 release_dc_ptr( dc );
933 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
934 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
935 { 0x00, 0x00, 0x00, 0x00 },
936 { 0x00, 0x00, 0x80, 0x00 },
937 { 0x00, 0x80, 0x00, 0x00 },
938 { 0x00, 0x80, 0x80, 0x00 },
939 { 0x80, 0x00, 0x00, 0x00 },
940 { 0x80, 0x00, 0x80, 0x00 },
941 { 0x80, 0x80, 0x00, 0x00 },
942 { 0xc0, 0xc0, 0xc0, 0x00 },
943 { 0xc0, 0xdc, 0xc0, 0x00 },
944 { 0xf0, 0xca, 0xa6, 0x00 },
945 { 0xf0, 0xfb, 0xff, 0x00 },
946 { 0xa4, 0xa0, 0xa0, 0x00 },
947 { 0x80, 0x80, 0x80, 0x00 },
948 { 0x00, 0x00, 0xff, 0x00 },
949 { 0x00, 0xff, 0x00, 0x00 },
950 { 0x00, 0xff, 0xff, 0x00 },
951 { 0xff, 0x00, 0x00, 0x00 },
952 { 0xff, 0x00, 0xff, 0x00 },
953 { 0xff, 0xff, 0x00, 0x00 },
954 { 0xff, 0xff, 0xff, 0x00 }
957 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
958 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
959 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
961 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
963 BITMAPINFOHEADER header;
965 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
966 header.biWidth = bmp->bitmap.bmWidth;
967 header.biHeight = bmp->bitmap.bmHeight;
972 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
973 switch (bmp->dib->dsBm.bmBitsPixel)
977 header.biCompression = BI_BITFIELDS;
980 header.biCompression = BI_RGB;
986 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
987 header.biBitCount = bmp->bitmap.bmBitsPixel;
990 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
991 header.biXPelsPerMeter = 0;
992 header.biYPelsPerMeter = 0;
993 header.biClrUsed = 0;
994 header.biClrImportant = 0;
996 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
998 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
1000 coreheader->bcWidth = header.biWidth;
1001 coreheader->bcHeight = header.biHeight;
1002 coreheader->bcPlanes = header.biPlanes;
1003 coreheader->bcBitCount = header.biBitCount;
1006 info->bmiHeader = header;
1008 return abs(bmp->bitmap.bmHeight);
1011 /************************************************************************
1014 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1016 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1018 unsigned int colors = get_dib_num_of_colors( src );
1019 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
1021 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
1023 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1025 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1026 if (coloruse == DIB_PAL_COLORS)
1027 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
1031 for (i = 0; i < colors; i++)
1033 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
1034 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
1035 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
1041 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1042 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1044 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1045 /* bitfields are always at bmiColors even in larger structures */
1046 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1049 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1052 if (coloruse == DIB_PAL_COLORS)
1053 size = colors * sizeof(WORD);
1055 size = colors * sizeof(RGBQUAD);
1056 memcpy( colorptr, src_colors, size );
1061 static void fill_default_color_table( BITMAPINFO *info )
1065 switch (info->bmiHeader.biBitCount)
1068 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
1069 info->bmiColors[0].rgbReserved = 0;
1070 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
1071 info->bmiColors[1].rgbReserved = 0;
1075 /* The EGA palette is the first and last 8 colours of the default palette
1076 with the innermost pair swapped */
1077 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
1078 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
1079 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
1080 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
1084 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
1085 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
1086 for (i = 10; i < 246; i++)
1088 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
1089 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
1090 info->bmiColors[i].rgbBlue = i & 0xc0;
1091 info->bmiColors[i].rgbReserved = 0;
1096 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
1098 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1101 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1103 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1104 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1105 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1106 info->bmiHeader.biPlanes = 1;
1107 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1108 info->bmiHeader.biCompression = BI_RGB;
1109 info->bmiHeader.biXPelsPerMeter = 0;
1110 info->bmiHeader.biYPelsPerMeter = 0;
1111 info->bmiHeader.biClrUsed = 0;
1112 info->bmiHeader.biClrImportant = 0;
1113 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1117 /******************************************************************************
1118 * GetDIBits [GDI32.@]
1120 * Retrieves bits of bitmap and copies to buffer.
1123 * Success: Number of scan lines copied from bitmap
1126 INT WINAPI GetDIBits(
1127 HDC hdc, /* [in] Handle to device context */
1128 HBITMAP hbitmap, /* [in] Handle to bitmap */
1129 UINT startscan, /* [in] First scan line to set in dest bitmap */
1130 UINT lines, /* [in] Number of scan lines to copy */
1131 LPVOID bits, /* [out] Address of array for bitmap bits */
1132 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1133 UINT coloruse) /* [in] RGB or palette index */
1137 int i, dst_to_src_offset, ret = 0;
1139 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1140 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1141 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1142 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1143 const struct gdi_dc_funcs *funcs;
1144 struct gdi_image_bits src_bits;
1145 struct bitblt_coords src, dst;
1146 BOOL empty_rect = FALSE;
1148 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1149 own copy and transfer the colour info back at the end */
1150 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1152 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1154 dst_info->bmiHeader.biClrUsed = 0;
1155 dst_info->bmiHeader.biClrImportant = 0;
1157 if (!(dc = get_dc_ptr( hdc )))
1159 SetLastError( ERROR_INVALID_PARAMETER );
1163 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1165 release_dc_ptr( dc );
1169 funcs = get_bitmap_funcs( bmp );
1171 src.visrect.left = 0;
1172 src.visrect.top = 0;
1173 src.visrect.right = bmp->bitmap.bmWidth;
1174 src.visrect.bottom = bmp->bitmap.bmHeight;
1176 dst.visrect.left = 0;
1177 dst.visrect.top = 0;
1178 dst.visrect.right = dst_info->bmiHeader.biWidth;
1179 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1181 if (lines == 0 || startscan >= dst.visrect.bottom)
1184 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1186 ret = fill_query_info( info, bmp );
1190 /* validate parameters */
1192 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1193 if (dst_info->bmiHeader.biHeight == 0) goto done;
1195 switch (dst_info->bmiHeader.biCompression)
1198 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1199 if (dst_info->bmiHeader.biHeight < 0) goto done;
1200 if (bits) goto done; /* can't retrieve compressed bits */
1203 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1204 if (dst_info->bmiHeader.biHeight < 0) goto done;
1205 if (bits) goto done; /* can't retrieve compressed bits */
1208 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1211 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1212 if (dst_info->bmiHeader.biBitCount == 1) break;
1213 if (dst_info->bmiHeader.biBitCount == 4) break;
1214 if (dst_info->bmiHeader.biBitCount == 8) break;
1215 if (dst_info->bmiHeader.biBitCount == 16) break;
1216 if (dst_info->bmiHeader.biBitCount == 24) break;
1217 if (dst_info->bmiHeader.biBitCount == 32) break;
1225 if (dst_info->bmiHeader.biHeight > 0)
1227 dst_to_src_offset = -startscan;
1228 lines = min( lines, dst.visrect.bottom - startscan );
1229 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1233 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1234 if (dst_to_src_offset < 0)
1236 dst_to_src_offset = 0;
1237 lines = dst.visrect.bottom - startscan;
1239 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1242 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1243 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1244 dst.visrect = src.visrect;
1245 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1247 if (dst_info->bmiHeader.biHeight > 0)
1249 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1251 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1252 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1253 memset( bits, 0, pad_bytes );
1254 bits = (char *)bits + pad_bytes;
1259 if (dst.visrect.bottom < lines)
1261 int pad_lines = lines - dst.visrect.bottom;
1262 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1263 int pad_bytes = pad_lines * stride;
1264 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1268 if (empty_rect) bits = NULL;
1270 src.x = src.visrect.left;
1271 src.y = src.visrect.top;
1272 src.width = src.visrect.right - src.visrect.left;
1273 src.height = src.visrect.bottom - src.visrect.top;
1278 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1282 /* fill out the src colour table, if it needs one */
1283 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1284 fill_default_color_table( src_info );
1286 /* if the src and dst are the same depth, copy the colour info across */
1287 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1289 switch (src_info->bmiHeader.biBitCount)
1292 if (src_info->bmiHeader.biCompression == BI_RGB)
1294 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1295 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1299 if (src_info->bmiHeader.biCompression == BI_RGB)
1301 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1302 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1306 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1307 copy_color_info( dst_info, src_info, coloruse );
1309 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1311 if( coloruse == DIB_PAL_COLORS )
1313 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1317 fill_default_color_table( dst_info );
1323 if(dst_info->bmiHeader.biHeight > 0)
1324 dst_info->bmiHeader.biHeight = src.height;
1326 dst_info->bmiHeader.biHeight = -src.height;
1328 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1329 if (src_bits.free) src_bits.free( &src_bits );
1333 ret = empty_rect ? FALSE : TRUE;
1335 if (coloruse == DIB_PAL_COLORS)
1337 WORD *index = (WORD *)dst_info->bmiColors;
1338 int colors = get_dib_num_of_colors( dst_info );
1339 for (i = 0; i < colors; i++, index++)
1343 copy_color_info( info, dst_info, coloruse );
1346 release_dc_ptr( dc );
1347 GDI_ReleaseObj( hbitmap );
1352 /***********************************************************************
1353 * CreateDIBitmap (GDI32.@)
1355 * Creates a DDB (device dependent bitmap) from a DIB.
1356 * The DDB will have the same color depth as the reference DC.
1358 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1359 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1362 BITMAPINFOHEADER info;
1366 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1367 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1368 if (info.biWidth < 0) return 0;
1370 /* Top-down DIBs have a negative height */
1371 height = abs( info.biHeight );
1373 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1374 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1375 info.biBitCount, info.biCompression);
1378 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1380 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1384 if (init & CBM_INIT)
1386 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1388 DeleteObject( handle );
1397 /* Copy/synthesize RGB palette from BITMAPINFO */
1398 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1400 unsigned int colors, i;
1402 colors = get_dib_num_of_colors( info );
1403 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1404 bmp->nb_colors = colors;
1406 if (coloruse == DIB_RGB_COLORS)
1408 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1412 PALETTEENTRY entries[256];
1413 const WORD *index = (const WORD *)info->bmiColors;
1414 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1416 for (i = 0; i < colors; i++, index++)
1418 PALETTEENTRY *entry = &entries[*index % count];
1419 bmp->color_table[i].rgbRed = entry->peRed;
1420 bmp->color_table[i].rgbGreen = entry->peGreen;
1421 bmp->color_table[i].rgbBlue = entry->peBlue;
1422 bmp->color_table[i].rgbReserved = 0;
1427 /***********************************************************************
1428 * CreateDIBSection (GDI32.@)
1430 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1431 VOID **bits, HANDLE section, DWORD offset)
1433 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1434 BITMAPINFO *info = (BITMAPINFO *)buffer;
1437 BOOL bDesktopDC = FALSE;
1440 void *mapBits = NULL;
1442 if (bits) *bits = NULL;
1443 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1444 if (info->bmiHeader.biPlanes != 1)
1446 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1447 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1450 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1452 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1453 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1454 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1455 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1456 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1458 dib->dsBm.bmType = 0;
1459 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1460 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1461 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1462 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1463 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1464 dib->dsBm.bmBits = NULL;
1465 dib->dsBmih = info->bmiHeader;
1467 /* set number of entries in bmi.bmiColors table */
1468 if( info->bmiHeader.biBitCount <= 8 )
1469 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1471 /* set dsBitfields values */
1472 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1474 dib->dsBmih.biCompression = BI_BITFIELDS;
1475 dib->dsBitfields[0] = 0x7c00;
1476 dib->dsBitfields[1] = 0x03e0;
1477 dib->dsBitfields[2] = 0x001f;
1479 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1481 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1482 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1483 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1484 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1486 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1488 /* get storage location for DIB bits */
1492 SYSTEM_INFO SystemInfo;
1496 GetSystemInfo( &SystemInfo );
1497 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1498 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1499 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1500 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1505 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1506 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1508 dib->dshSection = section;
1509 dib->dsOffset = offset;
1511 if (!dib->dsBm.bmBits)
1513 HeapFree( GetProcessHeap(), 0, dib );
1517 /* If the reference hdc is null, take the desktop dc */
1520 hdc = CreateCompatibleDC(0);
1524 if (!(dc = get_dc_ptr( hdc ))) goto error;
1526 /* create Device Dependent Bitmap and add DIB pointer */
1527 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1528 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1530 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1532 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1534 bmp->funcs = physdev->funcs;
1535 /* create local copy of DIB palette */
1536 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1537 GDI_ReleaseObj( ret );
1539 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1541 DeleteObject( ret );
1546 release_dc_ptr( dc );
1547 if (bDesktopDC) DeleteDC( hdc );
1548 if (ret && bits) *bits = dib->dsBm.bmBits;
1552 if (bDesktopDC) DeleteDC( hdc );
1553 if (section) UnmapViewOfFile( mapBits );
1554 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1555 HeapFree( GetProcessHeap(), 0, dib );