gdi32: Remove the nb_colors fields in the bitmap object, we always allocate a full...
[wine/multimedia.git] / dlls / gdi32 / dib.c
blobb2d18cc065a5baf03af6a78bcd61f0227f2b970a
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 BOOL fill_color_table_from_pal_colors( BITMAPINFO *info, HDC hdc )
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 TRUE;
257 if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return FALSE;
258 if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return FALSE;
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 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
268 memcpy( info->bmiColors, table, colors * sizeof(RGBQUAD) );
269 memset( info->bmiColors + colors, 0, (info->bmiHeader.biClrUsed - colors) * sizeof(RGBQUAD) );
270 return TRUE;
273 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
275 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
276 const int bpp = info->bmiHeader.biBitCount;
278 if (height > 0)
279 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
280 else
281 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
284 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
286 int i = 0;
287 int left, right;
288 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
289 HRGN run = NULL;
290 BYTE skip, num, data;
291 BYTE *out_bits, *in_bits = bits->ptr;
293 if (clip) *clip = NULL;
295 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
297 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
298 if (!out_bits) goto fail;
300 if (clip)
302 *clip = CreateRectRgn( 0, 0, 0, 0 );
303 run = CreateRectRgn( 0, 0, 0, 0 );
304 if (!*clip || !run) goto fail;
307 x = left = right = 0;
308 y = height - 1;
310 while (i < info->bmiHeader.biSizeImage - 1)
312 num = in_bits[i];
313 data = in_bits[i + 1];
314 i += 2;
316 if (num)
318 if (x + num > width) num = width - x;
319 if (num)
321 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
322 if (info->bmiHeader.biBitCount == 8)
323 memset( out_ptr, s, num );
324 else
326 if(x & 1)
328 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
329 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
330 out_ptr++;
331 x++;
332 num--;
334 /* this will write one too many if num is odd, but that doesn't matter */
335 if (num) memset( out_ptr, s, (num + 1) / 2 );
338 x += num;
339 right = x;
341 else
343 if (data < 3)
345 if(left != right && clip)
347 SetRectRgn( run, left, y, right, y + 1 );
348 CombineRgn( *clip, run, *clip, RGN_OR );
350 switch (data)
352 case 0: /* eol */
353 left = right = x = 0;
354 y--;
355 if(y < 0) goto done;
356 break;
358 case 1: /* eod */
359 goto done;
361 case 2: /* delta */
362 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
363 x += in_bits[i];
364 if (x > width) x = width;
365 left = right = x;
366 y -= in_bits[i + 1];
367 if(y < 0) goto done;
368 i += 2;
371 else /* data bytes of data */
373 num = data;
374 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
375 if (skip > info->bmiHeader.biSizeImage - i) goto done;
376 skip = (skip + 1) & ~1;
377 if (x + num > width) num = width - x;
378 if (num)
380 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
381 if (info->bmiHeader.biBitCount == 8)
382 memcpy( out_ptr, in_bits + i, num );
383 else
385 if(x & 1)
387 const BYTE *in_ptr = in_bits + i;
388 for ( ; num; num--, x++)
390 if (x & 1)
392 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
393 out_ptr++;
395 else
396 *out_ptr = (*in_ptr++ << 4) & 0xf0;
399 else
400 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
403 x += num;
404 right = x;
405 i += skip;
410 done:
411 if (run) DeleteObject( run );
412 if (bits->free) bits->free( bits );
414 bits->ptr = out_bits;
415 bits->is_copy = TRUE;
416 bits->free = free_heap_bits;
418 return TRUE;
420 fail:
421 if (run) DeleteObject( run );
422 if (clip && *clip) DeleteObject( *clip );
423 HeapFree( GetProcessHeap(), 0, out_bits );
424 return FALSE;
429 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
430 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
431 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
433 DC *dc = get_nulldrv_dc( dev );
434 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
435 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
436 struct bitblt_coords src, dst;
437 struct gdi_image_bits src_bits;
438 DWORD err;
439 HRGN clip = NULL;
440 INT ret = 0;
441 INT height = abs( src_info->bmiHeader.biHeight );
442 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
443 RECT rect;
445 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
446 xSrc, ySrc, widthSrc, heightSrc, rop);
448 src_bits.ptr = (void*)bits;
449 src_bits.is_copy = FALSE;
450 src_bits.free = NULL;
452 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
454 rect.left = xDst;
455 rect.top = yDst;
456 rect.right = xDst + widthDst;
457 rect.bottom = yDst + heightDst;
458 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
459 dst.x = rect.left;
460 dst.y = rect.top;
461 dst.width = rect.right - rect.left;
462 dst.height = rect.bottom - rect.top;
464 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
466 dst.x += dst.width;
467 dst.width = -dst.width;
469 rop &= ~NOMIRRORBITMAP;
471 src.x = xSrc;
472 src.width = widthSrc;
473 src.y = ySrc;
474 src.height = heightSrc;
476 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
477 non_stretch_from_origin = TRUE;
479 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
481 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
482 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
485 if (rop != SRCCOPY || non_stretch_from_origin)
487 if (dst.width == 1 && src.width > 1) src.width--;
488 if (dst.height == 1 && src.height > 1) src.height--;
491 if (rop != SRCCOPY)
493 if (dst.width < 0 && dst.width == src.width)
495 /* This is off-by-one, but that's what Windows does */
496 dst.x += dst.width;
497 src.x += src.width;
498 dst.width = -dst.width;
499 src.width = -src.width;
501 if (dst.height < 0 && dst.height == src.height)
503 dst.y += dst.height;
504 src.y += src.height;
505 dst.height = -dst.height;
506 src.height = -src.height;
510 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
512 if (src.y >= height && src.y + src.height + 1 < height)
513 src.y = height - 1;
514 else if (src.y > 0 && src.y + src.height + 1 < 0)
515 src.y = -src.height - 1;
517 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
519 src.visrect.left = 0;
520 src.visrect.right = src_info->bmiHeader.biWidth;
521 src.visrect.top = 0;
522 src.visrect.bottom = height;
523 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
525 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
527 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
529 if (!intersect_vis_rectangles( &dst, &src )) goto done;
531 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
533 dev = GET_DC_PHYSDEV( dc, pPutImage );
534 copy_bitmapinfo( dst_info, src_info );
535 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
536 if (err == ERROR_BAD_FORMAT)
538 /* 1-bpp destination without a color table requires a fake 1-entry table
539 * that contains only the background color */
540 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
542 COLORREF color = GetBkColor( dev->hdc );
543 dst_info->bmiColors[0].rgbRed = GetRValue( color );
544 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
545 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
546 dst_info->bmiColors[0].rgbReserved = 0;
547 dst_info->bmiHeader.biClrUsed = 1;
550 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
552 /* get rid of the fake 1-bpp table */
553 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
554 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
558 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
560 copy_bitmapinfo( src_info, dst_info );
561 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
562 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
564 if (err) ret = 0;
565 else if (rop == SRCCOPY) ret = height;
566 else ret = src_info->bmiHeader.biHeight;
568 done:
569 if (src_bits.free) src_bits.free( &src_bits );
570 if (clip) DeleteObject( clip );
571 return ret;
574 /***********************************************************************
575 * StretchDIBits (GDI32.@)
577 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
578 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
579 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
581 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
582 BITMAPINFO *info = (BITMAPINFO *)buffer;
583 DC *dc;
584 INT ret = 0;
586 if (!bits) return 0;
587 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
589 SetLastError( ERROR_INVALID_PARAMETER );
590 return 0;
593 if ((dc = get_dc_ptr( hdc )))
595 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
596 update_dc( dc );
597 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
598 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
599 release_dc_ptr( dc );
601 return ret;
605 /******************************************************************************
606 * SetDIBits [GDI32.@]
608 * Sets pixels in a bitmap using colors from DIB.
610 * PARAMS
611 * hdc [I] Handle to device context
612 * hbitmap [I] Handle to bitmap
613 * startscan [I] Starting scan line
614 * lines [I] Number of scan lines
615 * bits [I] Array of bitmap bits
616 * info [I] Address of structure with data
617 * coloruse [I] Type of color indexes to use
619 * RETURNS
620 * Success: Number of scan lines copied
621 * Failure: 0
623 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
624 UINT lines, LPCVOID bits, const BITMAPINFO *info,
625 UINT coloruse )
627 BITMAPOBJ *bitmap;
628 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
629 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
630 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
631 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
632 INT result = 0;
633 DWORD err;
634 struct gdi_image_bits src_bits;
635 struct bitblt_coords src, dst;
636 INT src_to_dst_offset;
637 HRGN clip = 0;
638 const struct gdi_dc_funcs *funcs;
640 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
642 SetLastError( ERROR_INVALID_PARAMETER );
643 return 0;
645 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
647 DWORD *masks = (DWORD *)src_info->bmiColors;
648 if (!masks[0] || !masks[1] || !masks[2])
650 SetLastError( ERROR_INVALID_PARAMETER );
651 return 0;
655 src_bits.ptr = (void *)bits;
656 src_bits.is_copy = FALSE;
657 src_bits.free = NULL;
658 src_bits.param = NULL;
660 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
662 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
664 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
666 if (lines == 0) goto done;
667 else lines = src_info->bmiHeader.biHeight;
668 startscan = 0;
670 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
673 dst.visrect.left = 0;
674 dst.visrect.top = 0;
675 dst.visrect.right = bitmap->bitmap.bmWidth;
676 dst.visrect.bottom = bitmap->bitmap.bmHeight;
678 src.visrect.left = 0;
679 src.visrect.top = 0;
680 src.visrect.right = src_info->bmiHeader.biWidth;
681 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
683 if (src_info->bmiHeader.biHeight > 0)
685 src_to_dst_offset = -startscan;
686 lines = min( lines, src.visrect.bottom - startscan );
687 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
689 else
691 src_to_dst_offset = src.visrect.bottom - lines - startscan;
692 /* Unlike the bottom-up case, Windows doesn't limit lines. */
693 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
696 funcs = get_bitmap_funcs( bitmap );
698 result = lines;
700 offset_rect( &src.visrect, 0, src_to_dst_offset );
701 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
702 src.visrect = dst.visrect;
703 offset_rect( &src.visrect, 0, -src_to_dst_offset );
705 src.x = src.visrect.left;
706 src.y = src.visrect.top;
707 src.width = src.visrect.right - src.visrect.left;
708 src.height = src.visrect.bottom - src.visrect.top;
710 dst.x = dst.visrect.left;
711 dst.y = dst.visrect.top;
712 dst.width = dst.visrect.right - dst.visrect.left;
713 dst.height = dst.visrect.bottom - dst.visrect.top;
715 copy_bitmapinfo( dst_info, src_info );
717 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
718 if (err == ERROR_BAD_FORMAT)
720 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
721 if (!err) err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
723 if(err) result = 0;
725 done:
726 if (src_bits.free) src_bits.free( &src_bits );
727 if (clip) DeleteObject( clip );
728 GDI_ReleaseObj( hbitmap );
729 return result;
733 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
734 INT x_src, INT y_src, UINT startscan, UINT lines,
735 const void *bits, BITMAPINFO *src_info, UINT coloruse )
737 DC *dc = get_nulldrv_dc( dev );
738 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
739 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
740 struct bitblt_coords src, dst;
741 struct gdi_image_bits src_bits;
742 HRGN clip = 0;
743 DWORD err;
744 UINT height;
745 BOOL top_down;
746 POINT pt;
747 RECT rect;
749 top_down = (src_info->bmiHeader.biHeight < 0);
750 height = abs( src_info->bmiHeader.biHeight );
752 src_bits.ptr = (void *)bits;
753 src_bits.is_copy = FALSE;
754 src_bits.free = NULL;
756 if (!lines) return 0;
757 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
759 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
761 startscan = 0;
762 lines = height;
763 src_info->bmiHeader.biWidth = x_src + cx;
764 src_info->bmiHeader.biHeight = y_src + cy;
765 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
766 src.x = x_src;
767 src.y = 0;
768 src.width = cx;
769 src.height = cy;
770 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
772 else
774 if (startscan >= height) return 0;
775 if (!top_down && lines > height - startscan) lines = height - startscan;
777 /* map src to top-down coordinates with startscan as origin */
778 src.x = x_src;
779 src.y = startscan + lines - (y_src + cy);
780 src.width = cx;
781 src.height = cy;
782 if (src.y > 0)
784 if (!top_down)
786 /* get rid of unnecessary lines */
787 if (src.y >= lines) return 0;
788 lines -= src.y;
789 src.y = 0;
791 else if (src.y >= lines) return lines;
793 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
796 src.visrect.left = src.x;
797 src.visrect.top = src.y;
798 src.visrect.right = src.x + cx;
799 src.visrect.bottom = src.y + cy;
800 rect.left = 0;
801 rect.top = 0;
802 rect.right = src_info->bmiHeader.biWidth;
803 rect.bottom = abs( src_info->bmiHeader.biHeight );
804 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
806 lines = 0;
807 goto done;
810 pt.x = x_dst;
811 pt.y = y_dst;
812 LPtoDP( dev->hdc, &pt, 1 );
813 dst.x = pt.x;
814 dst.y = pt.y;
815 dst.width = cx;
816 dst.height = cy;
817 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
819 rect.left = dst.x;
820 rect.top = dst.y;
821 rect.right = dst.x + cx;
822 rect.bottom = dst.y + cy;
823 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
825 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
826 intersect_rect( &rect, &src.visrect, &dst.visrect );
827 src.visrect = dst.visrect = rect;
828 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
829 if (is_rect_empty( &dst.visrect )) goto done;
830 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
832 dev = GET_DC_PHYSDEV( dc, pPutImage );
833 copy_bitmapinfo( dst_info, src_info );
834 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
835 if (err == ERROR_BAD_FORMAT)
837 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
838 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
840 if (err) lines = 0;
842 done:
843 if (src_bits.free) src_bits.free( &src_bits );
844 if (clip) DeleteObject( clip );
845 return lines;
848 /***********************************************************************
849 * SetDIBitsToDevice (GDI32.@)
851 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
852 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
853 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
854 UINT coloruse )
856 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
857 BITMAPINFO *info = (BITMAPINFO *)buffer;
858 INT ret = 0;
859 DC *dc;
861 if (!bits) return 0;
862 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
864 SetLastError( ERROR_INVALID_PARAMETER );
865 return 0;
868 if ((dc = get_dc_ptr( hdc )))
870 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
871 update_dc( dc );
872 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
873 ySrc, startscan, lines, bits, info, coloruse );
874 release_dc_ptr( dc );
876 return ret;
879 /***********************************************************************
880 * SetDIBColorTable (GDI32.@)
882 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
884 DC * dc;
885 UINT result = 0;
886 BITMAPOBJ * bitmap;
888 if (!(dc = get_dc_ptr( hdc ))) return 0;
890 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
892 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
894 /* Check if currently selected bitmap is a DIB */
895 if (bitmap->color_table)
897 if (startpos < bitmap->dib->dsBmih.biClrUsed)
899 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
900 memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
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->dib->dsBmih.biClrUsed)
929 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
930 memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
933 GDI_ReleaseObj( dc->hBitmap );
935 release_dc_ptr( dc );
936 return result;
939 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
940 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
941 { 0x00, 0x00, 0x00, 0x00 },
942 { 0x00, 0x00, 0x80, 0x00 },
943 { 0x00, 0x80, 0x00, 0x00 },
944 { 0x00, 0x80, 0x80, 0x00 },
945 { 0x80, 0x00, 0x00, 0x00 },
946 { 0x80, 0x00, 0x80, 0x00 },
947 { 0x80, 0x80, 0x00, 0x00 },
948 { 0xc0, 0xc0, 0xc0, 0x00 },
949 { 0xc0, 0xdc, 0xc0, 0x00 },
950 { 0xf0, 0xca, 0xa6, 0x00 },
951 { 0xf0, 0xfb, 0xff, 0x00 },
952 { 0xa4, 0xa0, 0xa0, 0x00 },
953 { 0x80, 0x80, 0x80, 0x00 },
954 { 0x00, 0x00, 0xff, 0x00 },
955 { 0x00, 0xff, 0x00, 0x00 },
956 { 0x00, 0xff, 0xff, 0x00 },
957 { 0xff, 0x00, 0x00, 0x00 },
958 { 0xff, 0x00, 0xff, 0x00 },
959 { 0xff, 0xff, 0x00, 0x00 },
960 { 0xff, 0xff, 0xff, 0x00 }
963 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
964 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
965 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
967 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
969 BITMAPINFOHEADER header;
971 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
972 header.biWidth = bmp->bitmap.bmWidth;
973 header.biHeight = bmp->bitmap.bmHeight;
974 header.biPlanes = 1;
976 if (bmp->dib)
978 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
979 switch (bmp->dib->dsBm.bmBitsPixel)
981 case 16:
982 case 32:
983 header.biCompression = BI_BITFIELDS;
984 break;
985 default:
986 header.biCompression = BI_RGB;
987 break;
990 else
992 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
993 header.biBitCount = bmp->bitmap.bmBitsPixel;
996 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
997 header.biXPelsPerMeter = 0;
998 header.biYPelsPerMeter = 0;
999 header.biClrUsed = 0;
1000 header.biClrImportant = 0;
1002 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
1004 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
1006 coreheader->bcWidth = header.biWidth;
1007 coreheader->bcHeight = header.biHeight;
1008 coreheader->bcPlanes = header.biPlanes;
1009 coreheader->bcBitCount = header.biBitCount;
1011 else
1012 info->bmiHeader = header;
1014 return abs(bmp->bitmap.bmHeight);
1017 /************************************************************************
1018 * copy_color_info
1020 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1022 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1024 unsigned int colors = get_dib_num_of_colors( src );
1025 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
1027 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
1029 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1031 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1032 if (coloruse == DIB_PAL_COLORS)
1033 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
1034 else
1036 unsigned int i;
1037 for (i = 0; i < colors; i++)
1039 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
1040 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
1041 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
1045 else
1047 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1048 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1050 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1051 /* bitfields are always at bmiColors even in larger structures */
1052 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1053 else if (colors)
1055 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1056 unsigned int size;
1058 if (coloruse == DIB_PAL_COLORS)
1059 size = colors * sizeof(WORD);
1060 else
1061 size = colors * sizeof(RGBQUAD);
1062 memcpy( colorptr, src_colors, size );
1067 void fill_default_color_table( BITMAPINFO *info )
1069 int i;
1071 switch (info->bmiHeader.biBitCount)
1073 case 1:
1074 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
1075 info->bmiColors[0].rgbReserved = 0;
1076 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
1077 info->bmiColors[1].rgbReserved = 0;
1078 break;
1080 case 4:
1081 /* The EGA palette is the first and last 8 colours of the default palette
1082 with the innermost pair swapped */
1083 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
1084 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
1085 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
1086 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
1087 break;
1089 case 8:
1090 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
1091 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
1092 for (i = 10; i < 246; i++)
1094 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
1095 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
1096 info->bmiColors[i].rgbBlue = i & 0xc0;
1097 info->bmiColors[i].rgbReserved = 0;
1099 break;
1101 default:
1102 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
1104 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1107 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1109 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1110 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1111 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1112 info->bmiHeader.biPlanes = 1;
1113 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1114 info->bmiHeader.biCompression = BI_RGB;
1115 info->bmiHeader.biXPelsPerMeter = 0;
1116 info->bmiHeader.biYPelsPerMeter = 0;
1117 info->bmiHeader.biClrUsed = 0;
1118 info->bmiHeader.biClrImportant = 0;
1119 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1122 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1124 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1125 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1126 int info_size, image_size;
1128 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1130 info_size = bitmap_info_size( info, usage );
1131 image_size = get_dib_image_size( info );
1132 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + image_size )))
1134 memcpy( ret, info, info_size );
1135 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size(src_info,usage), image_size );
1137 return ret;
1140 /******************************************************************************
1141 * GetDIBits [GDI32.@]
1143 * Retrieves bits of bitmap and copies to buffer.
1145 * RETURNS
1146 * Success: Number of scan lines copied from bitmap
1147 * Failure: 0
1149 INT WINAPI GetDIBits(
1150 HDC hdc, /* [in] Handle to device context */
1151 HBITMAP hbitmap, /* [in] Handle to bitmap */
1152 UINT startscan, /* [in] First scan line to set in dest bitmap */
1153 UINT lines, /* [in] Number of scan lines to copy */
1154 LPVOID bits, /* [out] Address of array for bitmap bits */
1155 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1156 UINT coloruse) /* [in] RGB or palette index */
1158 DC * dc;
1159 BITMAPOBJ * bmp;
1160 int i, dst_to_src_offset, ret = 0;
1161 DWORD err;
1162 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1163 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1164 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1165 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1166 const struct gdi_dc_funcs *funcs;
1167 struct gdi_image_bits src_bits;
1168 struct bitblt_coords src, dst;
1169 BOOL empty_rect = FALSE;
1171 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1172 own copy and transfer the colour info back at the end */
1173 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1174 if (bits &&
1175 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1176 return 0;
1177 dst_info->bmiHeader.biClrUsed = 0;
1178 dst_info->bmiHeader.biClrImportant = 0;
1180 if (!(dc = get_dc_ptr( hdc )))
1182 SetLastError( ERROR_INVALID_PARAMETER );
1183 return 0;
1185 update_dc( dc );
1186 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1188 release_dc_ptr( dc );
1189 return 0;
1192 funcs = get_bitmap_funcs( bmp );
1194 src.visrect.left = 0;
1195 src.visrect.top = 0;
1196 src.visrect.right = bmp->bitmap.bmWidth;
1197 src.visrect.bottom = bmp->bitmap.bmHeight;
1199 dst.visrect.left = 0;
1200 dst.visrect.top = 0;
1201 dst.visrect.right = dst_info->bmiHeader.biWidth;
1202 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1204 if (lines == 0 || startscan >= dst.visrect.bottom)
1205 bits = NULL;
1207 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1209 ret = fill_query_info( info, bmp );
1210 goto done;
1213 /* validate parameters */
1215 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1216 if (dst_info->bmiHeader.biHeight == 0) goto done;
1218 switch (dst_info->bmiHeader.biCompression)
1220 case BI_RLE4:
1221 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1222 if (dst_info->bmiHeader.biHeight < 0) goto done;
1223 if (bits) goto done; /* can't retrieve compressed bits */
1224 break;
1225 case BI_RLE8:
1226 if (dst_info->bmiHeader.biBitCount != 8) 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_BITFIELDS:
1231 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1232 /* fall through */
1233 case BI_RGB:
1234 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1235 if (dst_info->bmiHeader.biBitCount == 1) break;
1236 if (dst_info->bmiHeader.biBitCount == 4) break;
1237 if (dst_info->bmiHeader.biBitCount == 8) break;
1238 if (dst_info->bmiHeader.biBitCount == 16) break;
1239 if (dst_info->bmiHeader.biBitCount == 24) break;
1240 if (dst_info->bmiHeader.biBitCount == 32) break;
1241 /* fall through */
1242 default:
1243 goto done;
1246 if (bits)
1248 if (dst_info->bmiHeader.biHeight > 0)
1250 dst_to_src_offset = -startscan;
1251 lines = min( lines, dst.visrect.bottom - startscan );
1252 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1254 else
1256 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1257 if (dst_to_src_offset < 0)
1259 dst_to_src_offset = 0;
1260 lines = dst.visrect.bottom - startscan;
1262 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1265 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1266 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1267 dst.visrect = src.visrect;
1268 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1270 if (dst_info->bmiHeader.biHeight > 0)
1272 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1274 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1275 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1276 memset( bits, 0, pad_bytes );
1277 bits = (char *)bits + pad_bytes;
1280 else
1282 if (dst.visrect.bottom < lines)
1284 int pad_lines = lines - dst.visrect.bottom;
1285 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1286 int pad_bytes = pad_lines * stride;
1287 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1291 if (empty_rect) bits = NULL;
1293 src.x = src.visrect.left;
1294 src.y = src.visrect.top;
1295 src.width = src.visrect.right - src.visrect.left;
1296 src.height = src.visrect.bottom - src.visrect.top;
1298 lines = src.height;
1301 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1303 if (err) goto done;
1305 /* fill out the src colour table, if it needs one */
1306 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1307 fill_default_color_table( src_info );
1309 /* if the src and dst are the same depth, copy the colour info across */
1310 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1312 switch (src_info->bmiHeader.biBitCount)
1314 case 16:
1315 if (src_info->bmiHeader.biCompression == BI_RGB)
1317 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1318 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1320 break;
1321 case 32:
1322 if (src_info->bmiHeader.biCompression == BI_RGB)
1324 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1325 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1327 break;
1329 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1330 copy_color_info( dst_info, src_info, coloruse );
1332 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1334 if( coloruse == DIB_PAL_COLORS )
1336 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1338 else
1340 fill_default_color_table( dst_info );
1344 if (bits)
1346 if(dst_info->bmiHeader.biHeight > 0)
1347 dst_info->bmiHeader.biHeight = src.height;
1348 else
1349 dst_info->bmiHeader.biHeight = -src.height;
1351 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1352 if (src_bits.free) src_bits.free( &src_bits );
1353 ret = lines;
1355 else
1356 ret = empty_rect ? FALSE : TRUE;
1358 if (coloruse == DIB_PAL_COLORS)
1360 WORD *index = (WORD *)dst_info->bmiColors;
1361 int colors = get_dib_num_of_colors( dst_info );
1362 for (i = 0; i < colors; i++, index++)
1363 *index = i;
1366 dst_info->bmiHeader.biClrUsed = 0;
1367 copy_color_info( info, dst_info, coloruse );
1369 done:
1370 release_dc_ptr( dc );
1371 GDI_ReleaseObj( hbitmap );
1372 return ret;
1376 /***********************************************************************
1377 * CreateDIBitmap (GDI32.@)
1379 * Creates a DDB (device dependent bitmap) from a DIB.
1380 * The DDB will have the same color depth as the reference DC.
1382 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1383 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1384 UINT coloruse )
1386 BITMAPINFOHEADER info;
1387 HBITMAP handle;
1388 LONG height;
1390 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1391 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1392 if (info.biWidth < 0) return 0;
1394 /* Top-down DIBs have a negative height */
1395 height = abs( info.biHeight );
1397 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1398 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1399 info.biBitCount, info.biCompression);
1401 if (hdc == NULL)
1402 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1403 else
1404 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1406 if (handle)
1408 if (init & CBM_INIT)
1410 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1412 DeleteObject( handle );
1413 handle = 0;
1418 return handle;
1422 /***********************************************************************
1423 * CreateDIBSection (GDI32.@)
1425 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1426 VOID **bits, HANDLE section, DWORD offset)
1428 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1429 BITMAPINFO *info = (BITMAPINFO *)buffer;
1430 HBITMAP ret = 0;
1431 DC *dc;
1432 BOOL bDesktopDC = FALSE;
1433 DIBSECTION *dib;
1434 BITMAPOBJ *bmp;
1435 RGBQUAD *color_table = NULL;
1436 void *mapBits = NULL;
1438 if (bits) *bits = NULL;
1439 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1440 if (info->bmiHeader.biPlanes != 1)
1442 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1443 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1446 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1448 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1449 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1450 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1451 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1452 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1454 dib->dsBm.bmType = 0;
1455 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1456 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1457 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1458 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1459 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1460 dib->dsBm.bmBits = NULL;
1461 dib->dsBmih = info->bmiHeader;
1463 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1465 if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1466 goto error;
1467 dib->dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1468 if (!(color_table = HeapAlloc( GetProcessHeap(), 0, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) )))
1469 goto error;
1470 memcpy( color_table, info->bmiColors, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) );
1473 /* set dsBitfields values */
1474 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1476 dib->dsBmih.biCompression = BI_BITFIELDS;
1477 dib->dsBitfields[0] = 0x7c00;
1478 dib->dsBitfields[1] = 0x03e0;
1479 dib->dsBitfields[2] = 0x001f;
1481 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1483 if (usage == DIB_PAL_COLORS) goto error;
1484 dib->dsBitfields[0] = *(const DWORD *)info->bmiColors;
1485 dib->dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1486 dib->dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1487 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1489 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1491 /* get storage location for DIB bits */
1493 if (section)
1495 SYSTEM_INFO SystemInfo;
1496 DWORD mapOffset;
1497 INT mapSize;
1499 GetSystemInfo( &SystemInfo );
1500 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1501 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1502 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1503 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1505 else
1507 offset = 0;
1508 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1509 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1511 dib->dshSection = section;
1512 dib->dsOffset = offset;
1514 if (!dib->dsBm.bmBits) goto error;
1516 /* If the reference hdc is null, take the desktop dc */
1517 if (hdc == 0)
1519 hdc = CreateCompatibleDC(0);
1520 bDesktopDC = TRUE;
1523 if (!(dc = get_dc_ptr( hdc ))) goto error;
1525 /* create Device Dependent Bitmap and add DIB pointer */
1526 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1527 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1529 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1531 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1532 bmp->dib = dib;
1533 bmp->funcs = physdev->funcs;
1534 bmp->color_table = color_table;
1535 GDI_ReleaseObj( ret );
1537 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1539 DeleteObject( ret );
1540 ret = 0;
1544 release_dc_ptr( dc );
1545 if (bDesktopDC) DeleteDC( hdc );
1546 if (ret && bits) *bits = dib->dsBm.bmBits;
1547 return ret;
1549 error:
1550 if (bDesktopDC) DeleteDC( hdc );
1551 if (section) UnmapViewOfFile( mapBits );
1552 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1553 HeapFree( GetProcessHeap(), 0, color_table );
1554 HeapFree( GetProcessHeap(), 0, dib );
1555 return 0;