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 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
505 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
508 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
510 memcpy( src_info, dst_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
511 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
512 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
515 else if (rop == SRCCOPY) ret = height;
516 else ret = src_info->bmiHeader.biHeight;
519 if (src_bits.free) src_bits.free( &src_bits );
520 if (clip) DeleteObject( clip );
524 /***********************************************************************
525 * StretchDIBits (GDI32.@)
527 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
528 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
529 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
531 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
532 BITMAPINFO *info = (BITMAPINFO *)buffer;
537 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
539 SetLastError( ERROR_INVALID_PARAMETER );
543 if ((dc = get_dc_ptr( hdc )))
545 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
547 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
548 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
549 release_dc_ptr( dc );
555 /******************************************************************************
556 * SetDIBits [GDI32.@]
558 * Sets pixels in a bitmap using colors from DIB.
561 * hdc [I] Handle to device context
562 * hbitmap [I] Handle to bitmap
563 * startscan [I] Starting scan line
564 * lines [I] Number of scan lines
565 * bits [I] Array of bitmap bits
566 * info [I] Address of structure with data
567 * coloruse [I] Type of color indexes to use
570 * Success: Number of scan lines copied
573 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
574 UINT lines, LPCVOID bits, const BITMAPINFO *info,
578 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
579 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
580 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
581 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
584 struct gdi_image_bits src_bits;
585 struct bitblt_coords src, dst;
586 INT src_to_dst_offset;
588 const struct gdi_dc_funcs *funcs;
590 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
592 SetLastError( ERROR_INVALID_PARAMETER );
595 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
597 DWORD *masks = (DWORD *)src_info->bmiColors;
598 if (!masks[0] || !masks[1] || !masks[2])
600 SetLastError( ERROR_INVALID_PARAMETER );
605 src_bits.ptr = (void *)bits;
606 src_bits.is_copy = FALSE;
607 src_bits.free = NULL;
608 src_bits.param = NULL;
610 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, hdc )) return 0;
612 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
614 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
616 if (lines == 0) goto done;
617 else lines = src_info->bmiHeader.biHeight;
620 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
623 dst.visrect.left = 0;
625 dst.visrect.right = bitmap->bitmap.bmWidth;
626 dst.visrect.bottom = bitmap->bitmap.bmHeight;
628 src.visrect.left = 0;
630 src.visrect.right = src_info->bmiHeader.biWidth;
631 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
633 if (src_info->bmiHeader.biHeight > 0)
635 src_to_dst_offset = -startscan;
636 lines = min( lines, src.visrect.bottom - startscan );
637 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
641 src_to_dst_offset = src.visrect.bottom - lines - startscan;
642 /* Unlike the bottom-up case, Windows doesn't limit lines. */
643 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
646 funcs = get_bitmap_funcs( bitmap );
650 offset_rect( &src.visrect, 0, src_to_dst_offset );
651 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
652 src.visrect = dst.visrect;
653 offset_rect( &src.visrect, 0, -src_to_dst_offset );
655 src.x = src.visrect.left;
656 src.y = src.visrect.top;
657 src.width = src.visrect.right - src.visrect.left;
658 src.height = src.visrect.bottom - src.visrect.top;
660 dst.x = dst.visrect.left;
661 dst.y = dst.visrect.top;
662 dst.width = dst.visrect.right - dst.visrect.left;
663 dst.height = dst.visrect.bottom - dst.visrect.top;
665 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
667 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
668 if (err == ERROR_BAD_FORMAT)
672 dst_info->bmiHeader.biWidth = dst.width;
673 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
676 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
677 if (src_bits.free) src_bits.free( &src_bits );
679 src_bits.is_copy = TRUE;
680 src_bits.free = free_heap_bits;
682 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
684 else err = ERROR_OUTOFMEMORY;
689 if (src_bits.free) src_bits.free( &src_bits );
690 if (clip) DeleteObject( clip );
691 GDI_ReleaseObj( hbitmap );
696 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
697 INT x_src, INT y_src, UINT startscan, UINT lines,
698 const void *bits, BITMAPINFO *src_info, UINT coloruse )
700 DC *dc = get_nulldrv_dc( dev );
701 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
702 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
703 struct bitblt_coords src, dst;
704 struct gdi_image_bits src_bits;
712 top_down = (src_info->bmiHeader.biHeight < 0);
713 height = abs( src_info->bmiHeader.biHeight );
715 src_bits.ptr = (void *)bits;
716 src_bits.is_copy = FALSE;
717 src_bits.free = NULL;
719 if (!lines) return 0;
720 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
722 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
726 src_info->bmiHeader.biWidth = x_src + cx;
727 src_info->bmiHeader.biHeight = y_src + cy;
728 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
733 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
737 if (startscan >= height) return 0;
738 if (!top_down && lines > height - startscan) lines = height - startscan;
740 /* map src to top-down coordinates with startscan as origin */
742 src.y = startscan + lines - (y_src + cy);
749 /* get rid of unnecessary lines */
750 if (src.y >= lines) return 0;
754 else if (src.y >= lines) return lines;
756 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
759 src.visrect.left = src.x;
760 src.visrect.top = src.y;
761 src.visrect.right = src.x + cx;
762 src.visrect.bottom = src.y + cy;
765 rect.right = src_info->bmiHeader.biWidth;
766 rect.bottom = abs( src_info->bmiHeader.biHeight );
767 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
775 LPtoDP( dev->hdc, &pt, 1 );
780 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
782 dst.visrect.left = dst.x;
783 dst.visrect.top = dst.y;
784 dst.visrect.right = dst.x + cx;
785 dst.visrect.bottom = dst.y + cy;
786 if (get_clip_box( dc, &rect )) intersect_rect( &dst.visrect, &dst.visrect, &rect );
788 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
789 intersect_rect( &rect, &src.visrect, &dst.visrect );
790 src.visrect = dst.visrect = rect;
791 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
792 if (is_rect_empty( &dst.visrect )) goto done;
793 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
795 dev = GET_DC_PHYSDEV( dc, pPutImage );
796 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
797 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
798 if (err == ERROR_BAD_FORMAT)
802 dst_info->bmiHeader.biWidth = src.visrect.right - src.visrect.left;
803 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
806 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
807 if (src_bits.free) src_bits.free( &src_bits );
809 src_bits.is_copy = TRUE;
810 src_bits.free = free_heap_bits;
811 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
813 else err = ERROR_OUTOFMEMORY;
818 if (src_bits.free) src_bits.free( &src_bits );
819 if (clip) DeleteObject( clip );
823 /***********************************************************************
824 * SetDIBitsToDevice (GDI32.@)
826 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
827 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
828 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
831 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
832 BITMAPINFO *info = (BITMAPINFO *)buffer;
837 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
839 SetLastError( ERROR_INVALID_PARAMETER );
843 if ((dc = get_dc_ptr( hdc )))
845 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
847 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
848 ySrc, startscan, lines, bits, info, coloruse );
849 release_dc_ptr( dc );
854 /***********************************************************************
855 * SetDIBColorTable (GDI32.@)
857 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
863 if (!(dc = get_dc_ptr( hdc ))) return 0;
865 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
867 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
869 /* Check if currently selected bitmap is a DIB */
870 if (bitmap->color_table)
872 if (startpos < bitmap->nb_colors)
874 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
875 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
879 GDI_ReleaseObj( dc->hBitmap );
880 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
882 release_dc_ptr( dc );
887 /***********************************************************************
888 * GetDIBColorTable (GDI32.@)
890 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
896 if (!(dc = get_dc_ptr( hdc ))) return 0;
898 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
900 /* Check if currently selected bitmap is a DIB */
901 if (bitmap->color_table)
903 if (startpos < bitmap->nb_colors)
905 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
906 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
910 GDI_ReleaseObj( dc->hBitmap );
912 release_dc_ptr( dc );
916 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
917 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
918 { 0x00, 0x00, 0x00, 0x00 },
919 { 0x00, 0x00, 0x80, 0x00 },
920 { 0x00, 0x80, 0x00, 0x00 },
921 { 0x00, 0x80, 0x80, 0x00 },
922 { 0x80, 0x00, 0x00, 0x00 },
923 { 0x80, 0x00, 0x80, 0x00 },
924 { 0x80, 0x80, 0x00, 0x00 },
925 { 0xc0, 0xc0, 0xc0, 0x00 },
926 { 0xc0, 0xdc, 0xc0, 0x00 },
927 { 0xf0, 0xca, 0xa6, 0x00 },
928 { 0xf0, 0xfb, 0xff, 0x00 },
929 { 0xa4, 0xa0, 0xa0, 0x00 },
930 { 0x80, 0x80, 0x80, 0x00 },
931 { 0x00, 0x00, 0xff, 0x00 },
932 { 0x00, 0xff, 0x00, 0x00 },
933 { 0x00, 0xff, 0xff, 0x00 },
934 { 0xff, 0x00, 0x00, 0x00 },
935 { 0xff, 0x00, 0xff, 0x00 },
936 { 0xff, 0xff, 0x00, 0x00 },
937 { 0xff, 0xff, 0xff, 0x00 }
940 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
941 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
942 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
944 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
946 BITMAPINFOHEADER header;
948 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
949 header.biWidth = bmp->bitmap.bmWidth;
950 header.biHeight = bmp->bitmap.bmHeight;
955 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
956 switch (bmp->dib->dsBm.bmBitsPixel)
960 header.biCompression = BI_BITFIELDS;
963 header.biCompression = BI_RGB;
969 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
970 header.biBitCount = bmp->bitmap.bmBitsPixel;
973 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
974 header.biXPelsPerMeter = 0;
975 header.biYPelsPerMeter = 0;
976 header.biClrUsed = 0;
977 header.biClrImportant = 0;
979 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
981 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
983 coreheader->bcWidth = header.biWidth;
984 coreheader->bcHeight = header.biHeight;
985 coreheader->bcPlanes = header.biPlanes;
986 coreheader->bcBitCount = header.biBitCount;
989 info->bmiHeader = header;
991 return abs(bmp->bitmap.bmHeight);
994 /************************************************************************
997 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
999 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1001 unsigned int colors = get_dib_num_of_colors( src );
1002 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
1004 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
1006 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1008 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1009 if (coloruse == DIB_PAL_COLORS)
1010 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
1014 for (i = 0; i < colors; i++)
1016 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
1017 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
1018 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
1024 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1025 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1027 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1028 /* bitfields are always at bmiColors even in larger structures */
1029 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1032 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1035 if (coloruse == DIB_PAL_COLORS)
1036 size = colors * sizeof(WORD);
1038 size = colors * sizeof(RGBQUAD);
1039 memcpy( colorptr, src_colors, size );
1044 static void fill_default_color_table( BITMAPINFO *info )
1048 switch (info->bmiHeader.biBitCount)
1051 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
1052 info->bmiColors[0].rgbReserved = 0;
1053 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
1054 info->bmiColors[1].rgbReserved = 0;
1058 /* The EGA palette is the first and last 8 colours of the default palette
1059 with the innermost pair swapped */
1060 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
1061 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
1062 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
1063 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
1067 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
1068 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
1069 for (i = 10; i < 246; i++)
1071 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
1072 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
1073 info->bmiColors[i].rgbBlue = i & 0xc0;
1074 info->bmiColors[i].rgbReserved = 0;
1079 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
1081 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1084 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1086 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1087 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1088 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1089 info->bmiHeader.biPlanes = 1;
1090 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1091 info->bmiHeader.biCompression = BI_RGB;
1092 info->bmiHeader.biXPelsPerMeter = 0;
1093 info->bmiHeader.biYPelsPerMeter = 0;
1094 info->bmiHeader.biClrUsed = 0;
1095 info->bmiHeader.biClrImportant = 0;
1096 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1100 /******************************************************************************
1101 * GetDIBits [GDI32.@]
1103 * Retrieves bits of bitmap and copies to buffer.
1106 * Success: Number of scan lines copied from bitmap
1109 INT WINAPI GetDIBits(
1110 HDC hdc, /* [in] Handle to device context */
1111 HBITMAP hbitmap, /* [in] Handle to bitmap */
1112 UINT startscan, /* [in] First scan line to set in dest bitmap */
1113 UINT lines, /* [in] Number of scan lines to copy */
1114 LPVOID bits, /* [out] Address of array for bitmap bits */
1115 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1116 UINT coloruse) /* [in] RGB or palette index */
1120 int i, dst_to_src_offset, ret = 0;
1122 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1123 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1124 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1125 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1126 const struct gdi_dc_funcs *funcs;
1127 struct gdi_image_bits src_bits;
1128 struct bitblt_coords src, dst;
1129 BOOL empty_rect = FALSE;
1131 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1132 own copy and transfer the colour info back at the end */
1133 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1135 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1137 dst_info->bmiHeader.biClrUsed = 0;
1138 dst_info->bmiHeader.biClrImportant = 0;
1140 if (!(dc = get_dc_ptr( hdc )))
1142 SetLastError( ERROR_INVALID_PARAMETER );
1146 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1148 release_dc_ptr( dc );
1152 funcs = get_bitmap_funcs( bmp );
1154 src.visrect.left = 0;
1155 src.visrect.top = 0;
1156 src.visrect.right = bmp->bitmap.bmWidth;
1157 src.visrect.bottom = bmp->bitmap.bmHeight;
1159 dst.visrect.left = 0;
1160 dst.visrect.top = 0;
1161 dst.visrect.right = dst_info->bmiHeader.biWidth;
1162 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1164 if (lines == 0 || startscan >= dst.visrect.bottom)
1167 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1169 ret = fill_query_info( info, bmp );
1173 /* validate parameters */
1175 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1176 if (dst_info->bmiHeader.biHeight == 0) goto done;
1178 switch (dst_info->bmiHeader.biCompression)
1181 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1182 if (dst_info->bmiHeader.biHeight < 0) goto done;
1183 if (bits) goto done; /* can't retrieve compressed bits */
1186 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1187 if (dst_info->bmiHeader.biHeight < 0) goto done;
1188 if (bits) goto done; /* can't retrieve compressed bits */
1191 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1194 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1195 if (dst_info->bmiHeader.biBitCount == 1) break;
1196 if (dst_info->bmiHeader.biBitCount == 4) break;
1197 if (dst_info->bmiHeader.biBitCount == 8) break;
1198 if (dst_info->bmiHeader.biBitCount == 16) break;
1199 if (dst_info->bmiHeader.biBitCount == 24) break;
1200 if (dst_info->bmiHeader.biBitCount == 32) break;
1208 if (dst_info->bmiHeader.biHeight > 0)
1210 dst_to_src_offset = -startscan;
1211 lines = min( lines, dst.visrect.bottom - startscan );
1212 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1216 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1217 if (dst_to_src_offset < 0)
1219 dst_to_src_offset = 0;
1220 lines = dst.visrect.bottom - startscan;
1222 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1225 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1226 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1227 dst.visrect = src.visrect;
1228 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1230 if (dst_info->bmiHeader.biHeight > 0)
1232 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1234 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1235 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1236 memset( bits, 0, pad_bytes );
1237 bits = (char *)bits + pad_bytes;
1242 if (dst.visrect.bottom < lines)
1244 int pad_lines = lines - dst.visrect.bottom;
1245 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1246 int pad_bytes = pad_lines * stride;
1247 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1251 if (empty_rect) bits = NULL;
1253 src.x = src.visrect.left;
1254 src.y = src.visrect.top;
1255 src.width = src.visrect.right - src.visrect.left;
1256 src.height = src.visrect.bottom - src.visrect.top;
1261 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1265 /* fill out the src colour table, if it needs one */
1266 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1267 fill_default_color_table( src_info );
1269 /* if the src and dst are the same depth, copy the colour info across */
1270 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1272 switch (src_info->bmiHeader.biBitCount)
1275 if (src_info->bmiHeader.biCompression == BI_RGB)
1277 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1278 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1282 if (src_info->bmiHeader.biCompression == BI_RGB)
1284 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1285 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1289 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1290 copy_color_info( dst_info, src_info, coloruse );
1292 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1294 if( coloruse == DIB_PAL_COLORS )
1296 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1300 fill_default_color_table( dst_info );
1306 if(dst_info->bmiHeader.biHeight > 0)
1307 dst_info->bmiHeader.biHeight = src.height;
1309 dst_info->bmiHeader.biHeight = -src.height;
1311 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1312 if (src_bits.free) src_bits.free( &src_bits );
1316 ret = empty_rect ? FALSE : TRUE;
1318 if (coloruse == DIB_PAL_COLORS)
1320 WORD *index = (WORD *)dst_info->bmiColors;
1321 int colors = get_dib_num_of_colors( dst_info );
1322 for (i = 0; i < colors; i++, index++)
1326 copy_color_info( info, dst_info, coloruse );
1329 release_dc_ptr( dc );
1330 GDI_ReleaseObj( hbitmap );
1335 /***********************************************************************
1336 * CreateDIBitmap (GDI32.@)
1338 * Creates a DDB (device dependent bitmap) from a DIB.
1339 * The DDB will have the same color depth as the reference DC.
1341 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1342 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1345 BITMAPINFOHEADER info;
1349 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1350 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1351 if (info.biWidth < 0) return 0;
1353 /* Top-down DIBs have a negative height */
1354 height = abs( info.biHeight );
1356 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1357 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1358 info.biBitCount, info.biCompression);
1361 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1363 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1367 if (init & CBM_INIT)
1369 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1371 DeleteObject( handle );
1380 /* Copy/synthesize RGB palette from BITMAPINFO */
1381 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1383 unsigned int colors, i;
1385 colors = get_dib_num_of_colors( info );
1386 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1387 bmp->nb_colors = colors;
1389 if (coloruse == DIB_RGB_COLORS)
1391 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1395 PALETTEENTRY entries[256];
1396 const WORD *index = (const WORD *)info->bmiColors;
1397 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1399 for (i = 0; i < colors; i++, index++)
1401 PALETTEENTRY *entry = &entries[*index % count];
1402 bmp->color_table[i].rgbRed = entry->peRed;
1403 bmp->color_table[i].rgbGreen = entry->peGreen;
1404 bmp->color_table[i].rgbBlue = entry->peBlue;
1405 bmp->color_table[i].rgbReserved = 0;
1410 /***********************************************************************
1411 * CreateDIBSection (GDI32.@)
1413 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1414 VOID **bits, HANDLE section, DWORD offset)
1416 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1417 BITMAPINFO *info = (BITMAPINFO *)buffer;
1420 BOOL bDesktopDC = FALSE;
1423 void *mapBits = NULL;
1425 if (bits) *bits = NULL;
1426 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1427 if (info->bmiHeader.biPlanes != 1)
1429 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1430 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1433 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1435 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1436 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1437 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1438 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1439 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1441 dib->dsBm.bmType = 0;
1442 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1443 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1444 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1445 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1446 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1447 dib->dsBm.bmBits = NULL;
1448 dib->dsBmih = info->bmiHeader;
1450 /* set number of entries in bmi.bmiColors table */
1451 if( info->bmiHeader.biBitCount <= 8 )
1452 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1454 /* set dsBitfields values */
1455 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1457 dib->dsBmih.biCompression = BI_BITFIELDS;
1458 dib->dsBitfields[0] = 0x7c00;
1459 dib->dsBitfields[1] = 0x03e0;
1460 dib->dsBitfields[2] = 0x001f;
1462 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1464 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1465 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1466 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1467 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1469 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1471 /* get storage location for DIB bits */
1475 SYSTEM_INFO SystemInfo;
1479 GetSystemInfo( &SystemInfo );
1480 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1481 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1482 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1483 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1488 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1489 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1491 dib->dshSection = section;
1492 dib->dsOffset = offset;
1494 if (!dib->dsBm.bmBits)
1496 HeapFree( GetProcessHeap(), 0, dib );
1500 /* If the reference hdc is null, take the desktop dc */
1503 hdc = CreateCompatibleDC(0);
1507 if (!(dc = get_dc_ptr( hdc ))) goto error;
1509 /* create Device Dependent Bitmap and add DIB pointer */
1510 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1511 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1513 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1515 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1517 bmp->funcs = physdev->funcs;
1518 /* create local copy of DIB palette */
1519 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1520 GDI_ReleaseObj( ret );
1522 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1524 DeleteObject( ret );
1529 release_dc_ptr( dc );
1530 if (bDesktopDC) DeleteDC( hdc );
1531 if (ret && bits) *bits = dib->dsBm.bmBits;
1535 if (bDesktopDC) DeleteDC( hdc );
1536 if (section) UnmapViewOfFile( mapBits );
1537 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1538 HeapFree( GetProcessHeap(), 0, dib );