gdi32: Simplify computation of the DIB header size for internal BITMAPINFO structures.
[wine/multimedia.git] / dlls / gdi32 / dib.c
bloba08e2554a7aa74418741594a5355362ceac57ce9
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 if (info->bmiHeader.biClrUsed) colors = min( info->bmiHeader.biClrUsed, 256 );
94 else colors = info->bmiHeader.biBitCount > 8 ? 0 : 1 << info->bmiHeader.biBitCount;
95 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
96 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
97 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
101 /*******************************************************************************************
102 * Verify that the DIB parameters are valid.
104 static BOOL is_valid_dib_format( const BITMAPINFOHEADER *info, BOOL allow_compression )
106 if (info->biWidth <= 0) return FALSE;
107 if (info->biHeight == 0) return FALSE;
109 if (allow_compression && (info->biCompression == BI_RLE4 || info->biCompression == BI_RLE8))
111 if (info->biHeight < 0) return FALSE;
112 if (!info->biSizeImage) return FALSE;
113 return info->biBitCount == (info->biCompression == BI_RLE4 ? 4 : 8);
116 if (!info->biPlanes) return FALSE;
118 switch (info->biBitCount)
120 case 1:
121 case 4:
122 case 8:
123 case 24:
124 return (info->biCompression == BI_RGB);
125 case 16:
126 case 32:
127 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
128 default:
129 return FALSE;
133 /*******************************************************************************************
134 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
136 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
138 if (!info) return FALSE;
140 if (info->biSize == sizeof(BITMAPCOREHEADER))
142 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
143 dst->biWidth = core->bcWidth;
144 dst->biHeight = core->bcHeight;
145 dst->biPlanes = core->bcPlanes;
146 dst->biBitCount = core->bcBitCount;
147 dst->biCompression = BI_RGB;
148 dst->biXPelsPerMeter = 0;
149 dst->biYPelsPerMeter = 0;
150 dst->biClrUsed = 0;
151 dst->biClrImportant = 0;
153 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
155 *dst = *info;
157 else
159 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
160 return FALSE;
163 dst->biSize = sizeof(*dst);
164 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
165 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
166 return TRUE;
169 /*******************************************************************************************
170 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
172 * The resulting stanitized BITMAPINFO is guaranteed to have:
173 * - biSize set to sizeof(BITMAPINFOHEADER)
174 * - biSizeImage set to the actual image size even for non-compressed DIB
175 * - biClrUsed set to the size of the color table, and 0 only when there is no color table
176 * - color table present only for <= 8 bpp, always starts at info->bmiColors
178 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
179 UINT coloruse, BOOL allow_compression )
181 void *src_colors;
183 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
184 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
186 src_colors = (char *)info + info->bmiHeader.biSize;
188 if (dst->bmiHeader.biCompression == BI_BITFIELDS)
190 /* bitfields are always at bmiColors even in larger structures */
191 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
192 dst->bmiHeader.biClrUsed = 0;
194 else if (dst->bmiHeader.biBitCount <= 8)
196 unsigned int colors = dst->bmiHeader.biClrUsed;
197 unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
199 if (!colors) colors = max_colors;
200 else colors = min( colors, max_colors );
202 if (coloruse == DIB_PAL_COLORS)
204 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
205 max_colors = colors;
207 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
209 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
211 else
213 unsigned int i;
214 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
215 for (i = 0; i < colors; i++)
217 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
218 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
219 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
220 dst->bmiColors[i].rgbReserved = 0;
223 memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
224 dst->bmiHeader.biClrUsed = max_colors;
226 else dst->bmiHeader.biClrUsed = 0;
228 return TRUE;
231 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
233 PALETTEENTRY palEntry[256];
234 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
235 int i, colors = 1 << info->bmiHeader.biBitCount;
237 info->bmiHeader.biClrUsed = colors;
239 if (!palette) return 0;
241 memset( palEntry, 0, sizeof(palEntry) );
242 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
243 return 0;
245 for (i = 0; i < colors; i++)
247 info->bmiColors[i].rgbRed = palEntry[i].peRed;
248 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
249 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
250 info->bmiColors[i].rgbReserved = 0;
253 return colors;
256 BOOL fill_color_table_from_pal_colors( BITMAPINFO *info, HDC hdc )
258 PALETTEENTRY entries[256];
259 RGBQUAD table[256];
260 HPALETTE palette;
261 const WORD *index = (const WORD *)info->bmiColors;
262 int i, count, colors = info->bmiHeader.biClrUsed;
264 if (!colors) return TRUE;
265 if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return FALSE;
266 if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return FALSE;
268 for (i = 0; i < colors; i++, index++)
270 table[i].rgbRed = entries[*index % count].peRed;
271 table[i].rgbGreen = entries[*index % count].peGreen;
272 table[i].rgbBlue = entries[*index % count].peBlue;
273 table[i].rgbReserved = 0;
275 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
276 memcpy( info->bmiColors, table, colors * sizeof(RGBQUAD) );
277 memset( info->bmiColors + colors, 0, (info->bmiHeader.biClrUsed - colors) * sizeof(RGBQUAD) );
278 return TRUE;
281 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
283 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
284 const int bpp = info->bmiHeader.biBitCount;
286 if (height > 0)
287 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
288 else
289 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
292 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
294 int i = 0;
295 int left, right;
296 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
297 HRGN run = NULL;
298 BYTE skip, num, data;
299 BYTE *out_bits, *in_bits = bits->ptr;
301 if (clip) *clip = NULL;
303 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
305 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
306 if (!out_bits) goto fail;
308 if (clip)
310 *clip = CreateRectRgn( 0, 0, 0, 0 );
311 run = CreateRectRgn( 0, 0, 0, 0 );
312 if (!*clip || !run) goto fail;
315 x = left = right = 0;
316 y = height - 1;
318 while (i < info->bmiHeader.biSizeImage - 1)
320 num = in_bits[i];
321 data = in_bits[i + 1];
322 i += 2;
324 if (num)
326 if (x + num > width) num = width - x;
327 if (num)
329 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
330 if (info->bmiHeader.biBitCount == 8)
331 memset( out_ptr, s, num );
332 else
334 if(x & 1)
336 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
337 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
338 out_ptr++;
339 x++;
340 num--;
342 /* this will write one too many if num is odd, but that doesn't matter */
343 if (num) memset( out_ptr, s, (num + 1) / 2 );
346 x += num;
347 right = x;
349 else
351 if (data < 3)
353 if(left != right && clip)
355 SetRectRgn( run, left, y, right, y + 1 );
356 CombineRgn( *clip, run, *clip, RGN_OR );
358 switch (data)
360 case 0: /* eol */
361 left = right = x = 0;
362 y--;
363 if(y < 0) goto done;
364 break;
366 case 1: /* eod */
367 goto done;
369 case 2: /* delta */
370 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
371 x += in_bits[i];
372 if (x > width) x = width;
373 left = right = x;
374 y -= in_bits[i + 1];
375 if(y < 0) goto done;
376 i += 2;
379 else /* data bytes of data */
381 num = data;
382 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
383 if (skip > info->bmiHeader.biSizeImage - i) goto done;
384 skip = (skip + 1) & ~1;
385 if (x + num > width) num = width - x;
386 if (num)
388 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
389 if (info->bmiHeader.biBitCount == 8)
390 memcpy( out_ptr, in_bits + i, num );
391 else
393 if(x & 1)
395 const BYTE *in_ptr = in_bits + i;
396 for ( ; num; num--, x++)
398 if (x & 1)
400 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
401 out_ptr++;
403 else
404 *out_ptr = (*in_ptr++ << 4) & 0xf0;
407 else
408 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
411 x += num;
412 right = x;
413 i += skip;
418 done:
419 if (run) DeleteObject( run );
420 if (bits->free) bits->free( bits );
422 bits->ptr = out_bits;
423 bits->is_copy = TRUE;
424 bits->free = free_heap_bits;
426 return TRUE;
428 fail:
429 if (run) DeleteObject( run );
430 if (clip && *clip) DeleteObject( *clip );
431 HeapFree( GetProcessHeap(), 0, out_bits );
432 return FALSE;
437 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
438 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
439 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
441 DC *dc = get_nulldrv_dc( dev );
442 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
443 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
444 struct bitblt_coords src, dst;
445 struct gdi_image_bits src_bits;
446 DWORD err;
447 HRGN clip = NULL;
448 INT ret = 0;
449 INT height = abs( src_info->bmiHeader.biHeight );
450 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
451 RECT rect;
453 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
454 xSrc, ySrc, widthSrc, heightSrc, rop);
456 src_bits.ptr = (void*)bits;
457 src_bits.is_copy = FALSE;
458 src_bits.free = NULL;
460 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
462 rect.left = xDst;
463 rect.top = yDst;
464 rect.right = xDst + widthDst;
465 rect.bottom = yDst + heightDst;
466 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
467 dst.x = rect.left;
468 dst.y = rect.top;
469 dst.width = rect.right - rect.left;
470 dst.height = rect.bottom - rect.top;
472 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
474 dst.x += dst.width;
475 dst.width = -dst.width;
477 rop &= ~NOMIRRORBITMAP;
479 src.x = xSrc;
480 src.width = widthSrc;
481 src.y = ySrc;
482 src.height = heightSrc;
484 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
485 non_stretch_from_origin = TRUE;
487 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
489 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
490 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
493 if (rop != SRCCOPY || non_stretch_from_origin)
495 if (dst.width == 1 && src.width > 1) src.width--;
496 if (dst.height == 1 && src.height > 1) src.height--;
499 if (rop != SRCCOPY)
501 if (dst.width < 0 && dst.width == src.width)
503 /* This is off-by-one, but that's what Windows does */
504 dst.x += dst.width;
505 src.x += src.width;
506 dst.width = -dst.width;
507 src.width = -src.width;
509 if (dst.height < 0 && dst.height == src.height)
511 dst.y += dst.height;
512 src.y += src.height;
513 dst.height = -dst.height;
514 src.height = -src.height;
518 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
520 if (src.y >= height && src.y + src.height + 1 < height)
521 src.y = height - 1;
522 else if (src.y > 0 && src.y + src.height + 1 < 0)
523 src.y = -src.height - 1;
525 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
527 src.visrect.left = 0;
528 src.visrect.right = src_info->bmiHeader.biWidth;
529 src.visrect.top = 0;
530 src.visrect.bottom = height;
531 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
533 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
535 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
537 if (!intersect_vis_rectangles( &dst, &src )) goto done;
539 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
541 dev = GET_DC_PHYSDEV( dc, pPutImage );
542 copy_bitmapinfo( dst_info, src_info );
543 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
544 if (err == ERROR_BAD_FORMAT)
546 /* 1-bpp destination without a color table requires a fake 1-entry table
547 * that contains only the background color */
548 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
550 COLORREF color = GetBkColor( dev->hdc );
551 dst_info->bmiColors[0].rgbRed = GetRValue( color );
552 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
553 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
554 dst_info->bmiColors[0].rgbReserved = 0;
555 dst_info->bmiHeader.biClrUsed = 1;
558 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
560 /* get rid of the fake 1-bpp table */
561 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
562 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
566 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
568 copy_bitmapinfo( src_info, dst_info );
569 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
570 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
572 if (err) ret = 0;
573 else if (rop == SRCCOPY) ret = height;
574 else ret = src_info->bmiHeader.biHeight;
576 done:
577 if (src_bits.free) src_bits.free( &src_bits );
578 if (clip) DeleteObject( clip );
579 return ret;
582 /***********************************************************************
583 * StretchDIBits (GDI32.@)
585 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
586 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
587 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
589 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
590 BITMAPINFO *info = (BITMAPINFO *)buffer;
591 DC *dc;
592 INT ret = 0;
594 if (!bits) return 0;
595 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
597 SetLastError( ERROR_INVALID_PARAMETER );
598 return 0;
601 if ((dc = get_dc_ptr( hdc )))
603 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
604 update_dc( dc );
605 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
606 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
607 release_dc_ptr( dc );
609 return ret;
613 /******************************************************************************
614 * SetDIBits [GDI32.@]
616 * Sets pixels in a bitmap using colors from DIB.
618 * PARAMS
619 * hdc [I] Handle to device context
620 * hbitmap [I] Handle to bitmap
621 * startscan [I] Starting scan line
622 * lines [I] Number of scan lines
623 * bits [I] Array of bitmap bits
624 * info [I] Address of structure with data
625 * coloruse [I] Type of color indexes to use
627 * RETURNS
628 * Success: Number of scan lines copied
629 * Failure: 0
631 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
632 UINT lines, LPCVOID bits, const BITMAPINFO *info,
633 UINT coloruse )
635 BITMAPOBJ *bitmap;
636 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
637 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
638 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
639 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
640 INT result = 0;
641 DWORD err;
642 struct gdi_image_bits src_bits;
643 struct bitblt_coords src, dst;
644 INT src_to_dst_offset;
645 HRGN clip = 0;
646 const struct gdi_dc_funcs *funcs;
648 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
650 SetLastError( ERROR_INVALID_PARAMETER );
651 return 0;
653 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
655 DWORD *masks = (DWORD *)src_info->bmiColors;
656 if (!masks[0] || !masks[1] || !masks[2])
658 SetLastError( ERROR_INVALID_PARAMETER );
659 return 0;
663 src_bits.ptr = (void *)bits;
664 src_bits.is_copy = FALSE;
665 src_bits.free = NULL;
666 src_bits.param = NULL;
668 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
670 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
672 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
674 if (lines == 0) goto done;
675 else lines = src_info->bmiHeader.biHeight;
676 startscan = 0;
678 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
681 dst.visrect.left = 0;
682 dst.visrect.top = 0;
683 dst.visrect.right = bitmap->bitmap.bmWidth;
684 dst.visrect.bottom = bitmap->bitmap.bmHeight;
686 src.visrect.left = 0;
687 src.visrect.top = 0;
688 src.visrect.right = src_info->bmiHeader.biWidth;
689 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
691 if (src_info->bmiHeader.biHeight > 0)
693 src_to_dst_offset = -startscan;
694 lines = min( lines, src.visrect.bottom - startscan );
695 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
697 else
699 src_to_dst_offset = src.visrect.bottom - lines - startscan;
700 /* Unlike the bottom-up case, Windows doesn't limit lines. */
701 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
704 funcs = get_bitmap_funcs( bitmap );
706 result = lines;
708 offset_rect( &src.visrect, 0, src_to_dst_offset );
709 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
710 src.visrect = dst.visrect;
711 offset_rect( &src.visrect, 0, -src_to_dst_offset );
713 src.x = src.visrect.left;
714 src.y = src.visrect.top;
715 src.width = src.visrect.right - src.visrect.left;
716 src.height = src.visrect.bottom - src.visrect.top;
718 dst.x = dst.visrect.left;
719 dst.y = dst.visrect.top;
720 dst.width = dst.visrect.right - dst.visrect.left;
721 dst.height = dst.visrect.bottom - dst.visrect.top;
723 copy_bitmapinfo( dst_info, src_info );
725 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
726 if (err == ERROR_BAD_FORMAT)
728 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
729 if (!err) err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
731 if(err) result = 0;
733 done:
734 if (src_bits.free) src_bits.free( &src_bits );
735 if (clip) DeleteObject( clip );
736 GDI_ReleaseObj( hbitmap );
737 return result;
741 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
742 INT x_src, INT y_src, UINT startscan, UINT lines,
743 const void *bits, BITMAPINFO *src_info, UINT coloruse )
745 DC *dc = get_nulldrv_dc( dev );
746 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
747 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
748 struct bitblt_coords src, dst;
749 struct gdi_image_bits src_bits;
750 HRGN clip = 0;
751 DWORD err;
752 UINT height;
753 BOOL top_down;
754 POINT pt;
755 RECT rect;
757 top_down = (src_info->bmiHeader.biHeight < 0);
758 height = abs( src_info->bmiHeader.biHeight );
760 src_bits.ptr = (void *)bits;
761 src_bits.is_copy = FALSE;
762 src_bits.free = NULL;
764 if (!lines) return 0;
765 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
767 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
769 startscan = 0;
770 lines = height;
771 src_info->bmiHeader.biWidth = x_src + cx;
772 src_info->bmiHeader.biHeight = y_src + cy;
773 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
774 src.x = x_src;
775 src.y = 0;
776 src.width = cx;
777 src.height = cy;
778 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
780 else
782 if (startscan >= height) return 0;
783 if (!top_down && lines > height - startscan) lines = height - startscan;
785 /* map src to top-down coordinates with startscan as origin */
786 src.x = x_src;
787 src.y = startscan + lines - (y_src + cy);
788 src.width = cx;
789 src.height = cy;
790 if (src.y > 0)
792 if (!top_down)
794 /* get rid of unnecessary lines */
795 if (src.y >= lines) return 0;
796 lines -= src.y;
797 src.y = 0;
799 else if (src.y >= lines) return lines;
801 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
804 src.visrect.left = src.x;
805 src.visrect.top = src.y;
806 src.visrect.right = src.x + cx;
807 src.visrect.bottom = src.y + cy;
808 rect.left = 0;
809 rect.top = 0;
810 rect.right = src_info->bmiHeader.biWidth;
811 rect.bottom = abs( src_info->bmiHeader.biHeight );
812 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
814 lines = 0;
815 goto done;
818 pt.x = x_dst;
819 pt.y = y_dst;
820 LPtoDP( dev->hdc, &pt, 1 );
821 dst.x = pt.x;
822 dst.y = pt.y;
823 dst.width = cx;
824 dst.height = cy;
825 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
827 rect.left = dst.x;
828 rect.top = dst.y;
829 rect.right = dst.x + cx;
830 rect.bottom = dst.y + cy;
831 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
833 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
834 intersect_rect( &rect, &src.visrect, &dst.visrect );
835 src.visrect = dst.visrect = rect;
836 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
837 if (is_rect_empty( &dst.visrect )) goto done;
838 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
840 dev = GET_DC_PHYSDEV( dc, pPutImage );
841 copy_bitmapinfo( dst_info, src_info );
842 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
843 if (err == ERROR_BAD_FORMAT)
845 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
846 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
848 if (err) lines = 0;
850 done:
851 if (src_bits.free) src_bits.free( &src_bits );
852 if (clip) DeleteObject( clip );
853 return lines;
856 /***********************************************************************
857 * SetDIBitsToDevice (GDI32.@)
859 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
860 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
861 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
862 UINT coloruse )
864 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
865 BITMAPINFO *info = (BITMAPINFO *)buffer;
866 INT ret = 0;
867 DC *dc;
869 if (!bits) return 0;
870 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
872 SetLastError( ERROR_INVALID_PARAMETER );
873 return 0;
876 if ((dc = get_dc_ptr( hdc )))
878 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
879 update_dc( dc );
880 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
881 ySrc, startscan, lines, bits, info, coloruse );
882 release_dc_ptr( dc );
884 return ret;
887 /***********************************************************************
888 * SetDIBColorTable (GDI32.@)
890 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
892 DC * dc;
893 UINT result = 0;
894 BITMAPOBJ * bitmap;
896 if (!(dc = get_dc_ptr( hdc ))) return 0;
898 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
900 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
902 /* Check if currently selected bitmap is a DIB */
903 if (bitmap->color_table)
905 if (startpos < bitmap->dib->dsBmih.biClrUsed)
907 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
908 memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
911 GDI_ReleaseObj( dc->hBitmap );
912 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
914 release_dc_ptr( dc );
915 return result;
919 /***********************************************************************
920 * GetDIBColorTable (GDI32.@)
922 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
924 DC * dc;
925 BITMAPOBJ *bitmap;
926 UINT result = 0;
928 if (!(dc = get_dc_ptr( hdc ))) return 0;
930 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
932 /* Check if currently selected bitmap is a DIB */
933 if (bitmap->color_table)
935 if (startpos < bitmap->dib->dsBmih.biClrUsed)
937 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
938 memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
941 GDI_ReleaseObj( dc->hBitmap );
943 release_dc_ptr( dc );
944 return result;
947 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
948 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
949 { 0x00, 0x00, 0x00, 0x00 },
950 { 0x00, 0x00, 0x80, 0x00 },
951 { 0x00, 0x80, 0x00, 0x00 },
952 { 0x00, 0x80, 0x80, 0x00 },
953 { 0x80, 0x00, 0x00, 0x00 },
954 { 0x80, 0x00, 0x80, 0x00 },
955 { 0x80, 0x80, 0x00, 0x00 },
956 { 0xc0, 0xc0, 0xc0, 0x00 },
957 { 0xc0, 0xdc, 0xc0, 0x00 },
958 { 0xf0, 0xca, 0xa6, 0x00 },
959 { 0xf0, 0xfb, 0xff, 0x00 },
960 { 0xa4, 0xa0, 0xa0, 0x00 },
961 { 0x80, 0x80, 0x80, 0x00 },
962 { 0x00, 0x00, 0xff, 0x00 },
963 { 0x00, 0xff, 0x00, 0x00 },
964 { 0x00, 0xff, 0xff, 0x00 },
965 { 0xff, 0x00, 0x00, 0x00 },
966 { 0xff, 0x00, 0xff, 0x00 },
967 { 0xff, 0xff, 0x00, 0x00 },
968 { 0xff, 0xff, 0xff, 0x00 }
971 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
972 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
973 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
975 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
977 BITMAPINFOHEADER header;
979 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
980 header.biWidth = bmp->bitmap.bmWidth;
981 header.biHeight = bmp->bitmap.bmHeight;
982 header.biPlanes = 1;
984 if (bmp->dib)
986 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
987 switch (bmp->dib->dsBm.bmBitsPixel)
989 case 16:
990 case 32:
991 header.biCompression = BI_BITFIELDS;
992 break;
993 default:
994 header.biCompression = BI_RGB;
995 break;
998 else
1000 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
1001 header.biBitCount = bmp->bitmap.bmBitsPixel;
1004 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
1005 header.biXPelsPerMeter = 0;
1006 header.biYPelsPerMeter = 0;
1007 header.biClrUsed = 0;
1008 header.biClrImportant = 0;
1010 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
1012 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
1014 coreheader->bcWidth = header.biWidth;
1015 coreheader->bcHeight = header.biHeight;
1016 coreheader->bcPlanes = header.biPlanes;
1017 coreheader->bcBitCount = header.biBitCount;
1019 else
1020 info->bmiHeader = header;
1022 return abs(bmp->bitmap.bmHeight);
1025 /************************************************************************
1026 * copy_color_info
1028 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1030 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1032 assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1034 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1036 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1037 if (coloruse == DIB_PAL_COLORS)
1038 memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1039 else
1041 unsigned int i;
1042 for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1044 core->bmciColors[i].rgbtRed = src->bmiColors[i].rgbRed;
1045 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1046 core->bmciColors[i].rgbtBlue = src->bmiColors[i].rgbBlue;
1050 else
1052 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1053 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1055 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1056 /* bitfields are always at bmiColors even in larger structures */
1057 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1058 else if (src->bmiHeader.biClrUsed)
1060 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1061 unsigned int size;
1063 if (coloruse == DIB_PAL_COLORS)
1064 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1065 else
1066 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1067 memcpy( colorptr, src->bmiColors, size );
1072 void fill_default_color_table( BITMAPINFO *info )
1074 int i;
1076 switch (info->bmiHeader.biBitCount)
1078 case 1:
1079 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
1080 info->bmiColors[0].rgbReserved = 0;
1081 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
1082 info->bmiColors[1].rgbReserved = 0;
1083 break;
1085 case 4:
1086 /* The EGA palette is the first and last 8 colours of the default palette
1087 with the innermost pair swapped */
1088 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
1089 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
1090 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
1091 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
1092 break;
1094 case 8:
1095 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
1096 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
1097 for (i = 10; i < 246; i++)
1099 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
1100 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
1101 info->bmiColors[i].rgbBlue = i & 0xc0;
1102 info->bmiColors[i].rgbReserved = 0;
1104 break;
1106 default:
1107 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
1109 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1112 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1114 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1115 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1116 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1117 info->bmiHeader.biPlanes = 1;
1118 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1119 info->bmiHeader.biCompression = BI_RGB;
1120 info->bmiHeader.biXPelsPerMeter = 0;
1121 info->bmiHeader.biYPelsPerMeter = 0;
1122 info->bmiHeader.biClrUsed = 0;
1123 info->bmiHeader.biClrImportant = 0;
1124 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1127 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1129 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1130 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1131 unsigned int info_size;
1133 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1135 info_size = get_dib_info_size( info, usage );
1136 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + info->bmiHeader.biSizeImage )))
1138 memcpy( ret, info, info_size );
1139 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size( src_info, usage ),
1140 info->bmiHeader.biSizeImage );
1142 return ret;
1145 /******************************************************************************
1146 * GetDIBits [GDI32.@]
1148 * Retrieves bits of bitmap and copies to buffer.
1150 * RETURNS
1151 * Success: Number of scan lines copied from bitmap
1152 * Failure: 0
1154 INT WINAPI GetDIBits(
1155 HDC hdc, /* [in] Handle to device context */
1156 HBITMAP hbitmap, /* [in] Handle to bitmap */
1157 UINT startscan, /* [in] First scan line to set in dest bitmap */
1158 UINT lines, /* [in] Number of scan lines to copy */
1159 LPVOID bits, /* [out] Address of array for bitmap bits */
1160 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1161 UINT coloruse) /* [in] RGB or palette index */
1163 DC * dc;
1164 BITMAPOBJ * bmp;
1165 int i, dst_to_src_offset, ret = 0;
1166 DWORD err;
1167 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1168 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1169 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1170 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1171 const struct gdi_dc_funcs *funcs;
1172 struct gdi_image_bits src_bits;
1173 struct bitblt_coords src, dst;
1174 BOOL empty_rect = FALSE;
1176 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1177 own copy and transfer the colour info back at the end */
1178 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1179 if (bits &&
1180 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1181 return 0;
1182 dst_info->bmiHeader.biClrUsed = 0;
1183 dst_info->bmiHeader.biClrImportant = 0;
1185 if (!(dc = get_dc_ptr( hdc )))
1187 SetLastError( ERROR_INVALID_PARAMETER );
1188 return 0;
1190 update_dc( dc );
1191 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1193 release_dc_ptr( dc );
1194 return 0;
1197 funcs = get_bitmap_funcs( bmp );
1199 src.visrect.left = 0;
1200 src.visrect.top = 0;
1201 src.visrect.right = bmp->bitmap.bmWidth;
1202 src.visrect.bottom = bmp->bitmap.bmHeight;
1204 dst.visrect.left = 0;
1205 dst.visrect.top = 0;
1206 dst.visrect.right = dst_info->bmiHeader.biWidth;
1207 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1209 if (lines == 0 || startscan >= dst.visrect.bottom)
1210 bits = NULL;
1212 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1214 ret = fill_query_info( info, bmp );
1215 goto done;
1218 /* validate parameters */
1220 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1221 if (dst_info->bmiHeader.biHeight == 0) goto done;
1223 switch (dst_info->bmiHeader.biCompression)
1225 case BI_RLE4:
1226 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1227 if (dst_info->bmiHeader.biHeight < 0) goto done;
1228 if (bits) goto done; /* can't retrieve compressed bits */
1229 break;
1230 case BI_RLE8:
1231 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1232 if (dst_info->bmiHeader.biHeight < 0) goto done;
1233 if (bits) goto done; /* can't retrieve compressed bits */
1234 break;
1235 case BI_BITFIELDS:
1236 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1237 /* fall through */
1238 case BI_RGB:
1239 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1240 if (dst_info->bmiHeader.biBitCount == 1) break;
1241 if (dst_info->bmiHeader.biBitCount == 4) break;
1242 if (dst_info->bmiHeader.biBitCount == 8) break;
1243 if (dst_info->bmiHeader.biBitCount == 16) break;
1244 if (dst_info->bmiHeader.biBitCount == 24) break;
1245 if (dst_info->bmiHeader.biBitCount == 32) break;
1246 /* fall through */
1247 default:
1248 goto done;
1251 if (bits)
1253 if (dst_info->bmiHeader.biHeight > 0)
1255 dst_to_src_offset = -startscan;
1256 lines = min( lines, dst.visrect.bottom - startscan );
1257 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1259 else
1261 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1262 if (dst_to_src_offset < 0)
1264 dst_to_src_offset = 0;
1265 lines = dst.visrect.bottom - startscan;
1267 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1270 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1271 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1272 dst.visrect = src.visrect;
1273 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1275 if (dst_info->bmiHeader.biHeight > 0)
1277 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1279 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1280 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1281 memset( bits, 0, pad_bytes );
1282 bits = (char *)bits + pad_bytes;
1285 else
1287 if (dst.visrect.bottom < lines)
1289 int pad_lines = lines - dst.visrect.bottom;
1290 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1291 int pad_bytes = pad_lines * stride;
1292 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1296 if (empty_rect) bits = NULL;
1298 src.x = src.visrect.left;
1299 src.y = src.visrect.top;
1300 src.width = src.visrect.right - src.visrect.left;
1301 src.height = src.visrect.bottom - src.visrect.top;
1303 lines = src.height;
1306 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1308 if (err) goto done;
1310 /* fill out the src colour table, if it needs one */
1311 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1312 fill_default_color_table( src_info );
1314 /* if the src and dst are the same depth, copy the colour info across */
1315 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1317 switch (src_info->bmiHeader.biBitCount)
1319 case 16:
1320 if (src_info->bmiHeader.biCompression == BI_RGB)
1322 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1323 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1325 break;
1326 case 32:
1327 if (src_info->bmiHeader.biCompression == BI_RGB)
1329 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1330 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1332 break;
1334 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1335 copy_color_info( dst_info, src_info, coloruse );
1337 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1339 if( coloruse == DIB_PAL_COLORS )
1341 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1343 else
1345 fill_default_color_table( dst_info );
1349 if (bits)
1351 if(dst_info->bmiHeader.biHeight > 0)
1352 dst_info->bmiHeader.biHeight = src.height;
1353 else
1354 dst_info->bmiHeader.biHeight = -src.height;
1356 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1357 if (src_bits.free) src_bits.free( &src_bits );
1358 ret = lines;
1360 else
1361 ret = empty_rect ? FALSE : TRUE;
1363 if (coloruse == DIB_PAL_COLORS)
1365 WORD *index = (WORD *)dst_info->bmiColors;
1366 for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1367 *index = i;
1370 copy_color_info( info, dst_info, coloruse );
1371 if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1373 done:
1374 release_dc_ptr( dc );
1375 GDI_ReleaseObj( hbitmap );
1376 return ret;
1380 /***********************************************************************
1381 * CreateDIBitmap (GDI32.@)
1383 * Creates a DDB (device dependent bitmap) from a DIB.
1384 * The DDB will have the same color depth as the reference DC.
1386 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1387 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1388 UINT coloruse )
1390 BITMAPINFOHEADER info;
1391 HBITMAP handle;
1392 LONG height;
1394 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1395 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1396 if (info.biWidth < 0) return 0;
1398 /* Top-down DIBs have a negative height */
1399 height = abs( info.biHeight );
1401 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1402 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1403 info.biBitCount, info.biCompression);
1405 if (hdc == NULL)
1406 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1407 else
1408 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1410 if (handle)
1412 if (init & CBM_INIT)
1414 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1416 DeleteObject( handle );
1417 handle = 0;
1422 return handle;
1426 /***********************************************************************
1427 * CreateDIBSection (GDI32.@)
1429 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1430 VOID **bits, HANDLE section, DWORD offset)
1432 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1433 BITMAPINFO *info = (BITMAPINFO *)buffer;
1434 HBITMAP ret = 0;
1435 DC *dc;
1436 BOOL bDesktopDC = FALSE;
1437 DIBSECTION *dib;
1438 BITMAPOBJ *bmp;
1439 RGBQUAD *color_table = NULL;
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 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1469 if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1470 goto error;
1471 dib->dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1472 if (!(color_table = HeapAlloc( GetProcessHeap(), 0, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) )))
1473 goto error;
1474 memcpy( color_table, info->bmiColors, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) );
1477 /* set dsBitfields values */
1478 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1480 dib->dsBmih.biCompression = BI_BITFIELDS;
1481 dib->dsBitfields[0] = 0x7c00;
1482 dib->dsBitfields[1] = 0x03e0;
1483 dib->dsBitfields[2] = 0x001f;
1485 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1487 if (usage == DIB_PAL_COLORS) goto error;
1488 dib->dsBitfields[0] = *(const DWORD *)info->bmiColors;
1489 dib->dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1490 dib->dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1491 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1493 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1495 /* get storage location for DIB bits */
1497 if (section)
1499 SYSTEM_INFO SystemInfo;
1500 DWORD mapOffset;
1501 INT mapSize;
1503 GetSystemInfo( &SystemInfo );
1504 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1505 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1506 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1507 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1509 else
1511 offset = 0;
1512 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1513 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1515 dib->dshSection = section;
1516 dib->dsOffset = offset;
1518 if (!dib->dsBm.bmBits) goto error;
1520 /* If the reference hdc is null, take the desktop dc */
1521 if (hdc == 0)
1523 hdc = CreateCompatibleDC(0);
1524 bDesktopDC = TRUE;
1527 if (!(dc = get_dc_ptr( hdc ))) goto error;
1529 /* create Device Dependent Bitmap and add DIB pointer */
1530 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1531 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1533 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1535 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1536 bmp->dib = dib;
1537 bmp->funcs = physdev->funcs;
1538 bmp->color_table = color_table;
1539 GDI_ReleaseObj( ret );
1541 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1543 DeleteObject( ret );
1544 ret = 0;
1548 release_dc_ptr( dc );
1549 if (bDesktopDC) DeleteDC( hdc );
1550 if (ret && bits) *bits = dib->dsBm.bmBits;
1551 return ret;
1553 error:
1554 if (bDesktopDC) DeleteDC( hdc );
1555 if (section) UnmapViewOfFile( mapBits );
1556 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1557 HeapFree( GetProcessHeap(), 0, color_table );
1558 HeapFree( GetProcessHeap(), 0, dib );
1559 return 0;