gdi32: Always allocate a full-size color table when creating a DIB section.
[wine/multimedia.git] / dlls / gdi32 / dib.c
blob2cc89fd0bf41efa1355796161024f3aeb1d4b8b0
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;
176 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
177 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
179 src_colors = (char *)info + info->bmiHeader.biSize;
181 if (dst->bmiHeader.biCompression == BI_BITFIELDS)
183 /* bitfields are always at bmiColors even in larger structures */
184 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
185 dst->bmiHeader.biClrUsed = 0;
187 else if (dst->bmiHeader.biBitCount <= 8)
189 unsigned int colors = dst->bmiHeader.biClrUsed;
190 unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
192 if (!colors) colors = max_colors;
193 else colors = min( colors, max_colors );
195 if (coloruse == DIB_PAL_COLORS)
197 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
198 max_colors = colors;
200 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
202 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
204 else
206 unsigned int i;
207 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
208 for (i = 0; i < colors; i++)
210 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
211 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
212 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
213 dst->bmiColors[i].rgbReserved = 0;
216 memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
217 dst->bmiHeader.biClrUsed = max_colors;
219 else dst->bmiHeader.biClrUsed = 0;
221 return TRUE;
224 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
226 PALETTEENTRY palEntry[256];
227 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
228 int i, colors = get_dib_num_of_colors( info );
230 if (!palette) return 0;
231 if (!colors) return 0;
233 memset( palEntry, 0, sizeof(palEntry) );
234 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
235 return 0;
237 for (i = 0; i < colors; i++)
239 info->bmiColors[i].rgbRed = palEntry[i].peRed;
240 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
241 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
242 info->bmiColors[i].rgbReserved = 0;
245 return colors;
248 int fill_color_table_from_pal_colors( HDC hdc, const BITMAPINFO *info, RGBQUAD *color_table )
250 PALETTEENTRY entries[256];
251 RGBQUAD table[256];
252 HPALETTE palette;
253 const WORD *index = (const WORD *)info->bmiColors;
254 int i, count, colors = info->bmiHeader.biClrUsed;
256 if (!colors) return 0;
257 if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return 0;
258 if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return 0;
260 for (i = 0; i < colors; i++, index++)
262 table[i].rgbRed = entries[*index % count].peRed;
263 table[i].rgbGreen = entries[*index % count].peGreen;
264 table[i].rgbBlue = entries[*index % count].peBlue;
265 table[i].rgbReserved = 0;
267 memcpy( color_table, table, colors * sizeof(RGBQUAD) );
268 memset( color_table + colors, 0, ((1 << info->bmiHeader.biBitCount) - colors) * sizeof(RGBQUAD) );
269 return colors;
272 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
274 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
275 const int bpp = info->bmiHeader.biBitCount;
277 if (height > 0)
278 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
279 else
280 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
283 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
285 int i = 0;
286 int left, right;
287 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
288 HRGN run = NULL;
289 BYTE skip, num, data;
290 BYTE *out_bits, *in_bits = bits->ptr;
292 if (clip) *clip = NULL;
294 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
296 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
297 if (!out_bits) goto fail;
299 if (clip)
301 *clip = CreateRectRgn( 0, 0, 0, 0 );
302 run = CreateRectRgn( 0, 0, 0, 0 );
303 if (!*clip || !run) goto fail;
306 x = left = right = 0;
307 y = height - 1;
309 while (i < info->bmiHeader.biSizeImage - 1)
311 num = in_bits[i];
312 data = in_bits[i + 1];
313 i += 2;
315 if (num)
317 if (x + num > width) num = width - x;
318 if (num)
320 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
321 if (info->bmiHeader.biBitCount == 8)
322 memset( out_ptr, s, num );
323 else
325 if(x & 1)
327 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
328 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
329 out_ptr++;
330 x++;
331 num--;
333 /* this will write one too many if num is odd, but that doesn't matter */
334 if (num) memset( out_ptr, s, (num + 1) / 2 );
337 x += num;
338 right = x;
340 else
342 if (data < 3)
344 if(left != right && clip)
346 SetRectRgn( run, left, y, right, y + 1 );
347 CombineRgn( *clip, run, *clip, RGN_OR );
349 switch (data)
351 case 0: /* eol */
352 left = right = x = 0;
353 y--;
354 if(y < 0) goto done;
355 break;
357 case 1: /* eod */
358 goto done;
360 case 2: /* delta */
361 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
362 x += in_bits[i];
363 if (x > width) x = width;
364 left = right = x;
365 y -= in_bits[i + 1];
366 if(y < 0) goto done;
367 i += 2;
370 else /* data bytes of data */
372 num = data;
373 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
374 if (skip > info->bmiHeader.biSizeImage - i) goto done;
375 skip = (skip + 1) & ~1;
376 if (x + num > width) num = width - x;
377 if (num)
379 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
380 if (info->bmiHeader.biBitCount == 8)
381 memcpy( out_ptr, in_bits + i, num );
382 else
384 if(x & 1)
386 const BYTE *in_ptr = in_bits + i;
387 for ( ; num; num--, x++)
389 if (x & 1)
391 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
392 out_ptr++;
394 else
395 *out_ptr = (*in_ptr++ << 4) & 0xf0;
398 else
399 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
402 x += num;
403 right = x;
404 i += skip;
409 done:
410 if (run) DeleteObject( run );
411 if (bits->free) bits->free( bits );
413 bits->ptr = out_bits;
414 bits->is_copy = TRUE;
415 bits->free = free_heap_bits;
417 return TRUE;
419 fail:
420 if (run) DeleteObject( run );
421 if (clip && *clip) DeleteObject( *clip );
422 HeapFree( GetProcessHeap(), 0, out_bits );
423 return FALSE;
428 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
429 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
430 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
432 DC *dc = get_nulldrv_dc( dev );
433 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
434 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
435 struct bitblt_coords src, dst;
436 struct gdi_image_bits src_bits;
437 DWORD err;
438 HRGN clip = NULL;
439 INT ret = 0;
440 INT height = abs( src_info->bmiHeader.biHeight );
441 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
442 RECT rect;
444 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
445 xSrc, ySrc, widthSrc, heightSrc, rop);
447 src_bits.ptr = (void*)bits;
448 src_bits.is_copy = FALSE;
449 src_bits.free = NULL;
451 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
453 rect.left = xDst;
454 rect.top = yDst;
455 rect.right = xDst + widthDst;
456 rect.bottom = yDst + heightDst;
457 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
458 dst.x = rect.left;
459 dst.y = rect.top;
460 dst.width = rect.right - rect.left;
461 dst.height = rect.bottom - rect.top;
463 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
465 dst.x += dst.width;
466 dst.width = -dst.width;
468 rop &= ~NOMIRRORBITMAP;
470 src.x = xSrc;
471 src.width = widthSrc;
472 src.y = ySrc;
473 src.height = heightSrc;
475 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
476 non_stretch_from_origin = TRUE;
478 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
480 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
481 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
484 if (rop != SRCCOPY || non_stretch_from_origin)
486 if (dst.width == 1 && src.width > 1) src.width--;
487 if (dst.height == 1 && src.height > 1) src.height--;
490 if (rop != SRCCOPY)
492 if (dst.width < 0 && dst.width == src.width)
494 /* This is off-by-one, but that's what Windows does */
495 dst.x += dst.width;
496 src.x += src.width;
497 dst.width = -dst.width;
498 src.width = -src.width;
500 if (dst.height < 0 && dst.height == src.height)
502 dst.y += dst.height;
503 src.y += src.height;
504 dst.height = -dst.height;
505 src.height = -src.height;
509 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
511 if (src.y >= height && src.y + src.height + 1 < height)
512 src.y = height - 1;
513 else if (src.y > 0 && src.y + src.height + 1 < 0)
514 src.y = -src.height - 1;
516 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
518 src.visrect.left = 0;
519 src.visrect.right = src_info->bmiHeader.biWidth;
520 src.visrect.top = 0;
521 src.visrect.bottom = height;
522 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
524 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
526 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
528 if (!intersect_vis_rectangles( &dst, &src )) goto done;
530 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
532 dev = GET_DC_PHYSDEV( dc, pPutImage );
533 copy_bitmapinfo( dst_info, src_info );
534 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
535 if (err == ERROR_BAD_FORMAT)
537 /* 1-bpp destination without a color table requires a fake 1-entry table
538 * that contains only the background color */
539 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
541 COLORREF color = GetBkColor( dev->hdc );
542 dst_info->bmiColors[0].rgbRed = GetRValue( color );
543 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
544 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
545 dst_info->bmiColors[0].rgbReserved = 0;
546 dst_info->bmiHeader.biClrUsed = 1;
549 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
551 /* get rid of the fake 1-bpp table */
552 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
553 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
557 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
559 copy_bitmapinfo( src_info, dst_info );
560 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
561 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
563 if (err) ret = 0;
564 else if (rop == SRCCOPY) ret = height;
565 else ret = src_info->bmiHeader.biHeight;
567 done:
568 if (src_bits.free) src_bits.free( &src_bits );
569 if (clip) DeleteObject( clip );
570 return ret;
573 /***********************************************************************
574 * StretchDIBits (GDI32.@)
576 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
577 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
578 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
580 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
581 BITMAPINFO *info = (BITMAPINFO *)buffer;
582 DC *dc;
583 INT ret = 0;
585 if (!bits) return 0;
586 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
588 SetLastError( ERROR_INVALID_PARAMETER );
589 return 0;
592 if ((dc = get_dc_ptr( hdc )))
594 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
595 update_dc( dc );
596 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
597 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
598 release_dc_ptr( dc );
600 return ret;
604 /******************************************************************************
605 * SetDIBits [GDI32.@]
607 * Sets pixels in a bitmap using colors from DIB.
609 * PARAMS
610 * hdc [I] Handle to device context
611 * hbitmap [I] Handle to bitmap
612 * startscan [I] Starting scan line
613 * lines [I] Number of scan lines
614 * bits [I] Array of bitmap bits
615 * info [I] Address of structure with data
616 * coloruse [I] Type of color indexes to use
618 * RETURNS
619 * Success: Number of scan lines copied
620 * Failure: 0
622 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
623 UINT lines, LPCVOID bits, const BITMAPINFO *info,
624 UINT coloruse )
626 BITMAPOBJ *bitmap;
627 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
628 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
629 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
630 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
631 INT result = 0;
632 DWORD err;
633 struct gdi_image_bits src_bits;
634 struct bitblt_coords src, dst;
635 INT src_to_dst_offset;
636 HRGN clip = 0;
637 const struct gdi_dc_funcs *funcs;
639 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
641 SetLastError( ERROR_INVALID_PARAMETER );
642 return 0;
644 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
646 DWORD *masks = (DWORD *)src_info->bmiColors;
647 if (!masks[0] || !masks[1] || !masks[2])
649 SetLastError( ERROR_INVALID_PARAMETER );
650 return 0;
654 src_bits.ptr = (void *)bits;
655 src_bits.is_copy = FALSE;
656 src_bits.free = NULL;
657 src_bits.param = NULL;
659 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, hdc )) return 0;
661 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
663 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
665 if (lines == 0) goto done;
666 else lines = src_info->bmiHeader.biHeight;
667 startscan = 0;
669 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
672 dst.visrect.left = 0;
673 dst.visrect.top = 0;
674 dst.visrect.right = bitmap->bitmap.bmWidth;
675 dst.visrect.bottom = bitmap->bitmap.bmHeight;
677 src.visrect.left = 0;
678 src.visrect.top = 0;
679 src.visrect.right = src_info->bmiHeader.biWidth;
680 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
682 if (src_info->bmiHeader.biHeight > 0)
684 src_to_dst_offset = -startscan;
685 lines = min( lines, src.visrect.bottom - startscan );
686 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
688 else
690 src_to_dst_offset = src.visrect.bottom - lines - startscan;
691 /* Unlike the bottom-up case, Windows doesn't limit lines. */
692 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
695 funcs = get_bitmap_funcs( bitmap );
697 result = lines;
699 offset_rect( &src.visrect, 0, src_to_dst_offset );
700 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
701 src.visrect = dst.visrect;
702 offset_rect( &src.visrect, 0, -src_to_dst_offset );
704 src.x = src.visrect.left;
705 src.y = src.visrect.top;
706 src.width = src.visrect.right - src.visrect.left;
707 src.height = src.visrect.bottom - src.visrect.top;
709 dst.x = dst.visrect.left;
710 dst.y = dst.visrect.top;
711 dst.width = dst.visrect.right - dst.visrect.left;
712 dst.height = dst.visrect.bottom - dst.visrect.top;
714 copy_bitmapinfo( dst_info, src_info );
716 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
717 if (err == ERROR_BAD_FORMAT)
719 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
720 if (!err) err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
722 if(err) result = 0;
724 done:
725 if (src_bits.free) src_bits.free( &src_bits );
726 if (clip) DeleteObject( clip );
727 GDI_ReleaseObj( hbitmap );
728 return result;
732 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
733 INT x_src, INT y_src, UINT startscan, UINT lines,
734 const void *bits, BITMAPINFO *src_info, UINT coloruse )
736 DC *dc = get_nulldrv_dc( dev );
737 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
738 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
739 struct bitblt_coords src, dst;
740 struct gdi_image_bits src_bits;
741 HRGN clip = 0;
742 DWORD err;
743 UINT height;
744 BOOL top_down;
745 POINT pt;
746 RECT rect;
748 top_down = (src_info->bmiHeader.biHeight < 0);
749 height = abs( src_info->bmiHeader.biHeight );
751 src_bits.ptr = (void *)bits;
752 src_bits.is_copy = FALSE;
753 src_bits.free = NULL;
755 if (!lines) return 0;
756 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
758 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
760 startscan = 0;
761 lines = height;
762 src_info->bmiHeader.biWidth = x_src + cx;
763 src_info->bmiHeader.biHeight = y_src + cy;
764 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
765 src.x = x_src;
766 src.y = 0;
767 src.width = cx;
768 src.height = cy;
769 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
771 else
773 if (startscan >= height) return 0;
774 if (!top_down && lines > height - startscan) lines = height - startscan;
776 /* map src to top-down coordinates with startscan as origin */
777 src.x = x_src;
778 src.y = startscan + lines - (y_src + cy);
779 src.width = cx;
780 src.height = cy;
781 if (src.y > 0)
783 if (!top_down)
785 /* get rid of unnecessary lines */
786 if (src.y >= lines) return 0;
787 lines -= src.y;
788 src.y = 0;
790 else if (src.y >= lines) return lines;
792 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
795 src.visrect.left = src.x;
796 src.visrect.top = src.y;
797 src.visrect.right = src.x + cx;
798 src.visrect.bottom = src.y + cy;
799 rect.left = 0;
800 rect.top = 0;
801 rect.right = src_info->bmiHeader.biWidth;
802 rect.bottom = abs( src_info->bmiHeader.biHeight );
803 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
805 lines = 0;
806 goto done;
809 pt.x = x_dst;
810 pt.y = y_dst;
811 LPtoDP( dev->hdc, &pt, 1 );
812 dst.x = pt.x;
813 dst.y = pt.y;
814 dst.width = cx;
815 dst.height = cy;
816 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
818 rect.left = dst.x;
819 rect.top = dst.y;
820 rect.right = dst.x + cx;
821 rect.bottom = dst.y + cy;
822 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
824 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
825 intersect_rect( &rect, &src.visrect, &dst.visrect );
826 src.visrect = dst.visrect = rect;
827 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
828 if (is_rect_empty( &dst.visrect )) goto done;
829 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
831 dev = GET_DC_PHYSDEV( dc, pPutImage );
832 copy_bitmapinfo( dst_info, src_info );
833 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
834 if (err == ERROR_BAD_FORMAT)
836 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
837 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
839 if (err) lines = 0;
841 done:
842 if (src_bits.free) src_bits.free( &src_bits );
843 if (clip) DeleteObject( clip );
844 return lines;
847 /***********************************************************************
848 * SetDIBitsToDevice (GDI32.@)
850 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
851 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
852 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
853 UINT coloruse )
855 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
856 BITMAPINFO *info = (BITMAPINFO *)buffer;
857 INT ret = 0;
858 DC *dc;
860 if (!bits) return 0;
861 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
863 SetLastError( ERROR_INVALID_PARAMETER );
864 return 0;
867 if ((dc = get_dc_ptr( hdc )))
869 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
870 update_dc( dc );
871 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
872 ySrc, startscan, lines, bits, info, coloruse );
873 release_dc_ptr( dc );
875 return ret;
878 /***********************************************************************
879 * SetDIBColorTable (GDI32.@)
881 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
883 DC * dc;
884 UINT result = 0;
885 BITMAPOBJ * bitmap;
887 if (!(dc = get_dc_ptr( hdc ))) return 0;
889 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
891 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
893 /* Check if currently selected bitmap is a DIB */
894 if (bitmap->color_table)
896 if (startpos < bitmap->nb_colors)
898 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
899 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
900 result = entries;
903 GDI_ReleaseObj( dc->hBitmap );
904 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
906 release_dc_ptr( dc );
907 return result;
911 /***********************************************************************
912 * GetDIBColorTable (GDI32.@)
914 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
916 DC * dc;
917 BITMAPOBJ *bitmap;
918 UINT result = 0;
920 if (!(dc = get_dc_ptr( hdc ))) return 0;
922 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
924 /* Check if currently selected bitmap is a DIB */
925 if (bitmap->color_table)
927 if (startpos < bitmap->nb_colors)
929 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
930 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
931 result = entries;
934 GDI_ReleaseObj( dc->hBitmap );
936 release_dc_ptr( dc );
937 return result;
940 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
941 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
942 { 0x00, 0x00, 0x00, 0x00 },
943 { 0x00, 0x00, 0x80, 0x00 },
944 { 0x00, 0x80, 0x00, 0x00 },
945 { 0x00, 0x80, 0x80, 0x00 },
946 { 0x80, 0x00, 0x00, 0x00 },
947 { 0x80, 0x00, 0x80, 0x00 },
948 { 0x80, 0x80, 0x00, 0x00 },
949 { 0xc0, 0xc0, 0xc0, 0x00 },
950 { 0xc0, 0xdc, 0xc0, 0x00 },
951 { 0xf0, 0xca, 0xa6, 0x00 },
952 { 0xf0, 0xfb, 0xff, 0x00 },
953 { 0xa4, 0xa0, 0xa0, 0x00 },
954 { 0x80, 0x80, 0x80, 0x00 },
955 { 0x00, 0x00, 0xff, 0x00 },
956 { 0x00, 0xff, 0x00, 0x00 },
957 { 0x00, 0xff, 0xff, 0x00 },
958 { 0xff, 0x00, 0x00, 0x00 },
959 { 0xff, 0x00, 0xff, 0x00 },
960 { 0xff, 0xff, 0x00, 0x00 },
961 { 0xff, 0xff, 0xff, 0x00 }
964 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
965 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
966 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
968 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
970 BITMAPINFOHEADER header;
972 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
973 header.biWidth = bmp->bitmap.bmWidth;
974 header.biHeight = bmp->bitmap.bmHeight;
975 header.biPlanes = 1;
977 if (bmp->dib)
979 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
980 switch (bmp->dib->dsBm.bmBitsPixel)
982 case 16:
983 case 32:
984 header.biCompression = BI_BITFIELDS;
985 break;
986 default:
987 header.biCompression = BI_RGB;
988 break;
991 else
993 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
994 header.biBitCount = bmp->bitmap.bmBitsPixel;
997 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
998 header.biXPelsPerMeter = 0;
999 header.biYPelsPerMeter = 0;
1000 header.biClrUsed = 0;
1001 header.biClrImportant = 0;
1003 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
1005 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
1007 coreheader->bcWidth = header.biWidth;
1008 coreheader->bcHeight = header.biHeight;
1009 coreheader->bcPlanes = header.biPlanes;
1010 coreheader->bcBitCount = header.biBitCount;
1012 else
1013 info->bmiHeader = header;
1015 return abs(bmp->bitmap.bmHeight);
1018 /************************************************************************
1019 * copy_color_info
1021 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1023 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1025 unsigned int colors = get_dib_num_of_colors( src );
1026 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
1028 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
1030 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1032 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1033 if (coloruse == DIB_PAL_COLORS)
1034 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
1035 else
1037 unsigned int i;
1038 for (i = 0; i < colors; i++)
1040 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
1041 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
1042 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
1046 else
1048 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1049 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1051 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1052 /* bitfields are always at bmiColors even in larger structures */
1053 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1054 else if (colors)
1056 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1057 unsigned int size;
1059 if (coloruse == DIB_PAL_COLORS)
1060 size = colors * sizeof(WORD);
1061 else
1062 size = colors * sizeof(RGBQUAD);
1063 memcpy( colorptr, src_colors, size );
1068 void fill_default_color_table( BITMAPINFO *info )
1070 int i;
1072 switch (info->bmiHeader.biBitCount)
1074 case 1:
1075 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
1076 info->bmiColors[0].rgbReserved = 0;
1077 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
1078 info->bmiColors[1].rgbReserved = 0;
1079 break;
1081 case 4:
1082 /* The EGA palette is the first and last 8 colours of the default palette
1083 with the innermost pair swapped */
1084 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
1085 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
1086 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
1087 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
1088 break;
1090 case 8:
1091 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
1092 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
1093 for (i = 10; i < 246; i++)
1095 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
1096 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
1097 info->bmiColors[i].rgbBlue = i & 0xc0;
1098 info->bmiColors[i].rgbReserved = 0;
1100 break;
1102 default:
1103 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
1105 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1108 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1110 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1111 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1112 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1113 info->bmiHeader.biPlanes = 1;
1114 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1115 info->bmiHeader.biCompression = BI_RGB;
1116 info->bmiHeader.biXPelsPerMeter = 0;
1117 info->bmiHeader.biYPelsPerMeter = 0;
1118 info->bmiHeader.biClrUsed = 0;
1119 info->bmiHeader.biClrImportant = 0;
1120 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1123 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1125 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1126 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1127 int info_size, image_size;
1129 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1131 info_size = bitmap_info_size( info, usage );
1132 image_size = get_dib_image_size( info );
1133 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + image_size )))
1135 memcpy( ret, info, info_size );
1136 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size(src_info,usage), image_size );
1138 return ret;
1141 /******************************************************************************
1142 * GetDIBits [GDI32.@]
1144 * Retrieves bits of bitmap and copies to buffer.
1146 * RETURNS
1147 * Success: Number of scan lines copied from bitmap
1148 * Failure: 0
1150 INT WINAPI GetDIBits(
1151 HDC hdc, /* [in] Handle to device context */
1152 HBITMAP hbitmap, /* [in] Handle to bitmap */
1153 UINT startscan, /* [in] First scan line to set in dest bitmap */
1154 UINT lines, /* [in] Number of scan lines to copy */
1155 LPVOID bits, /* [out] Address of array for bitmap bits */
1156 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1157 UINT coloruse) /* [in] RGB or palette index */
1159 DC * dc;
1160 BITMAPOBJ * bmp;
1161 int i, dst_to_src_offset, ret = 0;
1162 DWORD err;
1163 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1164 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1165 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1166 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1167 const struct gdi_dc_funcs *funcs;
1168 struct gdi_image_bits src_bits;
1169 struct bitblt_coords src, dst;
1170 BOOL empty_rect = FALSE;
1172 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1173 own copy and transfer the colour info back at the end */
1174 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1175 if (bits &&
1176 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1177 return 0;
1178 dst_info->bmiHeader.biClrUsed = 0;
1179 dst_info->bmiHeader.biClrImportant = 0;
1181 if (!(dc = get_dc_ptr( hdc )))
1183 SetLastError( ERROR_INVALID_PARAMETER );
1184 return 0;
1186 update_dc( dc );
1187 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1189 release_dc_ptr( dc );
1190 return 0;
1193 funcs = get_bitmap_funcs( bmp );
1195 src.visrect.left = 0;
1196 src.visrect.top = 0;
1197 src.visrect.right = bmp->bitmap.bmWidth;
1198 src.visrect.bottom = bmp->bitmap.bmHeight;
1200 dst.visrect.left = 0;
1201 dst.visrect.top = 0;
1202 dst.visrect.right = dst_info->bmiHeader.biWidth;
1203 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1205 if (lines == 0 || startscan >= dst.visrect.bottom)
1206 bits = NULL;
1208 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1210 ret = fill_query_info( info, bmp );
1211 goto done;
1214 /* validate parameters */
1216 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1217 if (dst_info->bmiHeader.biHeight == 0) goto done;
1219 switch (dst_info->bmiHeader.biCompression)
1221 case BI_RLE4:
1222 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1223 if (dst_info->bmiHeader.biHeight < 0) goto done;
1224 if (bits) goto done; /* can't retrieve compressed bits */
1225 break;
1226 case BI_RLE8:
1227 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1228 if (dst_info->bmiHeader.biHeight < 0) goto done;
1229 if (bits) goto done; /* can't retrieve compressed bits */
1230 break;
1231 case BI_BITFIELDS:
1232 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1233 /* fall through */
1234 case BI_RGB:
1235 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1236 if (dst_info->bmiHeader.biBitCount == 1) break;
1237 if (dst_info->bmiHeader.biBitCount == 4) break;
1238 if (dst_info->bmiHeader.biBitCount == 8) break;
1239 if (dst_info->bmiHeader.biBitCount == 16) break;
1240 if (dst_info->bmiHeader.biBitCount == 24) break;
1241 if (dst_info->bmiHeader.biBitCount == 32) break;
1242 /* fall through */
1243 default:
1244 goto done;
1247 if (bits)
1249 if (dst_info->bmiHeader.biHeight > 0)
1251 dst_to_src_offset = -startscan;
1252 lines = min( lines, dst.visrect.bottom - startscan );
1253 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1255 else
1257 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1258 if (dst_to_src_offset < 0)
1260 dst_to_src_offset = 0;
1261 lines = dst.visrect.bottom - startscan;
1263 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1266 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1267 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1268 dst.visrect = src.visrect;
1269 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1271 if (dst_info->bmiHeader.biHeight > 0)
1273 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1275 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1276 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1277 memset( bits, 0, pad_bytes );
1278 bits = (char *)bits + pad_bytes;
1281 else
1283 if (dst.visrect.bottom < lines)
1285 int pad_lines = lines - dst.visrect.bottom;
1286 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1287 int pad_bytes = pad_lines * stride;
1288 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1292 if (empty_rect) bits = NULL;
1294 src.x = src.visrect.left;
1295 src.y = src.visrect.top;
1296 src.width = src.visrect.right - src.visrect.left;
1297 src.height = src.visrect.bottom - src.visrect.top;
1299 lines = src.height;
1302 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1304 if (err) goto done;
1306 /* fill out the src colour table, if it needs one */
1307 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1308 fill_default_color_table( src_info );
1310 /* if the src and dst are the same depth, copy the colour info across */
1311 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1313 switch (src_info->bmiHeader.biBitCount)
1315 case 16:
1316 if (src_info->bmiHeader.biCompression == BI_RGB)
1318 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1319 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1321 break;
1322 case 32:
1323 if (src_info->bmiHeader.biCompression == BI_RGB)
1325 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1326 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1328 break;
1330 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1331 copy_color_info( dst_info, src_info, coloruse );
1333 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1335 if( coloruse == DIB_PAL_COLORS )
1337 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1339 else
1341 fill_default_color_table( dst_info );
1345 if (bits)
1347 if(dst_info->bmiHeader.biHeight > 0)
1348 dst_info->bmiHeader.biHeight = src.height;
1349 else
1350 dst_info->bmiHeader.biHeight = -src.height;
1352 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1353 if (src_bits.free) src_bits.free( &src_bits );
1354 ret = lines;
1356 else
1357 ret = empty_rect ? FALSE : TRUE;
1359 if (coloruse == DIB_PAL_COLORS)
1361 WORD *index = (WORD *)dst_info->bmiColors;
1362 int colors = get_dib_num_of_colors( dst_info );
1363 for (i = 0; i < colors; i++, index++)
1364 *index = i;
1367 dst_info->bmiHeader.biClrUsed = 0;
1368 copy_color_info( info, dst_info, coloruse );
1370 done:
1371 release_dc_ptr( dc );
1372 GDI_ReleaseObj( hbitmap );
1373 return ret;
1377 /***********************************************************************
1378 * CreateDIBitmap (GDI32.@)
1380 * Creates a DDB (device dependent bitmap) from a DIB.
1381 * The DDB will have the same color depth as the reference DC.
1383 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1384 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1385 UINT coloruse )
1387 BITMAPINFOHEADER info;
1388 HBITMAP handle;
1389 LONG height;
1391 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1392 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1393 if (info.biWidth < 0) return 0;
1395 /* Top-down DIBs have a negative height */
1396 height = abs( info.biHeight );
1398 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1399 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1400 info.biBitCount, info.biCompression);
1402 if (hdc == NULL)
1403 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1404 else
1405 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1407 if (handle)
1409 if (init & CBM_INIT)
1411 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1413 DeleteObject( handle );
1414 handle = 0;
1419 return handle;
1423 /***********************************************************************
1424 * CreateDIBSection (GDI32.@)
1426 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1427 VOID **bits, HANDLE section, DWORD offset)
1429 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1430 BITMAPINFO *info = (BITMAPINFO *)buffer;
1431 HBITMAP ret = 0;
1432 DC *dc;
1433 BOOL bDesktopDC = FALSE;
1434 DIBSECTION *dib;
1435 BITMAPOBJ *bmp;
1436 RGBQUAD *color_table = NULL;
1437 void *mapBits = NULL;
1439 if (bits) *bits = NULL;
1440 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1441 if (info->bmiHeader.biPlanes != 1)
1443 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1444 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1447 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1449 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1450 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1451 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1452 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1453 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1455 dib->dsBm.bmType = 0;
1456 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1457 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1458 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1459 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1460 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1461 dib->dsBm.bmBits = NULL;
1462 dib->dsBmih = info->bmiHeader;
1464 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1466 unsigned int colors = 1 << info->bmiHeader.biBitCount;
1468 if (!(color_table = HeapAlloc( GetProcessHeap(), 0, colors * sizeof(RGBQUAD) )))
1470 HeapFree( GetProcessHeap(), 0, dib );
1471 return 0;
1473 if (usage == DIB_RGB_COLORS)
1474 memcpy( color_table, info->bmiColors, colors * sizeof(RGBQUAD) );
1475 else
1476 fill_color_table_from_pal_colors( hdc, info, color_table );
1478 dib->dsBmih.biClrUsed = colors;
1481 /* set dsBitfields values */
1482 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1484 dib->dsBmih.biCompression = BI_BITFIELDS;
1485 dib->dsBitfields[0] = 0x7c00;
1486 dib->dsBitfields[1] = 0x03e0;
1487 dib->dsBitfields[2] = 0x001f;
1489 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1491 dib->dsBitfields[0] = *(const DWORD *)info->bmiColors;
1492 dib->dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1493 dib->dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1494 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1496 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1498 /* get storage location for DIB bits */
1500 if (section)
1502 SYSTEM_INFO SystemInfo;
1503 DWORD mapOffset;
1504 INT mapSize;
1506 GetSystemInfo( &SystemInfo );
1507 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1508 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1509 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1510 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1512 else
1514 offset = 0;
1515 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1516 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1518 dib->dshSection = section;
1519 dib->dsOffset = offset;
1521 if (!dib->dsBm.bmBits)
1523 HeapFree( GetProcessHeap(), 0, color_table );
1524 HeapFree( GetProcessHeap(), 0, dib );
1525 return 0;
1528 /* If the reference hdc is null, take the desktop dc */
1529 if (hdc == 0)
1531 hdc = CreateCompatibleDC(0);
1532 bDesktopDC = TRUE;
1535 if (!(dc = get_dc_ptr( hdc ))) goto error;
1537 /* create Device Dependent Bitmap and add DIB pointer */
1538 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1539 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1541 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1543 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1544 bmp->dib = dib;
1545 bmp->funcs = physdev->funcs;
1546 bmp->color_table = color_table;
1547 bmp->nb_colors = dib->dsBmih.biClrUsed;
1548 GDI_ReleaseObj( ret );
1550 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1552 DeleteObject( ret );
1553 ret = 0;
1557 release_dc_ptr( dc );
1558 if (bDesktopDC) DeleteDC( hdc );
1559 if (ret && bits) *bits = dib->dsBm.bmBits;
1560 return ret;
1562 error:
1563 if (bDesktopDC) DeleteDC( hdc );
1564 if (section) UnmapViewOfFile( mapBits );
1565 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1566 HeapFree( GetProcessHeap(), 0, color_table );
1567 HeapFree( GetProcessHeap(), 0, dib );
1568 return 0;