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