gdi32: Make clip_line external.
[wine/multimedia.git] / dlls / gdi32 / dib.c
blob3739cb77805c076a4c1bead74890e0270a6e23f3
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 *clip = NULL;
257 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
259 out_bits = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ) );
260 *clip = CreateRectRgn( 0, 0, 0, 0 );
261 run = CreateRectRgn( 0, 0, 0, 0 );
262 if (!out_bits || !*clip || !run) goto fail;
264 x = left = right = 0;
265 y = height - 1;
267 while (i < info->bmiHeader.biSizeImage - 1)
269 num = in_bits[i];
270 data = in_bits[i + 1];
271 i += 2;
273 if (num)
275 if (x + num > width) num = width - x;
276 if (num)
278 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
279 if (info->bmiHeader.biBitCount == 8)
280 memset( out_ptr, s, num );
281 else
283 if(x & 1)
285 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
286 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
287 out_ptr++;
288 x++;
289 num--;
291 /* this will write one too many if num is odd, but that doesn't matter */
292 if (num) memset( out_ptr, s, (num + 1) / 2 );
295 x += num;
296 right = x;
298 else
300 if (data < 3)
302 if(left != right)
304 SetRectRgn( run, left, y, right, y + 1 );
305 CombineRgn( *clip, run, *clip, RGN_OR );
307 switch (data)
309 case 0: /* eol */
310 left = right = x = 0;
311 y--;
312 if(y < 0) goto done;
313 break;
315 case 1: /* eod */
316 goto done;
318 case 2: /* delta */
319 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
320 x += in_bits[i];
321 if (x > width) x = width;
322 left = right = x;
323 y -= in_bits[i + 1];
324 if(y < 0) goto done;
325 i += 2;
328 else /* data bytes of data */
330 num = data;
331 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
332 if (skip > info->bmiHeader.biSizeImage - i) goto done;
333 skip = (skip + 1) & ~1;
334 if (x + num > width) num = width - x;
335 if (num)
337 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
338 if (info->bmiHeader.biBitCount == 8)
339 memcpy( out_ptr, in_bits + i, num );
340 else
342 if(x & 1)
344 const BYTE *in_ptr = in_bits + i;
345 for ( ; num; num--, x++)
347 if (x & 1)
349 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
350 out_ptr++;
352 else
353 *out_ptr = (*in_ptr++ << 4) & 0xf0;
356 else
357 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
360 x += num;
361 right = x;
362 i += skip;
367 done:
368 DeleteObject( run );
369 if (bits->free) bits->free( bits );
371 bits->ptr = out_bits;
372 bits->is_copy = TRUE;
373 bits->free = free_heap_bits;
375 return TRUE;
377 fail:
378 if (run) DeleteObject( run );
379 if (*clip) DeleteObject( *clip );
380 HeapFree( GetProcessHeap(), 0, out_bits );
381 return FALSE;
386 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
387 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
388 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
389 BITMAPINFO *info, UINT coloruse, DWORD rop )
391 DC *dc = get_nulldrv_dc( dev );
392 INT ret;
393 LONG height;
394 HBITMAP hBitmap;
395 HDC hdcMem;
397 /* make sure we have a real implementation for StretchBlt and PutImage */
398 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pPutImage ) == dev)
399 return 0;
401 height = info->bmiHeader.biHeight;
403 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
404 info->bmiHeader.biCompression == BI_RGB)
406 /* Windows appears to have a fast case optimization
407 * that uses the wrong origin for top-down DIBs */
408 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
410 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
412 BITMAP bm;
413 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
414 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
415 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
416 bm.bmBitsPixel == info->bmiHeader.biBitCount && bm.bmPlanes == 1)
418 /* fast path */
419 return SetDIBits( dev->hdc, hBitmap, 0, abs( height ), bits, info, coloruse );
424 hdcMem = CreateCompatibleDC( dev->hdc );
425 hBitmap = CreateCompatibleBitmap( dev->hdc, info->bmiHeader.biWidth, height );
426 SelectObject( hdcMem, hBitmap );
427 if (coloruse == DIB_PAL_COLORS)
428 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
430 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
432 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
433 * contain all the rectangle described in bmiHeader, but only part of it.
434 * This mean that those undescribed pixels must be left untouched.
435 * So, we first copy on a memory bitmap the current content of the
436 * destination rectangle, blit the DIB bits on top of it - hence leaving
437 * the gaps untouched -, and blitting the rectangle back.
438 * This insure that gaps are untouched on the destination rectangle
440 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
441 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
443 ret = SetDIBits( hdcMem, hBitmap, 0, abs( height ), bits, info, coloruse );
444 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
445 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
446 DeleteDC( hdcMem );
447 DeleteObject( hBitmap );
448 return ret;
451 /***********************************************************************
452 * StretchDIBits (GDI32.@)
454 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
455 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
456 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
458 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
459 BITMAPINFO *info = (BITMAPINFO *)buffer;
460 DC *dc;
461 INT ret = 0;
463 if (!bits) return 0;
464 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
466 SetLastError( ERROR_INVALID_PARAMETER );
467 return 0;
470 if ((dc = get_dc_ptr( hdc )))
472 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
473 update_dc( dc );
474 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
475 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
476 release_dc_ptr( dc );
478 return ret;
482 /******************************************************************************
483 * SetDIBits [GDI32.@]
485 * Sets pixels in a bitmap using colors from DIB.
487 * PARAMS
488 * hdc [I] Handle to device context
489 * hbitmap [I] Handle to bitmap
490 * startscan [I] Starting scan line
491 * lines [I] Number of scan lines
492 * bits [I] Array of bitmap bits
493 * info [I] Address of structure with data
494 * coloruse [I] Type of color indexes to use
496 * RETURNS
497 * Success: Number of scan lines copied
498 * Failure: 0
500 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
501 UINT lines, LPCVOID bits, const BITMAPINFO *info,
502 UINT coloruse )
504 BITMAPOBJ *bitmap;
505 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
506 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
507 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
508 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
509 INT result = 0;
510 DWORD err;
511 struct gdi_image_bits src_bits;
512 struct bitblt_coords src, dst;
513 INT src_to_dst_offset;
514 HRGN clip = 0;
515 const struct gdi_dc_funcs *funcs;
517 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
519 SetLastError( ERROR_INVALID_PARAMETER );
520 return 0;
523 src_bits.ptr = (void *)bits;
524 src_bits.is_copy = FALSE;
525 src_bits.free = NULL;
526 src_bits.param = NULL;
528 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, hdc )) return 0;
530 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
532 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
534 if (lines == 0) goto done;
535 else lines = src_info->bmiHeader.biHeight;
536 startscan = 0;
538 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
541 dst.visrect.left = 0;
542 dst.visrect.top = 0;
543 dst.visrect.right = bitmap->bitmap.bmWidth;
544 dst.visrect.bottom = bitmap->bitmap.bmHeight;
546 src.visrect.left = 0;
547 src.visrect.top = 0;
548 src.visrect.right = src_info->bmiHeader.biWidth;
549 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
551 if (src_info->bmiHeader.biHeight > 0)
553 src_to_dst_offset = -startscan;
554 lines = min( lines, src.visrect.bottom - startscan );
555 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
557 else
559 src_to_dst_offset = src.visrect.bottom - lines - startscan;
560 /* Unlike the bottom-up case, Windows doesn't limit lines. */
561 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
564 funcs = get_bitmap_funcs( bitmap );
566 result = lines;
568 offset_rect( &src.visrect, 0, src_to_dst_offset );
569 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
570 src.visrect = dst.visrect;
571 offset_rect( &src.visrect, 0, -src_to_dst_offset );
573 src.x = src.visrect.left;
574 src.y = src.visrect.top;
575 src.width = src.visrect.right - src.visrect.left;
576 src.height = src.visrect.bottom - src.visrect.top;
578 dst.x = dst.visrect.left;
579 dst.y = dst.visrect.top;
580 dst.width = dst.visrect.right - dst.visrect.left;
581 dst.height = dst.visrect.bottom - dst.visrect.top;
583 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
585 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
586 if (err == ERROR_BAD_FORMAT)
588 void *ptr;
590 dst_info->bmiHeader.biWidth = dst.width;
591 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
592 if (ptr)
594 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr );
595 if (src_bits.free) src_bits.free( &src_bits );
596 src_bits.ptr = ptr;
597 src_bits.is_copy = TRUE;
598 src_bits.free = free_heap_bits;
599 if (!err)
600 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
602 else err = ERROR_OUTOFMEMORY;
604 if(err) result = 0;
606 done:
607 if (src_bits.free) src_bits.free( &src_bits );
608 if (clip) DeleteObject( clip );
609 GDI_ReleaseObj( hbitmap );
610 return result;
614 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
615 INT x_src, INT y_src, UINT startscan, UINT lines,
616 const void *bits, BITMAPINFO *src_info, UINT coloruse )
618 DC *dc = get_nulldrv_dc( dev );
619 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
620 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
621 struct bitblt_coords src, dst;
622 struct gdi_image_bits src_bits;
623 HRGN clip = 0;
624 DWORD err;
625 UINT height;
626 BOOL top_down;
627 POINT pt;
628 RECT rect;
630 top_down = (src_info->bmiHeader.biHeight < 0);
631 height = abs( src_info->bmiHeader.biHeight );
633 src_bits.ptr = (void *)bits;
634 src_bits.is_copy = FALSE;
635 src_bits.free = NULL;
637 if (!lines) return 0;
638 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
640 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
642 startscan = 0;
643 lines = height;
644 src_info->bmiHeader.biWidth = x_src + cx;
645 src_info->bmiHeader.biHeight = y_src + cy;
646 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
647 src.x = x_src;
648 src.y = 0;
649 src.width = cx;
650 src.height = cy;
651 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
653 else
655 if (startscan >= height) return 0;
656 if (!top_down && lines > height - startscan) lines = height - startscan;
658 /* map src to top-down coordinates with startscan as origin */
659 src.x = x_src;
660 src.y = startscan + lines - (y_src + cy);
661 src.width = cx;
662 src.height = cy;
663 if (src.y > 0)
665 if (!top_down)
667 /* get rid of unnecessary lines */
668 if (src.y >= lines) return 0;
669 lines -= src.y;
670 src.y = 0;
672 else if (src.y >= lines) return lines;
674 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
677 src.visrect.left = src.x;
678 src.visrect.top = src.y;
679 src.visrect.right = src.x + cx;
680 src.visrect.bottom = src.y + cy;
681 rect.left = 0;
682 rect.top = 0;
683 rect.right = src_info->bmiHeader.biWidth;
684 rect.bottom = abs( src_info->bmiHeader.biHeight );
685 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
687 lines = 0;
688 goto done;
691 pt.x = x_dst;
692 pt.y = y_dst;
693 LPtoDP( dev->hdc, &pt, 1 );
694 dst.x = pt.x;
695 dst.y = pt.y;
696 dst.width = cx;
697 dst.height = cy;
698 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
700 dst.visrect.left = dst.x;
701 dst.visrect.top = dst.y;
702 dst.visrect.right = dst.x + cx;
703 dst.visrect.bottom = dst.y + cy;
704 if (get_clip_box( dc, &rect )) intersect_rect( &dst.visrect, &dst.visrect, &rect );
706 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
707 intersect_rect( &rect, &src.visrect, &dst.visrect );
708 src.visrect = dst.visrect = rect;
709 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
710 if (is_rect_empty( &dst.visrect )) goto done;
711 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
713 dev = GET_DC_PHYSDEV( dc, pPutImage );
714 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
715 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
716 if (err == ERROR_BAD_FORMAT)
718 void *ptr;
720 dst_info->bmiHeader.biWidth = src.visrect.right - src.visrect.left;
721 ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
722 if (ptr)
724 err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr );
725 if (src_bits.free) src_bits.free( &src_bits );
726 src_bits.ptr = ptr;
727 src_bits.is_copy = TRUE;
728 src_bits.free = free_heap_bits;
729 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
731 else err = ERROR_OUTOFMEMORY;
733 if (err) lines = 0;
735 done:
736 if (src_bits.free) src_bits.free( &src_bits );
737 if (clip) DeleteObject( clip );
738 return lines;
741 /***********************************************************************
742 * SetDIBitsToDevice (GDI32.@)
744 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
745 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
746 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
747 UINT coloruse )
749 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
750 BITMAPINFO *info = (BITMAPINFO *)buffer;
751 INT ret = 0;
752 DC *dc;
754 if (!bits) return 0;
755 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
757 SetLastError( ERROR_INVALID_PARAMETER );
758 return 0;
761 if ((dc = get_dc_ptr( hdc )))
763 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
764 update_dc( dc );
765 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
766 ySrc, startscan, lines, bits, info, coloruse );
767 release_dc_ptr( dc );
769 return ret;
772 /***********************************************************************
773 * SetDIBColorTable (GDI32.@)
775 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
777 DC * dc;
778 UINT result = 0;
779 BITMAPOBJ * bitmap;
781 if (!(dc = get_dc_ptr( hdc ))) return 0;
783 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
785 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
787 /* Check if currently selected bitmap is a DIB */
788 if (bitmap->color_table)
790 if (startpos < bitmap->nb_colors)
792 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
793 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
794 result = entries;
797 GDI_ReleaseObj( dc->hBitmap );
798 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
800 release_dc_ptr( dc );
801 return result;
805 /***********************************************************************
806 * GetDIBColorTable (GDI32.@)
808 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
810 DC * dc;
811 BITMAPOBJ *bitmap;
812 UINT result = 0;
814 if (!(dc = get_dc_ptr( hdc ))) return 0;
816 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
818 /* Check if currently selected bitmap is a DIB */
819 if (bitmap->color_table)
821 if (startpos < bitmap->nb_colors)
823 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
824 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
825 result = entries;
828 GDI_ReleaseObj( dc->hBitmap );
830 release_dc_ptr( dc );
831 return result;
834 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
835 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
836 { 0x00, 0x00, 0x00, 0x00 },
837 { 0x00, 0x00, 0x80, 0x00 },
838 { 0x00, 0x80, 0x00, 0x00 },
839 { 0x00, 0x80, 0x80, 0x00 },
840 { 0x80, 0x00, 0x00, 0x00 },
841 { 0x80, 0x00, 0x80, 0x00 },
842 { 0x80, 0x80, 0x00, 0x00 },
843 { 0xc0, 0xc0, 0xc0, 0x00 },
844 { 0xc0, 0xdc, 0xc0, 0x00 },
845 { 0xf0, 0xca, 0xa6, 0x00 },
846 { 0xf0, 0xfb, 0xff, 0x00 },
847 { 0xa4, 0xa0, 0xa0, 0x00 },
848 { 0x80, 0x80, 0x80, 0x00 },
849 { 0x00, 0x00, 0xff, 0x00 },
850 { 0x00, 0xff, 0x00, 0x00 },
851 { 0x00, 0xff, 0xff, 0x00 },
852 { 0xff, 0x00, 0x00, 0x00 },
853 { 0xff, 0x00, 0xff, 0x00 },
854 { 0xff, 0xff, 0x00, 0x00 },
855 { 0xff, 0xff, 0xff, 0x00 }
858 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
859 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
860 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
862 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
864 BITMAPINFOHEADER header;
866 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
867 header.biWidth = bmp->bitmap.bmWidth;
868 header.biHeight = bmp->bitmap.bmHeight;
869 header.biPlanes = 1;
871 if (bmp->dib)
873 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
874 switch (bmp->dib->dsBm.bmBitsPixel)
876 case 16:
877 case 32:
878 header.biCompression = BI_BITFIELDS;
879 break;
880 default:
881 header.biCompression = BI_RGB;
882 break;
885 else
887 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
888 header.biBitCount = bmp->bitmap.bmBitsPixel;
891 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
892 header.biXPelsPerMeter = 0;
893 header.biYPelsPerMeter = 0;
894 header.biClrUsed = 0;
895 header.biClrImportant = 0;
897 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
899 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
901 coreheader->bcWidth = header.biWidth;
902 coreheader->bcHeight = header.biHeight;
903 coreheader->bcPlanes = header.biPlanes;
904 coreheader->bcBitCount = header.biBitCount;
906 else
907 info->bmiHeader = header;
909 return abs(bmp->bitmap.bmHeight);
912 /************************************************************************
913 * copy_color_info
915 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
917 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
919 unsigned int colors = get_dib_num_of_colors( src );
920 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
922 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
924 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
926 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
927 if (coloruse == DIB_PAL_COLORS)
928 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
929 else
931 unsigned int i;
932 for (i = 0; i < colors; i++)
934 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
935 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
936 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
940 else
942 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
943 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
945 if (src->bmiHeader.biCompression == BI_BITFIELDS)
946 /* bitfields are always at bmiColors even in larger structures */
947 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
948 else if (colors)
950 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
951 unsigned int size;
953 if (coloruse == DIB_PAL_COLORS)
954 size = colors * sizeof(WORD);
955 else
956 size = colors * sizeof(RGBQUAD);
957 memcpy( colorptr, src_colors, size );
962 static void fill_default_color_table( BITMAPINFO *info )
964 int i;
966 switch (info->bmiHeader.biBitCount)
968 case 1:
969 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
970 info->bmiColors[0].rgbReserved = 0;
971 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
972 info->bmiColors[1].rgbReserved = 0;
973 break;
975 case 4:
976 /* The EGA palette is the first and last 8 colours of the default palette
977 with the innermost pair swapped */
978 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
979 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
980 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
981 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
982 break;
984 case 8:
985 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
986 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
987 for (i = 10; i < 246; i++)
989 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
990 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
991 info->bmiColors[i].rgbBlue = i & 0xc0;
992 info->bmiColors[i].rgbReserved = 0;
994 break;
996 default:
997 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
999 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1002 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1004 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1005 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1006 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1007 info->bmiHeader.biPlanes = 1;
1008 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1009 info->bmiHeader.biCompression = BI_RGB;
1010 info->bmiHeader.biXPelsPerMeter = 0;
1011 info->bmiHeader.biYPelsPerMeter = 0;
1012 info->bmiHeader.biClrUsed = 0;
1013 info->bmiHeader.biClrImportant = 0;
1014 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1018 /******************************************************************************
1019 * GetDIBits [GDI32.@]
1021 * Retrieves bits of bitmap and copies to buffer.
1023 * RETURNS
1024 * Success: Number of scan lines copied from bitmap
1025 * Failure: 0
1027 INT WINAPI GetDIBits(
1028 HDC hdc, /* [in] Handle to device context */
1029 HBITMAP hbitmap, /* [in] Handle to bitmap */
1030 UINT startscan, /* [in] First scan line to set in dest bitmap */
1031 UINT lines, /* [in] Number of scan lines to copy */
1032 LPVOID bits, /* [out] Address of array for bitmap bits */
1033 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1034 UINT coloruse) /* [in] RGB or palette index */
1036 DC * dc;
1037 BITMAPOBJ * bmp;
1038 int i, dst_to_src_offset, ret = 0;
1039 DWORD err;
1040 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1041 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1042 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1043 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1044 const struct gdi_dc_funcs *funcs;
1045 struct gdi_image_bits src_bits;
1046 struct bitblt_coords src, dst;
1047 BOOL empty_rect = FALSE;
1049 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1050 own copy and transfer the colour info back at the end */
1051 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1052 if (bits &&
1053 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1054 return 0;
1055 dst_info->bmiHeader.biClrUsed = 0;
1056 dst_info->bmiHeader.biClrImportant = 0;
1058 if (!(dc = get_dc_ptr( hdc )))
1060 SetLastError( ERROR_INVALID_PARAMETER );
1061 return 0;
1063 update_dc( dc );
1064 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1066 release_dc_ptr( dc );
1067 return 0;
1070 funcs = get_bitmap_funcs( bmp );
1072 src.visrect.left = 0;
1073 src.visrect.top = 0;
1074 src.visrect.right = bmp->bitmap.bmWidth;
1075 src.visrect.bottom = bmp->bitmap.bmHeight;
1077 dst.visrect.left = 0;
1078 dst.visrect.top = 0;
1079 dst.visrect.right = dst_info->bmiHeader.biWidth;
1080 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1082 if (lines == 0 || startscan >= dst.visrect.bottom)
1083 bits = NULL;
1085 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1087 ret = fill_query_info( info, bmp );
1088 goto done;
1091 /* validate parameters */
1093 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1094 if (dst_info->bmiHeader.biHeight == 0) goto done;
1096 switch (dst_info->bmiHeader.biCompression)
1098 case BI_RLE4:
1099 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1100 if (dst_info->bmiHeader.biHeight < 0) goto done;
1101 if (bits) goto done; /* can't retrieve compressed bits */
1102 break;
1103 case BI_RLE8:
1104 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1105 if (dst_info->bmiHeader.biHeight < 0) goto done;
1106 if (bits) goto done; /* can't retrieve compressed bits */
1107 break;
1108 case BI_BITFIELDS:
1109 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1110 /* fall through */
1111 case BI_RGB:
1112 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1113 if (dst_info->bmiHeader.biBitCount == 1) break;
1114 if (dst_info->bmiHeader.biBitCount == 4) break;
1115 if (dst_info->bmiHeader.biBitCount == 8) break;
1116 if (dst_info->bmiHeader.biBitCount == 16) break;
1117 if (dst_info->bmiHeader.biBitCount == 24) break;
1118 if (dst_info->bmiHeader.biBitCount == 32) break;
1119 /* fall through */
1120 default:
1121 goto done;
1124 if (bits)
1126 if (dst_info->bmiHeader.biHeight > 0)
1128 dst_to_src_offset = -startscan;
1129 lines = min( lines, dst.visrect.bottom - startscan );
1130 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1132 else
1134 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1135 if (dst_to_src_offset < 0)
1137 dst_to_src_offset = 0;
1138 lines = dst.visrect.bottom - startscan;
1140 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1143 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1144 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1145 dst.visrect = src.visrect;
1146 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1148 if (dst_info->bmiHeader.biHeight > 0)
1150 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1152 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1153 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1154 memset( bits, 0, pad_bytes );
1155 bits = (char *)bits + pad_bytes;
1158 else
1160 if (dst.visrect.bottom < lines)
1162 int pad_lines = lines - dst.visrect.bottom;
1163 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1164 int pad_bytes = pad_lines * stride;
1165 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1169 if (empty_rect) bits = NULL;
1171 src.x = src.visrect.left;
1172 src.y = src.visrect.top;
1173 src.width = src.visrect.right - src.visrect.left;
1174 src.height = src.visrect.bottom - src.visrect.top;
1176 lines = src.height;
1179 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1181 if (err) goto done;
1183 /* fill out the src colour table, if it needs one */
1184 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1185 fill_default_color_table( src_info );
1187 /* if the src and dst are the same depth, copy the colour info across */
1188 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1190 switch (src_info->bmiHeader.biBitCount)
1192 case 16:
1193 if (src_info->bmiHeader.biCompression == BI_RGB)
1195 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1196 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1198 break;
1199 case 32:
1200 if (src_info->bmiHeader.biCompression == BI_RGB)
1202 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1203 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1205 break;
1207 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1208 copy_color_info( dst_info, src_info, coloruse );
1210 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1212 if( coloruse == DIB_PAL_COLORS )
1214 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1216 else
1218 fill_default_color_table( dst_info );
1222 if (bits)
1224 if(dst_info->bmiHeader.biHeight > 0)
1225 dst_info->bmiHeader.biHeight = src.height;
1226 else
1227 dst_info->bmiHeader.biHeight = -src.height;
1229 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
1230 if (src_bits.free) src_bits.free( &src_bits );
1231 ret = lines;
1233 else
1234 ret = empty_rect ? FALSE : TRUE;
1236 if (coloruse == DIB_PAL_COLORS)
1238 WORD *index = (WORD *)dst_info->bmiColors;
1239 int colors = get_dib_num_of_colors( dst_info );
1240 for (i = 0; i < colors; i++, index++)
1241 *index = i;
1244 copy_color_info( info, dst_info, coloruse );
1246 done:
1247 release_dc_ptr( dc );
1248 GDI_ReleaseObj( hbitmap );
1249 return ret;
1253 /***********************************************************************
1254 * CreateDIBitmap (GDI32.@)
1256 * Creates a DDB (device dependent bitmap) from a DIB.
1257 * The DDB will have the same color depth as the reference DC.
1259 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1260 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1261 UINT coloruse )
1263 BITMAPINFOHEADER info;
1264 HBITMAP handle;
1265 LONG height;
1267 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1268 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1269 if (info.biWidth < 0) return 0;
1271 /* Top-down DIBs have a negative height */
1272 height = abs( info.biHeight );
1274 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1275 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1276 info.biBitCount, info.biCompression);
1278 if (hdc == NULL)
1279 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1280 else
1281 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1283 if (handle)
1285 if (init & CBM_INIT)
1287 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1289 DeleteObject( handle );
1290 handle = 0;
1295 return handle;
1298 /* Copy/synthesize RGB palette from BITMAPINFO */
1299 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1301 unsigned int colors, i;
1303 colors = get_dib_num_of_colors( info );
1304 if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1305 bmp->nb_colors = colors;
1307 if (coloruse == DIB_RGB_COLORS)
1309 memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1311 else
1313 PALETTEENTRY entries[256];
1314 const WORD *index = (const WORD *)info->bmiColors;
1315 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1317 for (i = 0; i < colors; i++, index++)
1319 PALETTEENTRY *entry = &entries[*index % count];
1320 bmp->color_table[i].rgbRed = entry->peRed;
1321 bmp->color_table[i].rgbGreen = entry->peGreen;
1322 bmp->color_table[i].rgbBlue = entry->peBlue;
1323 bmp->color_table[i].rgbReserved = 0;
1328 /***********************************************************************
1329 * CreateDIBSection (GDI32.@)
1331 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1332 VOID **bits, HANDLE section, DWORD offset)
1334 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1335 BITMAPINFO *info = (BITMAPINFO *)buffer;
1336 HBITMAP ret = 0;
1337 DC *dc;
1338 BOOL bDesktopDC = FALSE;
1339 DIBSECTION *dib;
1340 BITMAPOBJ *bmp;
1341 void *mapBits = NULL;
1343 if (bits) *bits = NULL;
1344 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1345 if (info->bmiHeader.biPlanes != 1)
1347 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1348 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1351 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1353 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1354 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1355 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1356 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1357 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1359 dib->dsBm.bmType = 0;
1360 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1361 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1362 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1363 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1364 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1365 dib->dsBm.bmBits = NULL;
1366 dib->dsBmih = info->bmiHeader;
1368 /* set number of entries in bmi.bmiColors table */
1369 if( info->bmiHeader.biBitCount <= 8 )
1370 dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1372 /* set dsBitfields values */
1373 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1375 dib->dsBmih.biCompression = BI_BITFIELDS;
1376 dib->dsBitfields[0] = 0x7c00;
1377 dib->dsBitfields[1] = 0x03e0;
1378 dib->dsBitfields[2] = 0x001f;
1380 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1382 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1383 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1384 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1385 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1387 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1389 /* get storage location for DIB bits */
1391 if (section)
1393 SYSTEM_INFO SystemInfo;
1394 DWORD mapOffset;
1395 INT mapSize;
1397 GetSystemInfo( &SystemInfo );
1398 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1399 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1400 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1401 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1403 else
1405 offset = 0;
1406 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1407 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1409 dib->dshSection = section;
1410 dib->dsOffset = offset;
1412 if (!dib->dsBm.bmBits)
1414 HeapFree( GetProcessHeap(), 0, dib );
1415 return 0;
1418 /* If the reference hdc is null, take the desktop dc */
1419 if (hdc == 0)
1421 hdc = CreateCompatibleDC(0);
1422 bDesktopDC = TRUE;
1425 if (!(dc = get_dc_ptr( hdc ))) goto error;
1427 /* create Device Dependent Bitmap and add DIB pointer */
1428 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1429 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1431 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1433 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1434 bmp->dib = dib;
1435 bmp->funcs = physdev->funcs;
1436 /* create local copy of DIB palette */
1437 if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1438 GDI_ReleaseObj( ret );
1440 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1442 DeleteObject( ret );
1443 ret = 0;
1447 release_dc_ptr( dc );
1448 if (bDesktopDC) DeleteDC( hdc );
1449 if (ret && bits) *bits = dib->dsBm.bmBits;
1450 return ret;
1452 error:
1453 if (bDesktopDC) DeleteDC( hdc );
1454 if (section) UnmapViewOfFile( mapBits );
1455 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1456 HeapFree( GetProcessHeap(), 0, dib );
1457 return 0;