gdi32: Introduce a unified function to perform COLORREF to pixel color mapping.
[wine.git] / dlls / gdi32 / dib.c
blob550f099d4194c3173850a95694afc0d0fcc91ac6
1 /*
2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize).
34 * The palettes are stored in different formats:
36 - BITMAPCOREINFO: Array of RGBTRIPLE
37 - BITMAPINFO: Array of RGBQUAD
40 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
43 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45 If biCompression is BI_BITFIELDS, the color masks are at the same position
46 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
47 the new headers have structure members for the masks.
50 * You should never access the color table using the bmiColors member,
51 because the passed structure may have one of the extended headers
52 mentioned above. Use this to calculate the location:
54 BITMAPINFO* info;
55 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
58 * More information:
59 Search for "Bitmap Structures" in MSDN
62 #include <stdarg.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <assert.h>
67 #include "windef.h"
68 #include "winbase.h"
69 #include "gdi_private.h"
70 #include "wine/debug.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
75 /***********************************************************************
76 * bitmap_info_size
78 * Return the size of the bitmap info structure including color table.
80 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
82 unsigned int colors, size, masks = 0;
84 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
86 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
87 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
88 return sizeof(BITMAPCOREHEADER) + colors *
89 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
91 else /* assume BITMAPINFOHEADER */
93 colors = get_dib_num_of_colors( info );
94 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
95 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
96 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
100 /*******************************************************************************************
101 * Verify that the DIB parameters are valid.
103 static BOOL is_valid_dib_format( const BITMAPINFOHEADER *info, BOOL allow_compression )
105 if (info->biWidth <= 0) return FALSE;
106 if (info->biHeight == 0) return FALSE;
108 if (allow_compression && (info->biCompression == BI_RLE4 || info->biCompression == BI_RLE8))
110 if (info->biHeight < 0) return FALSE;
111 if (!info->biSizeImage) return FALSE;
112 return info->biBitCount == (info->biCompression == BI_RLE4 ? 4 : 8);
115 if (!info->biPlanes) return FALSE;
117 switch (info->biBitCount)
119 case 1:
120 case 4:
121 case 8:
122 case 24:
123 return (info->biCompression == BI_RGB);
124 case 16:
125 case 32:
126 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
127 default:
128 return FALSE;
132 /*******************************************************************************************
133 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
135 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
137 if (!info) return FALSE;
139 if (info->biSize == sizeof(BITMAPCOREHEADER))
141 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
142 dst->biWidth = core->bcWidth;
143 dst->biHeight = core->bcHeight;
144 dst->biPlanes = core->bcPlanes;
145 dst->biBitCount = core->bcBitCount;
146 dst->biCompression = BI_RGB;
147 dst->biXPelsPerMeter = 0;
148 dst->biYPelsPerMeter = 0;
149 dst->biClrUsed = 0;
150 dst->biClrImportant = 0;
152 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
154 *dst = *info;
156 else
158 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
159 return FALSE;
162 dst->biSize = sizeof(*dst);
163 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
164 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
165 return TRUE;
168 /*******************************************************************************************
169 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
171 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
172 UINT coloruse, BOOL allow_compression )
174 void *src_colors;
175 unsigned int colors;
177 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
178 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
180 src_colors = (char *)info + info->bmiHeader.biSize;
181 colors = get_dib_num_of_colors( dst );
183 if (dst->bmiHeader.biCompression == BI_BITFIELDS)
185 /* bitfields are always at bmiColors even in larger structures */
186 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
188 else if (colors)
190 if (coloruse == DIB_PAL_COLORS)
191 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
192 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
193 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
194 else
196 unsigned int i;
197 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
198 for (i = 0; i < colors; i++)
200 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
201 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
202 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
203 dst->bmiColors[i].rgbReserved = 0;
206 dst->bmiHeader.biClrUsed = colors;
208 return TRUE;
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 ))
222 return 0;
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;
232 return colors;
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;
240 if (height > 0)
241 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
242 else
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 )
248 int i = 0;
249 int left, right;
250 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
251 HRGN run = NULL;
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;
262 if (clip)
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;
270 y = height - 1;
272 while (i < info->bmiHeader.biSizeImage - 1)
274 num = in_bits[i];
275 data = in_bits[i + 1];
276 i += 2;
278 if (num)
280 if (x + num > width) num = width - x;
281 if (num)
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 );
286 else
288 if(x & 1)
290 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
291 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
292 out_ptr++;
293 x++;
294 num--;
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 );
300 x += num;
301 right = x;
303 else
305 if (data < 3)
307 if(left != right && clip)
309 SetRectRgn( run, left, y, right, y + 1 );
310 CombineRgn( *clip, run, *clip, RGN_OR );
312 switch (data)
314 case 0: /* eol */
315 left = right = x = 0;
316 y--;
317 if(y < 0) goto done;
318 break;
320 case 1: /* eod */
321 goto done;
323 case 2: /* delta */
324 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
325 x += in_bits[i];
326 if (x > width) x = width;
327 left = right = x;
328 y -= in_bits[i + 1];
329 if(y < 0) goto done;
330 i += 2;
333 else /* data bytes of data */
335 num = 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;
340 if (num)
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 );
345 else
347 if(x & 1)
349 const BYTE *in_ptr = in_bits + i;
350 for ( ; num; num--, x++)
352 if (x & 1)
354 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
355 out_ptr++;
357 else
358 *out_ptr = (*in_ptr++ << 4) & 0xf0;
361 else
362 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
365 x += num;
366 right = x;
367 i += skip;
372 done:
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;
380 return TRUE;
382 fail:
383 if (run) DeleteObject( run );
384 if (clip && *clip) DeleteObject( *clip );
385 HeapFree( GetProcessHeap(), 0, out_bits );
386 return FALSE;
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;
400 DWORD err;
401 HRGN clip = NULL;
402 INT ret = 0;
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;
416 rect.left = xDst;
417 rect.top = yDst;
418 rect.right = xDst + widthDst;
419 rect.bottom = yDst + heightDst;
420 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
421 dst.x = rect.left;
422 dst.y = rect.top;
423 dst.width = rect.right - rect.left;
424 dst.height = rect.bottom - rect.top;
426 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
428 dst.x += dst.width;
429 dst.width = -dst.width;
431 rop &= ~NOMIRRORBITMAP;
433 src.x = xSrc;
434 src.width = widthSrc;
435 src.y = ySrc;
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--;
453 if (rop != SRCCOPY)
455 if (dst.width < 0 && dst.width == src.width)
457 /* This is off-by-one, but that's what Windows does */
458 dst.x += dst.width;
459 src.x += src.width;
460 dst.width = -dst.width;
461 src.width = -src.width;
463 if (dst.height < 0 && dst.height == src.height)
465 dst.y += dst.height;
466 src.y += 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)
475 src.y = height - 1;
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;
483 src.visrect.top = 0;
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 );
491 else
492 dst.visrect = 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 );
514 if (err) ret = 0;
515 else if (rop == SRCCOPY) ret = height;
516 else ret = src_info->bmiHeader.biHeight;
518 done:
519 if (src_bits.free) src_bits.free( &src_bits );
520 if (clip) DeleteObject( clip );
521 return ret;
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;
533 DC *dc;
534 INT ret = 0;
536 if (!bits) return 0;
537 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
539 SetLastError( ERROR_INVALID_PARAMETER );
540 return 0;
543 if ((dc = get_dc_ptr( hdc )))
545 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
546 update_dc( dc );
547 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
548 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
549 release_dc_ptr( dc );
551 return ret;
555 /******************************************************************************
556 * SetDIBits [GDI32.@]
558 * Sets pixels in a bitmap using colors from DIB.
560 * PARAMS
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
569 * RETURNS
570 * Success: Number of scan lines copied
571 * Failure: 0
573 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
574 UINT lines, LPCVOID bits, const BITMAPINFO *info,
575 UINT coloruse )
577 BITMAPOBJ *bitmap;
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;
582 INT result = 0;
583 DWORD err;
584 struct gdi_image_bits src_bits;
585 struct bitblt_coords src, dst;
586 INT src_to_dst_offset;
587 HRGN clip = 0;
588 const struct gdi_dc_funcs *funcs;
590 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
592 SetLastError( ERROR_INVALID_PARAMETER );
593 return 0;
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 );
601 return 0;
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;
618 startscan = 0;
620 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
623 dst.visrect.left = 0;
624 dst.visrect.top = 0;
625 dst.visrect.right = bitmap->bitmap.bmWidth;
626 dst.visrect.bottom = bitmap->bitmap.bmHeight;
628 src.visrect.left = 0;
629 src.visrect.top = 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;
639 else
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 );
648 result = lines;
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)
670 void *ptr;
672 dst_info->bmiHeader.biWidth = dst.width;
673 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
674 if (ptr)
676 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
677 if (src_bits.free) src_bits.free( &src_bits );
678 src_bits.ptr = ptr;
679 src_bits.is_copy = TRUE;
680 src_bits.free = free_heap_bits;
681 if (!err)
682 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
684 else err = ERROR_OUTOFMEMORY;
686 if(err) result = 0;
688 done:
689 if (src_bits.free) src_bits.free( &src_bits );
690 if (clip) DeleteObject( clip );
691 GDI_ReleaseObj( hbitmap );
692 return result;
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;
705 HRGN clip = 0;
706 DWORD err;
707 UINT height;
708 BOOL top_down;
709 POINT pt;
710 RECT rect;
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)
724 startscan = 0;
725 lines = height;
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;
729 src.x = x_src;
730 src.y = 0;
731 src.width = cx;
732 src.height = cy;
733 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
735 else
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 */
741 src.x = x_src;
742 src.y = startscan + lines - (y_src + cy);
743 src.width = cx;
744 src.height = cy;
745 if (src.y > 0)
747 if (!top_down)
749 /* get rid of unnecessary lines */
750 if (src.y >= lines) return 0;
751 lines -= src.y;
752 src.y = 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;
763 rect.left = 0;
764 rect.top = 0;
765 rect.right = src_info->bmiHeader.biWidth;
766 rect.bottom = abs( src_info->bmiHeader.biHeight );
767 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
769 lines = 0;
770 goto done;
773 pt.x = x_dst;
774 pt.y = y_dst;
775 LPtoDP( dev->hdc, &pt, 1 );
776 dst.x = pt.x;
777 dst.y = pt.y;
778 dst.width = cx;
779 dst.height = cy;
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)
800 void *ptr;
802 dst_info->bmiHeader.biWidth = src.visrect.right - src.visrect.left;
803 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
804 if (ptr)
806 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr, FALSE );
807 if (src_bits.free) src_bits.free( &src_bits );
808 src_bits.ptr = ptr;
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;
815 if (err) lines = 0;
817 done:
818 if (src_bits.free) src_bits.free( &src_bits );
819 if (clip) DeleteObject( clip );
820 return lines;
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,
829 UINT coloruse )
831 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
832 BITMAPINFO *info = (BITMAPINFO *)buffer;
833 INT ret = 0;
834 DC *dc;
836 if (!bits) return 0;
837 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
839 SetLastError( ERROR_INVALID_PARAMETER );
840 return 0;
843 if ((dc = get_dc_ptr( hdc )))
845 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
846 update_dc( dc );
847 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
848 ySrc, startscan, lines, bits, info, coloruse );
849 release_dc_ptr( dc );
851 return ret;
854 /***********************************************************************
855 * SetDIBColorTable (GDI32.@)
857 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
859 DC * dc;
860 UINT result = 0;
861 BITMAPOBJ * bitmap;
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));
876 result = entries;
879 GDI_ReleaseObj( dc->hBitmap );
880 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
882 release_dc_ptr( dc );
883 return result;
887 /***********************************************************************
888 * GetDIBColorTable (GDI32.@)
890 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
892 DC * dc;
893 BITMAPOBJ *bitmap;
894 UINT result = 0;
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));
907 result = entries;
910 GDI_ReleaseObj( dc->hBitmap );
912 release_dc_ptr( dc );
913 return result;
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;
951 header.biPlanes = 1;
953 if (bmp->dib)
955 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
956 switch (bmp->dib->dsBm.bmBitsPixel)
958 case 16:
959 case 32:
960 header.biCompression = BI_BITFIELDS;
961 break;
962 default:
963 header.biCompression = BI_RGB;
964 break;
967 else
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;
988 else
989 info->bmiHeader = header;
991 return abs(bmp->bitmap.bmHeight);
994 /************************************************************************
995 * copy_color_info
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) );
1011 else
1013 unsigned int i;
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;
1022 else
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) );
1030 else if (colors)
1032 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1033 unsigned int size;
1035 if (coloruse == DIB_PAL_COLORS)
1036 size = colors * sizeof(WORD);
1037 else
1038 size = colors * sizeof(RGBQUAD);
1039 memcpy( colorptr, src_colors, size );
1044 static void fill_default_color_table( BITMAPINFO *info )
1046 int i;
1048 switch (info->bmiHeader.biBitCount)
1050 case 1:
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;
1055 break;
1057 case 4:
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));
1064 break;
1066 case 8:
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;
1076 break;
1078 default:
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.
1105 * RETURNS
1106 * Success: Number of scan lines copied from bitmap
1107 * Failure: 0
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 */
1118 DC * dc;
1119 BITMAPOBJ * bmp;
1120 int i, dst_to_src_offset, ret = 0;
1121 DWORD err;
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;
1134 if (bits &&
1135 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1136 return 0;
1137 dst_info->bmiHeader.biClrUsed = 0;
1138 dst_info->bmiHeader.biClrImportant = 0;
1140 if (!(dc = get_dc_ptr( hdc )))
1142 SetLastError( ERROR_INVALID_PARAMETER );
1143 return 0;
1145 update_dc( dc );
1146 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1148 release_dc_ptr( dc );
1149 return 0;
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)
1165 bits = NULL;
1167 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1169 ret = fill_query_info( info, bmp );
1170 goto done;
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)
1180 case BI_RLE4:
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 */
1184 break;
1185 case BI_RLE8:
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 */
1189 break;
1190 case BI_BITFIELDS:
1191 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1192 /* fall through */
1193 case BI_RGB:
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;
1201 /* fall through */
1202 default:
1203 goto done;
1206 if (bits)
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;
1214 else
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;
1240 else
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;
1258 lines = src.height;
1261 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1263 if (err) goto done;
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)
1274 case 16:
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) );
1280 break;
1281 case 32:
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) );
1287 break;
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;
1298 else
1300 fill_default_color_table( dst_info );
1304 if (bits)
1306 if(dst_info->bmiHeader.biHeight > 0)
1307 dst_info->bmiHeader.biHeight = src.height;
1308 else
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 );
1313 ret = lines;
1315 else
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++)
1323 *index = i;
1326 copy_color_info( info, dst_info, coloruse );
1328 done:
1329 release_dc_ptr( dc );
1330 GDI_ReleaseObj( hbitmap );
1331 return ret;
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,
1343 UINT coloruse )
1345 BITMAPINFOHEADER info;
1346 HBITMAP handle;
1347 LONG height;
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);
1360 if (hdc == NULL)
1361 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1362 else
1363 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1365 if (handle)
1367 if (init & CBM_INIT)
1369 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1371 DeleteObject( handle );
1372 handle = 0;
1377 return 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));
1393 else
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;
1418 HBITMAP ret = 0;
1419 DC *dc;
1420 BOOL bDesktopDC = FALSE;
1421 DIBSECTION *dib;
1422 BITMAPOBJ *bmp;
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 */
1473 if (section)
1475 SYSTEM_INFO SystemInfo;
1476 DWORD mapOffset;
1477 INT mapSize;
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);
1485 else
1487 offset = 0;
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 );
1497 return 0;
1500 /* If the reference hdc is null, take the desktop dc */
1501 if (hdc == 0)
1503 hdc = CreateCompatibleDC(0);
1504 bDesktopDC = TRUE;
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 );
1516 bmp->dib = dib;
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 );
1525 ret = 0;
1529 release_dc_ptr( dc );
1530 if (bDesktopDC) DeleteDC( hdc );
1531 if (ret && bits) *bits = dib->dsBm.bmBits;
1532 return ret;
1534 error:
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 );
1539 return 0;