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) );
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) );
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;
206 dst->bmiHeader.biClrUsed = colors;
211 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
213 PALETTEENTRY palEntry[256];
214 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
215 int i, colors = get_dib_num_of_colors( info );
217 if (!palette) return 0;
218 if (!colors) return 0;
220 memset( palEntry, 0, sizeof(palEntry) );
221 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
224 for (i = 0; i < colors; i++)
226 info->bmiColors[i].rgbRed = palEntry[i].peRed;
227 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
228 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
229 info->bmiColors[i].rgbReserved = 0;
235 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
237 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
238 const int bpp = info->bmiHeader.biBitCount;
241 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
243 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
246 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
250 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
252 BYTE skip, num, data;
253 BYTE *out_bits, *in_bits = bits->ptr;
255 if (clip) *clip = NULL;
257 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
259 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
260 if (!out_bits) goto fail;
264 *clip = CreateRectRgn( 0, 0, 0, 0 );
265 run = CreateRectRgn( 0, 0, 0, 0 );
266 if (!*clip || !run) goto fail;
269 x = left = right = 0;
272 while (i < info->bmiHeader.biSizeImage - 1)
275 data = in_bits[i + 1];
280 if (x + num > width) num = width - x;
283 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
284 if (info->bmiHeader.biBitCount == 8)
285 memset( out_ptr, s, num );
290 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
291 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
296 /* this will write one too many if num is odd, but that doesn't matter */
297 if (num) memset( out_ptr, s, (num + 1) / 2 );
307 if(left != right && clip)
309 SetRectRgn( run, left, y, right, y + 1 );
310 CombineRgn( *clip, run, *clip, RGN_OR );
315 left = right = x = 0;
324 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
326 if (x > width) x = width;
333 else /* data bytes of data */
336 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
337 if (skip > info->bmiHeader.biSizeImage - i) goto done;
338 skip = (skip + 1) & ~1;
339 if (x + num > width) num = width - x;
342 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
343 if (info->bmiHeader.biBitCount == 8)
344 memcpy( out_ptr, in_bits + i, num );
349 const BYTE *in_ptr = in_bits + i;
350 for ( ; num; num--, x++)
354 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
358 *out_ptr = (*in_ptr++ << 4) & 0xf0;
362 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
373 if (run) DeleteObject( run );
374 if (bits->free) bits->free( bits );
376 bits->ptr = out_bits;
377 bits->is_copy = TRUE;
378 bits->free = free_heap_bits;
383 if (run) DeleteObject( run );
384 if (clip && *clip) DeleteObject( *clip );
385 HeapFree( GetProcessHeap(), 0, out_bits );
391 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
392 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
393 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
395 DC *dc = get_nulldrv_dc( dev );
396 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
397 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
398 struct bitblt_coords src, dst;
399 struct gdi_image_bits src_bits;
403 INT height = abs( src_info->bmiHeader.biHeight );
404 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
405 RECT rect, clip_rect;
407 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
408 xSrc, ySrc, widthSrc, heightSrc, rop);
410 src_bits.ptr = (void*)bits;
411 src_bits.is_copy = FALSE;
412 src_bits.free = NULL;
414 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
418 rect.right = xDst + widthDst;
419 rect.bottom = yDst + heightDst;
420 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
423 dst.width = rect.right - rect.left;
424 dst.height = rect.bottom - rect.top;
426 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
429 dst.width = -dst.width;
431 rop &= ~NOMIRRORBITMAP;
434 src.width = widthSrc;
436 src.height = heightSrc;
438 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
439 non_stretch_from_origin = TRUE;
441 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
443 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
444 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
447 if (rop != SRCCOPY || non_stretch_from_origin)
449 if (dst.width == 1 && src.width > 1) src.width--;
450 if (dst.height == 1 && src.height > 1) src.height--;
455 if (dst.width < 0 && dst.width == src.width)
457 /* This is off-by-one, but that's what Windows does */
460 dst.width = -dst.width;
461 src.width = -src.width;
463 if (dst.height < 0 && dst.height == src.height)
467 dst.height = -dst.height;
468 src.height = -src.height;
472 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
474 if (src.y >= height && src.y + src.height + 1 < height)
476 else if (src.y > 0 && src.y + src.height + 1 < 0)
477 src.y = -src.height - 1;
479 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
481 src.visrect.left = 0;
482 src.visrect.right = src_info->bmiHeader.biWidth;
484 src.visrect.bottom = height;
485 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
487 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
489 if (get_clip_box( dc, &clip_rect ))
490 intersect_rect( &dst.visrect, &rect, &clip_rect );
493 if (is_rect_empty( &dst.visrect )) goto done;
495 if (!intersect_vis_rectangles( &dst, &src )) goto done;
497 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
499 dev = GET_DC_PHYSDEV( dc, pPutImage );
500 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
501 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
502 if (err == ERROR_BAD_FORMAT)
504 /* 1-bpp destination without a color table requires a fake 1-entry table
505 * that contains only the background color */
506 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
508 COLORREF color = GetBkColor( dev->hdc );
509 dst_info->bmiColors[0].rgbRed = GetRValue( color );
510 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
511 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
512 dst_info->bmiColors[0].rgbReserved = 0;
513 dst_info->bmiHeader.biClrUsed = 1;
516 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
518 /* get rid of the fake 1-bpp table */
519 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
520 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
524 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
526 memcpy( src_info, dst_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
527 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
528 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
531 else if (rop == SRCCOPY) ret = height;
532 else ret = src_info->bmiHeader.biHeight;
535 if (src_bits.free) src_bits.free( &src_bits );
536 if (clip) DeleteObject( clip );
540 /***********************************************************************
541 * StretchDIBits (GDI32.@)
543 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
544 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
545 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
547 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
548 BITMAPINFO *info = (BITMAPINFO *)buffer;
553 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
555 SetLastError( ERROR_INVALID_PARAMETER );
559 if ((dc = get_dc_ptr( hdc )))
561 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
563 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
564 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
565 release_dc_ptr( dc );
571 /******************************************************************************
572 * SetDIBits [GDI32.@]
574 * Sets pixels in a bitmap using colors from DIB.
577 * hdc [I] Handle to device context
578 * hbitmap [I] Handle to bitmap
579 * startscan [I] Starting scan line
580 * lines [I] Number of scan lines
581 * bits [I] Array of bitmap bits
582 * info [I] Address of structure with data
583 * coloruse [I] Type of color indexes to use
586 * Success: Number of scan lines copied
589 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
590 UINT lines, LPCVOID bits, const BITMAPINFO *info,
594 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
595 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
596 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
597 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
600 struct gdi_image_bits src_bits;
601 struct bitblt_coords src, dst;
602 INT src_to_dst_offset;
604 const struct gdi_dc_funcs *funcs;
606 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
608 SetLastError( ERROR_INVALID_PARAMETER );
611 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
613 DWORD *masks = (DWORD *)src_info->bmiColors;
614 if (!masks[0] || !masks[1] || !masks[2])
616 SetLastError( ERROR_INVALID_PARAMETER );
621 src_bits.ptr = (void *)bits;
622 src_bits.is_copy = FALSE;
623 src_bits.free = NULL;
624 src_bits.param = NULL;
626 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, hdc )) return 0;
628 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
630 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
632 if (lines == 0) goto done;
633 else lines = src_info->bmiHeader.biHeight;
636 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
639 dst.visrect.left = 0;
641 dst.visrect.right = bitmap->bitmap.bmWidth;
642 dst.visrect.bottom = bitmap->bitmap.bmHeight;
644 src.visrect.left = 0;
646 src.visrect.right = src_info->bmiHeader.biWidth;
647 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
649 if (src_info->bmiHeader.biHeight > 0)
651 src_to_dst_offset = -startscan;
652 lines = min( lines, src.visrect.bottom - startscan );
653 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
657 src_to_dst_offset = src.visrect.bottom - lines - startscan;
658 /* Unlike the bottom-up case, Windows doesn't limit lines. */
659 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
662 funcs = get_bitmap_funcs( bitmap );
666 offset_rect( &src.visrect, 0, src_to_dst_offset );
667 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
668 src.visrect = dst.visrect;
669 offset_rect( &src.visrect, 0, -src_to_dst_offset );
671 src.x = src.visrect.left;
672 src.y = src.visrect.top;
673 src.width = src.visrect.right - src.visrect.left;
674 src.height = src.visrect.bottom - src.visrect.top;
676 dst.x = dst.visrect.left;
677 dst.y = dst.visrect.top;
678 dst.width = dst.visrect.right - dst.visrect.left;
679 dst.height = dst.visrect.bottom - dst.visrect.top;
681 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
683 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
684 if (err == ERROR_BAD_FORMAT)
688 dst_info->bmiHeader.biWidth = dst.width;
689 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
692 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
693 if (src_bits.free) src_bits.free( &src_bits );
695 src_bits.is_copy = TRUE;
696 src_bits.free = free_heap_bits;
698 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
700 else err = ERROR_OUTOFMEMORY;
705 if (src_bits.free) src_bits.free( &src_bits );
706 if (clip) DeleteObject( clip );
707 GDI_ReleaseObj( hbitmap );
712 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
713 INT x_src, INT y_src, UINT startscan, UINT lines,
714 const void *bits, BITMAPINFO *src_info, UINT coloruse )
716 DC *dc = get_nulldrv_dc( dev );
717 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
718 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
719 struct bitblt_coords src, dst;
720 struct gdi_image_bits src_bits;
728 top_down = (src_info->bmiHeader.biHeight < 0);
729 height = abs( src_info->bmiHeader.biHeight );
731 src_bits.ptr = (void *)bits;
732 src_bits.is_copy = FALSE;
733 src_bits.free = NULL;
735 if (!lines) return 0;
736 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
738 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
742 src_info->bmiHeader.biWidth = x_src + cx;
743 src_info->bmiHeader.biHeight = y_src + cy;
744 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
749 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
753 if (startscan >= height) return 0;
754 if (!top_down && lines > height - startscan) lines = height - startscan;
756 /* map src to top-down coordinates with startscan as origin */
758 src.y = startscan + lines - (y_src + cy);
765 /* get rid of unnecessary lines */
766 if (src.y >= lines) return 0;
770 else if (src.y >= lines) return lines;
772 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
775 src.visrect.left = src.x;
776 src.visrect.top = src.y;
777 src.visrect.right = src.x + cx;
778 src.visrect.bottom = src.y + cy;
781 rect.right = src_info->bmiHeader.biWidth;
782 rect.bottom = abs( src_info->bmiHeader.biHeight );
783 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
791 LPtoDP( dev->hdc, &pt, 1 );
796 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
798 dst.visrect.left = dst.x;
799 dst.visrect.top = dst.y;
800 dst.visrect.right = dst.x + cx;
801 dst.visrect.bottom = dst.y + cy;
802 if (get_clip_box( dc, &rect )) intersect_rect( &dst.visrect, &dst.visrect, &rect );
804 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
805 intersect_rect( &rect, &src.visrect, &dst.visrect );
806 src.visrect = dst.visrect = rect;
807 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
808 if (is_rect_empty( &dst.visrect )) goto done;
809 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
811 dev = GET_DC_PHYSDEV( dc, pPutImage );
812 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
813 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
814 if (err == ERROR_BAD_FORMAT)
818 dst_info->bmiHeader.biWidth = src.visrect.right - src.visrect.left;
819 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
822 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
823 if (src_bits.free) src_bits.free( &src_bits );
825 src_bits.is_copy = TRUE;
826 src_bits.free = free_heap_bits;
827 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
829 else err = ERROR_OUTOFMEMORY;
834 if (src_bits.free) src_bits.free( &src_bits );
835 if (clip) DeleteObject( clip );
839 /***********************************************************************
840 * SetDIBitsToDevice (GDI32.@)
842 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
843 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
844 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
847 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
848 BITMAPINFO *info = (BITMAPINFO *)buffer;
853 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
855 SetLastError( ERROR_INVALID_PARAMETER );
859 if ((dc = get_dc_ptr( hdc )))
861 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
863 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
864 ySrc, startscan, lines, bits, info, coloruse );
865 release_dc_ptr( dc );
870 /***********************************************************************
871 * SetDIBColorTable (GDI32.@)
873 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
879 if (!(dc = get_dc_ptr( hdc ))) return 0;
881 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
883 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
885 /* Check if currently selected bitmap is a DIB */
886 if (bitmap->color_table)
888 if (startpos < bitmap->nb_colors)
890 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
891 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
895 GDI_ReleaseObj( dc->hBitmap );
896 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
898 release_dc_ptr( dc );
903 /***********************************************************************
904 * GetDIBColorTable (GDI32.@)
906 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
912 if (!(dc = get_dc_ptr( hdc ))) return 0;
914 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
916 /* Check if currently selected bitmap is a DIB */
917 if (bitmap->color_table)
919 if (startpos < bitmap->nb_colors)
921 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
922 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
926 GDI_ReleaseObj( dc->hBitmap );
928 release_dc_ptr( dc );
932 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
933 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
934 { 0x00, 0x00, 0x00, 0x00 },
935 { 0x00, 0x00, 0x80, 0x00 },
936 { 0x00, 0x80, 0x00, 0x00 },
937 { 0x00, 0x80, 0x80, 0x00 },
938 { 0x80, 0x00, 0x00, 0x00 },
939 { 0x80, 0x00, 0x80, 0x00 },
940 { 0x80, 0x80, 0x00, 0x00 },
941 { 0xc0, 0xc0, 0xc0, 0x00 },
942 { 0xc0, 0xdc, 0xc0, 0x00 },
943 { 0xf0, 0xca, 0xa6, 0x00 },
944 { 0xf0, 0xfb, 0xff, 0x00 },
945 { 0xa4, 0xa0, 0xa0, 0x00 },
946 { 0x80, 0x80, 0x80, 0x00 },
947 { 0x00, 0x00, 0xff, 0x00 },
948 { 0x00, 0xff, 0x00, 0x00 },
949 { 0x00, 0xff, 0xff, 0x00 },
950 { 0xff, 0x00, 0x00, 0x00 },
951 { 0xff, 0x00, 0xff, 0x00 },
952 { 0xff, 0xff, 0x00, 0x00 },
953 { 0xff, 0xff, 0xff, 0x00 }
956 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
957 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
958 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
960 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
962 BITMAPINFOHEADER header;
964 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
965 header.biWidth = bmp->bitmap.bmWidth;
966 header.biHeight = bmp->bitmap.bmHeight;
971 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
972 switch (bmp->dib->dsBm.bmBitsPixel)
976 header.biCompression = BI_BITFIELDS;
979 header.biCompression = BI_RGB;
985 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
986 header.biBitCount = bmp->bitmap.bmBitsPixel;
989 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
990 header.biXPelsPerMeter = 0;
991 header.biYPelsPerMeter = 0;
992 header.biClrUsed = 0;
993 header.biClrImportant = 0;
995 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
997 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
999 coreheader->bcWidth = header.biWidth;
1000 coreheader->bcHeight = header.biHeight;
1001 coreheader->bcPlanes = header.biPlanes;
1002 coreheader->bcBitCount = header.biBitCount;
1005 info->bmiHeader = header;
1007 return abs(bmp->bitmap.bmHeight);
1010 /************************************************************************
1013 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1015 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1017 unsigned int colors = get_dib_num_of_colors( src );
1018 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
1020 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
1022 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1024 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1025 if (coloruse == DIB_PAL_COLORS)
1026 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
1030 for (i = 0; i < colors; i++)
1032 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
1033 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
1034 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
1040 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1041 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1043 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1044 /* bitfields are always at bmiColors even in larger structures */
1045 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1048 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1051 if (coloruse == DIB_PAL_COLORS)
1052 size = colors * sizeof(WORD);
1054 size = colors * sizeof(RGBQUAD);
1055 memcpy( colorptr, src_colors, size );
1060 static void fill_default_color_table( BITMAPINFO *info )
1064 switch (info->bmiHeader.biBitCount)
1067 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
1068 info->bmiColors[0].rgbReserved = 0;
1069 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
1070 info->bmiColors[1].rgbReserved = 0;
1074 /* The EGA palette is the first and last 8 colours of the default palette
1075 with the innermost pair swapped */
1076 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
1077 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
1078 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
1079 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
1083 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
1084 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
1085 for (i = 10; i < 246; i++)
1087 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
1088 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
1089 info->bmiColors[i].rgbBlue = i & 0xc0;
1090 info->bmiColors[i].rgbReserved = 0;
1095 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
1097 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1100 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1102 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1103 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1104 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1105 info->bmiHeader.biPlanes = 1;
1106 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1107 info->bmiHeader.biCompression = BI_RGB;
1108 info->bmiHeader.biXPelsPerMeter = 0;
1109 info->bmiHeader.biYPelsPerMeter = 0;
1110 info->bmiHeader.biClrUsed = 0;
1111 info->bmiHeader.biClrImportant = 0;
1112 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1116 /******************************************************************************
1117 * GetDIBits [GDI32.@]
1119 * Retrieves bits of bitmap and copies to buffer.
1122 * Success: Number of scan lines copied from bitmap
1125 INT WINAPI GetDIBits(
1126 HDC hdc, /* [in] Handle to device context */
1127 HBITMAP hbitmap, /* [in] Handle to bitmap */
1128 UINT startscan, /* [in] First scan line to set in dest bitmap */
1129 UINT lines, /* [in] Number of scan lines to copy */
1130 LPVOID bits, /* [out] Address of array for bitmap bits */
1131 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1132 UINT coloruse) /* [in] RGB or palette index */
1136 int i, dst_to_src_offset, ret = 0;
1138 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1139 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1140 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1141 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1142 const struct gdi_dc_funcs *funcs;
1143 struct gdi_image_bits src_bits;
1144 struct bitblt_coords src, dst;
1145 BOOL empty_rect = FALSE;
1147 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1148 own copy and transfer the colour info back at the end */
1149 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1151 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1153 dst_info->bmiHeader.biClrUsed = 0;
1154 dst_info->bmiHeader.biClrImportant = 0;
1156 if (!(dc = get_dc_ptr( hdc )))
1158 SetLastError( ERROR_INVALID_PARAMETER );
1162 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1164 release_dc_ptr( dc );
1168 funcs = get_bitmap_funcs( bmp );
1170 src.visrect.left = 0;
1171 src.visrect.top = 0;
1172 src.visrect.right = bmp->bitmap.bmWidth;
1173 src.visrect.bottom = bmp->bitmap.bmHeight;
1175 dst.visrect.left = 0;
1176 dst.visrect.top = 0;
1177 dst.visrect.right = dst_info->bmiHeader.biWidth;
1178 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1180 if (lines == 0 || startscan >= dst.visrect.bottom)
1183 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1185 ret = fill_query_info( info, bmp );
1189 /* validate parameters */
1191 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1192 if (dst_info->bmiHeader.biHeight == 0) goto done;
1194 switch (dst_info->bmiHeader.biCompression)
1197 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1198 if (dst_info->bmiHeader.biHeight < 0) goto done;
1199 if (bits) goto done; /* can't retrieve compressed bits */
1202 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1203 if (dst_info->bmiHeader.biHeight < 0) goto done;
1204 if (bits) goto done; /* can't retrieve compressed bits */
1207 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1210 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1211 if (dst_info->bmiHeader.biBitCount == 1) break;
1212 if (dst_info->bmiHeader.biBitCount == 4) break;
1213 if (dst_info->bmiHeader.biBitCount == 8) break;
1214 if (dst_info->bmiHeader.biBitCount == 16) break;
1215 if (dst_info->bmiHeader.biBitCount == 24) break;
1216 if (dst_info->bmiHeader.biBitCount == 32) break;
1224 if (dst_info->bmiHeader.biHeight > 0)
1226 dst_to_src_offset = -startscan;
1227 lines = min( lines, dst.visrect.bottom - startscan );
1228 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1232 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1233 if (dst_to_src_offset < 0)
1235 dst_to_src_offset = 0;
1236 lines = dst.visrect.bottom - startscan;
1238 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1241 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1242 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1243 dst.visrect = src.visrect;
1244 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1246 if (dst_info->bmiHeader.biHeight > 0)
1248 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1250 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1251 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1252 memset( bits, 0, pad_bytes );
1253 bits = (char *)bits + pad_bytes;
1258 if (dst.visrect.bottom < lines)
1260 int pad_lines = lines - dst.visrect.bottom;
1261 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1262 int pad_bytes = pad_lines * stride;
1263 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1267 if (empty_rect) bits = NULL;
1269 src.x = src.visrect.left;
1270 src.y = src.visrect.top;
1271 src.width = src.visrect.right - src.visrect.left;
1272 src.height = src.visrect.bottom - src.visrect.top;
1277 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1281 /* fill out the src colour table, if it needs one */
1282 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1283 fill_default_color_table( src_info );
1285 /* if the src and dst are the same depth, copy the colour info across */
1286 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1288 switch (src_info->bmiHeader.biBitCount)
1291 if (src_info->bmiHeader.biCompression == BI_RGB)
1293 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1294 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1298 if (src_info->bmiHeader.biCompression == BI_RGB)
1300 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1301 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1305 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1306 copy_color_info( dst_info, src_info, coloruse );
1308 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1310 if( coloruse == DIB_PAL_COLORS )
1312 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1316 fill_default_color_table( dst_info );
1322 if(dst_info->bmiHeader.biHeight > 0)
1323 dst_info->bmiHeader.biHeight = src.height;
1325 dst_info->bmiHeader.biHeight = -src.height;
1327 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1328 if (src_bits.free) src_bits.free( &src_bits );
1332 ret = empty_rect ? FALSE : TRUE;
1334 if (coloruse == DIB_PAL_COLORS)
1336 WORD *index = (WORD *)dst_info->bmiColors;
1337 int colors = get_dib_num_of_colors( dst_info );
1338 for (i = 0; i < colors; i++, index++)
1342 copy_color_info( info, dst_info, coloruse );
1345 release_dc_ptr( dc );
1346 GDI_ReleaseObj( hbitmap );
1351 /***********************************************************************
1352 * CreateDIBitmap (GDI32.@)
1354 * Creates a DDB (device dependent bitmap) from a DIB.
1355 * The DDB will have the same color depth as the reference DC.
1357 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1358 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1361 BITMAPINFOHEADER info;
1365 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1366 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1367 if (info.biWidth < 0) return 0;
1369 /* Top-down DIBs have a negative height */
1370 height = abs( info.biHeight );
1372 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1373 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1374 info.biBitCount, info.biCompression);
1377 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1379 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1383 if (init & CBM_INIT)
1385 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1387 DeleteObject( handle );
1396 /* Copy/synthesize RGB palette from BITMAPINFO */
1397 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1399 unsigned int colors, i;
1401 colors = get_dib_num_of_colors( info );
1402 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1403 bmp->nb_colors = colors;
1405 if (coloruse == DIB_RGB_COLORS)
1407 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1411 PALETTEENTRY entries[256];
1412 const WORD *index = (const WORD *)info->bmiColors;
1413 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1415 for (i = 0; i < colors; i++, index++)
1417 PALETTEENTRY *entry = &entries[*index % count];
1418 bmp->color_table[i].rgbRed = entry->peRed;
1419 bmp->color_table[i].rgbGreen = entry->peGreen;
1420 bmp->color_table[i].rgbBlue = entry->peBlue;
1421 bmp->color_table[i].rgbReserved = 0;
1426 /***********************************************************************
1427 * CreateDIBSection (GDI32.@)
1429 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1430 VOID **bits, HANDLE section, DWORD offset)
1432 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1433 BITMAPINFO *info = (BITMAPINFO *)buffer;
1436 BOOL bDesktopDC = FALSE;
1439 void *mapBits = NULL;
1441 if (bits) *bits = NULL;
1442 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1443 if (info->bmiHeader.biPlanes != 1)
1445 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1446 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1449 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1451 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1452 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1453 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1454 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1455 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1457 dib->dsBm.bmType = 0;
1458 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1459 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1460 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1461 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1462 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1463 dib->dsBm.bmBits = NULL;
1464 dib->dsBmih = info->bmiHeader;
1466 /* set number of entries in bmi.bmiColors table */
1467 if( info->bmiHeader.biBitCount <= 8 )
1468 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1470 /* set dsBitfields values */
1471 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1473 dib->dsBmih.biCompression = BI_BITFIELDS;
1474 dib->dsBitfields[0] = 0x7c00;
1475 dib->dsBitfields[1] = 0x03e0;
1476 dib->dsBitfields[2] = 0x001f;
1478 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1480 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1481 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1482 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1483 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1485 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1487 /* get storage location for DIB bits */
1491 SYSTEM_INFO SystemInfo;
1495 GetSystemInfo( &SystemInfo );
1496 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1497 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1498 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1499 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1504 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1505 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1507 dib->dshSection = section;
1508 dib->dsOffset = offset;
1510 if (!dib->dsBm.bmBits)
1512 HeapFree( GetProcessHeap(), 0, dib );
1516 /* If the reference hdc is null, take the desktop dc */
1519 hdc = CreateCompatibleDC(0);
1523 if (!(dc = get_dc_ptr( hdc ))) goto error;
1525 /* create Device Dependent Bitmap and add DIB pointer */
1526 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1527 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1529 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1531 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1533 bmp->funcs = physdev->funcs;
1534 /* create local copy of DIB palette */
1535 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1536 GDI_ReleaseObj( ret );
1538 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1540 DeleteObject( ret );
1545 release_dc_ptr( dc );
1546 if (bDesktopDC) DeleteDC( hdc );
1547 if (ret && bits) *bits = dib->dsBm.bmBits;
1551 if (bDesktopDC) DeleteDC( hdc );
1552 if (section) UnmapViewOfFile( mapBits );
1553 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1554 HeapFree( GetProcessHeap(), 0, dib );