gdi32: Always use biClrUsed for the number of colors of internal BITMAPINFO structures.
[wine/multimedia.git] / dlls / gdi32 / dib.c
blob23affb1334028365731359db64c1e092c52c981e
1 /*
2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize).
34 * The palettes are stored in different formats:
36 - BITMAPCOREINFO: Array of RGBTRIPLE
37 - BITMAPINFO: Array of RGBQUAD
40 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
43 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
45 If biCompression is BI_BITFIELDS, the color masks are at the same position
46 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
47 the new headers have structure members for the masks.
50 * You should never access the color table using the bmiColors member,
51 because the passed structure may have one of the extended headers
52 mentioned above. Use this to calculate the location:
54 BITMAPINFO* info;
55 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
58 * More information:
59 Search for "Bitmap Structures" in MSDN
62 #include <stdarg.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <assert.h>
67 #include "windef.h"
68 #include "winbase.h"
69 #include "gdi_private.h"
70 #include "wine/debug.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
75 /***********************************************************************
76 * bitmap_info_size
78 * Return the size of the bitmap info structure including color table.
80 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
82 unsigned int colors, size, masks = 0;
84 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
86 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
87 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
88 return sizeof(BITMAPCOREHEADER) + colors *
89 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
91 else /* assume BITMAPINFOHEADER */
93 if (info->bmiHeader.biClrUsed) colors = min( info->bmiHeader.biClrUsed, 256 );
94 else colors = info->bmiHeader.biBitCount > 8 ? 0 : 1 << info->bmiHeader.biBitCount;
95 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
96 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
97 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
101 /*******************************************************************************************
102 * Verify that the DIB parameters are valid.
104 static BOOL is_valid_dib_format( const BITMAPINFOHEADER *info, BOOL allow_compression )
106 if (info->biWidth <= 0) return FALSE;
107 if (info->biHeight == 0) return FALSE;
109 if (allow_compression && (info->biCompression == BI_RLE4 || info->biCompression == BI_RLE8))
111 if (info->biHeight < 0) return FALSE;
112 if (!info->biSizeImage) return FALSE;
113 return info->biBitCount == (info->biCompression == BI_RLE4 ? 4 : 8);
116 if (!info->biPlanes) return FALSE;
118 switch (info->biBitCount)
120 case 1:
121 case 4:
122 case 8:
123 case 24:
124 return (info->biCompression == BI_RGB);
125 case 16:
126 case 32:
127 return (info->biCompression == BI_BITFIELDS || info->biCompression == BI_RGB);
128 default:
129 return FALSE;
133 /*******************************************************************************************
134 * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
136 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
138 if (!info) return FALSE;
140 if (info->biSize == sizeof(BITMAPCOREHEADER))
142 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
143 dst->biWidth = core->bcWidth;
144 dst->biHeight = core->bcHeight;
145 dst->biPlanes = core->bcPlanes;
146 dst->biBitCount = core->bcBitCount;
147 dst->biCompression = BI_RGB;
148 dst->biXPelsPerMeter = 0;
149 dst->biYPelsPerMeter = 0;
150 dst->biClrUsed = 0;
151 dst->biClrImportant = 0;
153 else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
155 *dst = *info;
157 else
159 WARN( "(%u): unknown/wrong size for header\n", info->biSize );
160 return FALSE;
163 dst->biSize = sizeof(*dst);
164 if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
165 dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
166 return TRUE;
169 /*******************************************************************************************
170 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
172 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info,
173 UINT coloruse, BOOL allow_compression )
175 void *src_colors;
177 if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
178 if (!is_valid_dib_format( &dst->bmiHeader, allow_compression )) return FALSE;
180 src_colors = (char *)info + info->bmiHeader.biSize;
182 if (dst->bmiHeader.biCompression == BI_BITFIELDS)
184 /* bitfields are always at bmiColors even in larger structures */
185 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
186 dst->bmiHeader.biClrUsed = 0;
188 else if (dst->bmiHeader.biBitCount <= 8)
190 unsigned int colors = dst->bmiHeader.biClrUsed;
191 unsigned int max_colors = 1 << dst->bmiHeader.biBitCount;
193 if (!colors) colors = max_colors;
194 else colors = min( colors, max_colors );
196 if (coloruse == DIB_PAL_COLORS)
198 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
199 max_colors = colors;
201 else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
203 memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
205 else
207 unsigned int i;
208 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
209 for (i = 0; i < colors; i++)
211 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
212 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
213 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
214 dst->bmiColors[i].rgbReserved = 0;
217 memset( dst->bmiColors + colors, 0, (max_colors - colors) * sizeof(RGBQUAD) );
218 dst->bmiHeader.biClrUsed = max_colors;
220 else dst->bmiHeader.biClrUsed = 0;
222 return TRUE;
225 static int fill_color_table_from_palette( BITMAPINFO *info, HDC hdc )
227 PALETTEENTRY palEntry[256];
228 HPALETTE palette = GetCurrentObject( hdc, OBJ_PAL );
229 int i, colors = 1 << info->bmiHeader.biBitCount;
231 info->bmiHeader.biClrUsed = colors;
233 if (!palette) return 0;
235 memset( palEntry, 0, sizeof(palEntry) );
236 if (!GetPaletteEntries( palette, 0, colors, palEntry ))
237 return 0;
239 for (i = 0; i < colors; i++)
241 info->bmiColors[i].rgbRed = palEntry[i].peRed;
242 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
243 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
244 info->bmiColors[i].rgbReserved = 0;
247 return colors;
250 BOOL fill_color_table_from_pal_colors( BITMAPINFO *info, HDC hdc )
252 PALETTEENTRY entries[256];
253 RGBQUAD table[256];
254 HPALETTE palette;
255 const WORD *index = (const WORD *)info->bmiColors;
256 int i, count, colors = info->bmiHeader.biClrUsed;
258 if (!colors) return TRUE;
259 if (!(palette = GetCurrentObject( hdc, OBJ_PAL ))) return FALSE;
260 if (!(count = GetPaletteEntries( palette, 0, colors, entries ))) return FALSE;
262 for (i = 0; i < colors; i++, index++)
264 table[i].rgbRed = entries[*index % count].peRed;
265 table[i].rgbGreen = entries[*index % count].peGreen;
266 table[i].rgbBlue = entries[*index % count].peBlue;
267 table[i].rgbReserved = 0;
269 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
270 memcpy( info->bmiColors, table, colors * sizeof(RGBQUAD) );
271 memset( info->bmiColors + colors, 0, (info->bmiHeader.biClrUsed - colors) * sizeof(RGBQUAD) );
272 return TRUE;
275 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
277 const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
278 const int bpp = info->bmiHeader.biBitCount;
280 if (height > 0)
281 return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
282 else
283 return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
286 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
288 int i = 0;
289 int left, right;
290 int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
291 HRGN run = NULL;
292 BYTE skip, num, data;
293 BYTE *out_bits, *in_bits = bits->ptr;
295 if (clip) *clip = NULL;
297 assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
299 out_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ) );
300 if (!out_bits) goto fail;
302 if (clip)
304 *clip = CreateRectRgn( 0, 0, 0, 0 );
305 run = CreateRectRgn( 0, 0, 0, 0 );
306 if (!*clip || !run) goto fail;
309 x = left = right = 0;
310 y = height - 1;
312 while (i < info->bmiHeader.biSizeImage - 1)
314 num = in_bits[i];
315 data = in_bits[i + 1];
316 i += 2;
318 if (num)
320 if (x + num > width) num = width - x;
321 if (num)
323 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
324 if (info->bmiHeader.biBitCount == 8)
325 memset( out_ptr, s, num );
326 else
328 if(x & 1)
330 s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
331 *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
332 out_ptr++;
333 x++;
334 num--;
336 /* this will write one too many if num is odd, but that doesn't matter */
337 if (num) memset( out_ptr, s, (num + 1) / 2 );
340 x += num;
341 right = x;
343 else
345 if (data < 3)
347 if(left != right && clip)
349 SetRectRgn( run, left, y, right, y + 1 );
350 CombineRgn( *clip, run, *clip, RGN_OR );
352 switch (data)
354 case 0: /* eol */
355 left = right = x = 0;
356 y--;
357 if(y < 0) goto done;
358 break;
360 case 1: /* eod */
361 goto done;
363 case 2: /* delta */
364 if (i >= info->bmiHeader.biSizeImage - 1) goto done;
365 x += in_bits[i];
366 if (x > width) x = width;
367 left = right = x;
368 y -= in_bits[i + 1];
369 if(y < 0) goto done;
370 i += 2;
373 else /* data bytes of data */
375 num = data;
376 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
377 if (skip > info->bmiHeader.biSizeImage - i) goto done;
378 skip = (skip + 1) & ~1;
379 if (x + num > width) num = width - x;
380 if (num)
382 BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
383 if (info->bmiHeader.biBitCount == 8)
384 memcpy( out_ptr, in_bits + i, num );
385 else
387 if(x & 1)
389 const BYTE *in_ptr = in_bits + i;
390 for ( ; num; num--, x++)
392 if (x & 1)
394 *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
395 out_ptr++;
397 else
398 *out_ptr = (*in_ptr++ << 4) & 0xf0;
401 else
402 memcpy( out_ptr, in_bits + i, (num + 1) / 2);
405 x += num;
406 right = x;
407 i += skip;
412 done:
413 if (run) DeleteObject( run );
414 if (bits->free) bits->free( bits );
416 bits->ptr = out_bits;
417 bits->is_copy = TRUE;
418 bits->free = free_heap_bits;
420 return TRUE;
422 fail:
423 if (run) DeleteObject( run );
424 if (clip && *clip) DeleteObject( *clip );
425 HeapFree( GetProcessHeap(), 0, out_bits );
426 return FALSE;
431 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
432 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
433 BITMAPINFO *src_info, UINT coloruse, DWORD rop )
435 DC *dc = get_nulldrv_dc( dev );
436 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
437 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
438 struct bitblt_coords src, dst;
439 struct gdi_image_bits src_bits;
440 DWORD err;
441 HRGN clip = NULL;
442 INT ret = 0;
443 INT height = abs( src_info->bmiHeader.biHeight );
444 BOOL top_down = src_info->bmiHeader.biHeight < 0, non_stretch_from_origin = FALSE;
445 RECT rect;
447 TRACE("%d %d %d %d <- %d %d %d %d rop %08x\n", xDst, yDst, widthDst, heightDst,
448 xSrc, ySrc, widthSrc, heightSrc, rop);
450 src_bits.ptr = (void*)bits;
451 src_bits.is_copy = FALSE;
452 src_bits.free = NULL;
454 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
456 rect.left = xDst;
457 rect.top = yDst;
458 rect.right = xDst + widthDst;
459 rect.bottom = yDst + heightDst;
460 LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
461 dst.x = rect.left;
462 dst.y = rect.top;
463 dst.width = rect.right - rect.left;
464 dst.height = rect.bottom - rect.top;
466 if (dc->layout & LAYOUT_RTL && rop & NOMIRRORBITMAP)
468 dst.x += dst.width;
469 dst.width = -dst.width;
471 rop &= ~NOMIRRORBITMAP;
473 src.x = xSrc;
474 src.width = widthSrc;
475 src.y = ySrc;
476 src.height = heightSrc;
478 if (src.x == 0 && src.y == 0 && src.width == dst.width && src.height == dst.height)
479 non_stretch_from_origin = TRUE;
481 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
483 BOOL want_clip = non_stretch_from_origin && (rop == SRCCOPY);
484 if (!build_rle_bitmap( src_info, &src_bits, want_clip ? &clip : NULL )) return 0;
487 if (rop != SRCCOPY || non_stretch_from_origin)
489 if (dst.width == 1 && src.width > 1) src.width--;
490 if (dst.height == 1 && src.height > 1) src.height--;
493 if (rop != SRCCOPY)
495 if (dst.width < 0 && dst.width == src.width)
497 /* This is off-by-one, but that's what Windows does */
498 dst.x += dst.width;
499 src.x += src.width;
500 dst.width = -dst.width;
501 src.width = -src.width;
503 if (dst.height < 0 && dst.height == src.height)
505 dst.y += dst.height;
506 src.y += src.height;
507 dst.height = -dst.height;
508 src.height = -src.height;
512 if (!top_down || (rop == SRCCOPY && !non_stretch_from_origin)) src.y = height - src.y - src.height;
514 if (src.y >= height && src.y + src.height + 1 < height)
515 src.y = height - 1;
516 else if (src.y > 0 && src.y + src.height + 1 < 0)
517 src.y = -src.height - 1;
519 get_bounding_rect( &rect, src.x, src.y, src.width, src.height );
521 src.visrect.left = 0;
522 src.visrect.right = src_info->bmiHeader.biWidth;
523 src.visrect.top = 0;
524 src.visrect.bottom = height;
525 if (!intersect_rect( &src.visrect, &src.visrect, &rect )) goto done;
527 get_bounding_rect( &rect, dst.x, dst.y, dst.width, dst.height );
529 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
531 if (!intersect_vis_rectangles( &dst, &src )) goto done;
533 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
535 dev = GET_DC_PHYSDEV( dc, pPutImage );
536 copy_bitmapinfo( dst_info, src_info );
537 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
538 if (err == ERROR_BAD_FORMAT)
540 /* 1-bpp destination without a color table requires a fake 1-entry table
541 * that contains only the background color */
542 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
544 COLORREF color = GetBkColor( dev->hdc );
545 dst_info->bmiColors[0].rgbRed = GetRValue( color );
546 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
547 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
548 dst_info->bmiColors[0].rgbReserved = 0;
549 dst_info->bmiHeader.biClrUsed = 1;
552 if (!(err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE )))
554 /* get rid of the fake 1-bpp table */
555 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
556 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, rop );
560 if (err == ERROR_TRANSFORM_NOT_SUPPORTED)
562 copy_bitmapinfo( src_info, dst_info );
563 err = stretch_bits( src_info, &src, dst_info, &dst, &src_bits, GetStretchBltMode( dev->hdc ) );
564 if (!err) err = dev->funcs->pPutImage( dev, 0, NULL, dst_info, &src_bits, &src, &dst, rop );
566 if (err) ret = 0;
567 else if (rop == SRCCOPY) ret = height;
568 else ret = src_info->bmiHeader.biHeight;
570 done:
571 if (src_bits.free) src_bits.free( &src_bits );
572 if (clip) DeleteObject( clip );
573 return ret;
576 /***********************************************************************
577 * StretchDIBits (GDI32.@)
579 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
580 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
581 const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
583 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
584 BITMAPINFO *info = (BITMAPINFO *)buffer;
585 DC *dc;
586 INT ret = 0;
588 if (!bits) return 0;
589 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
591 SetLastError( ERROR_INVALID_PARAMETER );
592 return 0;
595 if ((dc = get_dc_ptr( hdc )))
597 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
598 update_dc( dc );
599 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
600 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
601 release_dc_ptr( dc );
603 return ret;
607 /******************************************************************************
608 * SetDIBits [GDI32.@]
610 * Sets pixels in a bitmap using colors from DIB.
612 * PARAMS
613 * hdc [I] Handle to device context
614 * hbitmap [I] Handle to bitmap
615 * startscan [I] Starting scan line
616 * lines [I] Number of scan lines
617 * bits [I] Array of bitmap bits
618 * info [I] Address of structure with data
619 * coloruse [I] Type of color indexes to use
621 * RETURNS
622 * Success: Number of scan lines copied
623 * Failure: 0
625 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
626 UINT lines, LPCVOID bits, const BITMAPINFO *info,
627 UINT coloruse )
629 BITMAPOBJ *bitmap;
630 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
631 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
632 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
633 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
634 INT result = 0;
635 DWORD err;
636 struct gdi_image_bits src_bits;
637 struct bitblt_coords src, dst;
638 INT src_to_dst_offset;
639 HRGN clip = 0;
640 const struct gdi_dc_funcs *funcs;
642 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse, TRUE ))
644 SetLastError( ERROR_INVALID_PARAMETER );
645 return 0;
647 if (src_info->bmiHeader.biCompression == BI_BITFIELDS)
649 DWORD *masks = (DWORD *)src_info->bmiColors;
650 if (!masks[0] || !masks[1] || !masks[2])
652 SetLastError( ERROR_INVALID_PARAMETER );
653 return 0;
657 src_bits.ptr = (void *)bits;
658 src_bits.is_copy = FALSE;
659 src_bits.free = NULL;
660 src_bits.param = NULL;
662 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, hdc )) return 0;
664 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return 0;
666 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
668 if (lines == 0) goto done;
669 else lines = src_info->bmiHeader.biHeight;
670 startscan = 0;
672 if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
675 dst.visrect.left = 0;
676 dst.visrect.top = 0;
677 dst.visrect.right = bitmap->bitmap.bmWidth;
678 dst.visrect.bottom = bitmap->bitmap.bmHeight;
680 src.visrect.left = 0;
681 src.visrect.top = 0;
682 src.visrect.right = src_info->bmiHeader.biWidth;
683 src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
685 if (src_info->bmiHeader.biHeight > 0)
687 src_to_dst_offset = -startscan;
688 lines = min( lines, src.visrect.bottom - startscan );
689 if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
691 else
693 src_to_dst_offset = src.visrect.bottom - lines - startscan;
694 /* Unlike the bottom-up case, Windows doesn't limit lines. */
695 if (lines < src.visrect.bottom) src.visrect.bottom = lines;
698 funcs = get_bitmap_funcs( bitmap );
700 result = lines;
702 offset_rect( &src.visrect, 0, src_to_dst_offset );
703 if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
704 src.visrect = dst.visrect;
705 offset_rect( &src.visrect, 0, -src_to_dst_offset );
707 src.x = src.visrect.left;
708 src.y = src.visrect.top;
709 src.width = src.visrect.right - src.visrect.left;
710 src.height = src.visrect.bottom - src.visrect.top;
712 dst.x = dst.visrect.left;
713 dst.y = dst.visrect.top;
714 dst.width = dst.visrect.right - dst.visrect.left;
715 dst.height = dst.visrect.bottom - dst.visrect.top;
717 copy_bitmapinfo( dst_info, src_info );
719 err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
720 if (err == ERROR_BAD_FORMAT)
722 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
723 if (!err) err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
725 if(err) result = 0;
727 done:
728 if (src_bits.free) src_bits.free( &src_bits );
729 if (clip) DeleteObject( clip );
730 GDI_ReleaseObj( hbitmap );
731 return result;
735 INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
736 INT x_src, INT y_src, UINT startscan, UINT lines,
737 const void *bits, BITMAPINFO *src_info, UINT coloruse )
739 DC *dc = get_nulldrv_dc( dev );
740 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
741 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
742 struct bitblt_coords src, dst;
743 struct gdi_image_bits src_bits;
744 HRGN clip = 0;
745 DWORD err;
746 UINT height;
747 BOOL top_down;
748 POINT pt;
749 RECT rect;
751 top_down = (src_info->bmiHeader.biHeight < 0);
752 height = abs( src_info->bmiHeader.biHeight );
754 src_bits.ptr = (void *)bits;
755 src_bits.is_copy = FALSE;
756 src_bits.free = NULL;
758 if (!lines) return 0;
759 if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( src_info, dev->hdc )) return 0;
761 if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
763 startscan = 0;
764 lines = height;
765 src_info->bmiHeader.biWidth = x_src + cx;
766 src_info->bmiHeader.biHeight = y_src + cy;
767 if (src_info->bmiHeader.biWidth <= 0 || src_info->bmiHeader.biHeight <= 0) return 0;
768 src.x = x_src;
769 src.y = 0;
770 src.width = cx;
771 src.height = cy;
772 if (!build_rle_bitmap( src_info, &src_bits, &clip )) return 0;
774 else
776 if (startscan >= height) return 0;
777 if (!top_down && lines > height - startscan) lines = height - startscan;
779 /* map src to top-down coordinates with startscan as origin */
780 src.x = x_src;
781 src.y = startscan + lines - (y_src + cy);
782 src.width = cx;
783 src.height = cy;
784 if (src.y > 0)
786 if (!top_down)
788 /* get rid of unnecessary lines */
789 if (src.y >= lines) return 0;
790 lines -= src.y;
791 src.y = 0;
793 else if (src.y >= lines) return lines;
795 src_info->bmiHeader.biHeight = top_down ? -lines : lines;
798 src.visrect.left = src.x;
799 src.visrect.top = src.y;
800 src.visrect.right = src.x + cx;
801 src.visrect.bottom = src.y + cy;
802 rect.left = 0;
803 rect.top = 0;
804 rect.right = src_info->bmiHeader.biWidth;
805 rect.bottom = abs( src_info->bmiHeader.biHeight );
806 if (!intersect_rect( &src.visrect, &src.visrect, &rect ))
808 lines = 0;
809 goto done;
812 pt.x = x_dst;
813 pt.y = y_dst;
814 LPtoDP( dev->hdc, &pt, 1 );
815 dst.x = pt.x;
816 dst.y = pt.y;
817 dst.width = cx;
818 dst.height = cy;
819 if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
821 rect.left = dst.x;
822 rect.top = dst.y;
823 rect.right = dst.x + cx;
824 rect.bottom = dst.y + cy;
825 if (!clip_visrect( dc, &dst.visrect, &rect )) goto done;
827 offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
828 intersect_rect( &rect, &src.visrect, &dst.visrect );
829 src.visrect = dst.visrect = rect;
830 offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
831 if (is_rect_empty( &dst.visrect )) goto done;
832 if (clip) OffsetRgn( clip, dst.x - src.x, dst.y - src.y );
834 dev = GET_DC_PHYSDEV( dc, pPutImage );
835 copy_bitmapinfo( dst_info, src_info );
836 err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
837 if (err == ERROR_BAD_FORMAT)
839 err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
840 if (!err) err = dev->funcs->pPutImage( dev, 0, clip, dst_info, &src_bits, &src, &dst, SRCCOPY );
842 if (err) lines = 0;
844 done:
845 if (src_bits.free) src_bits.free( &src_bits );
846 if (clip) DeleteObject( clip );
847 return lines;
850 /***********************************************************************
851 * SetDIBitsToDevice (GDI32.@)
853 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
854 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
855 UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
856 UINT coloruse )
858 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
859 BITMAPINFO *info = (BITMAPINFO *)buffer;
860 INT ret = 0;
861 DC *dc;
863 if (!bits) return 0;
864 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse, TRUE ))
866 SetLastError( ERROR_INVALID_PARAMETER );
867 return 0;
870 if ((dc = get_dc_ptr( hdc )))
872 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
873 update_dc( dc );
874 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
875 ySrc, startscan, lines, bits, info, coloruse );
876 release_dc_ptr( dc );
878 return ret;
881 /***********************************************************************
882 * SetDIBColorTable (GDI32.@)
884 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
886 DC * dc;
887 UINT result = 0;
888 BITMAPOBJ * bitmap;
890 if (!(dc = get_dc_ptr( hdc ))) return 0;
892 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
894 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
896 /* Check if currently selected bitmap is a DIB */
897 if (bitmap->color_table)
899 if (startpos < bitmap->dib->dsBmih.biClrUsed)
901 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
902 memcpy(bitmap->color_table + startpos, colors, result * sizeof(RGBQUAD));
905 GDI_ReleaseObj( dc->hBitmap );
906 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
908 release_dc_ptr( dc );
909 return result;
913 /***********************************************************************
914 * GetDIBColorTable (GDI32.@)
916 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
918 DC * dc;
919 BITMAPOBJ *bitmap;
920 UINT result = 0;
922 if (!(dc = get_dc_ptr( hdc ))) return 0;
924 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
926 /* Check if currently selected bitmap is a DIB */
927 if (bitmap->color_table)
929 if (startpos < bitmap->dib->dsBmih.biClrUsed)
931 result = min( entries, bitmap->dib->dsBmih.biClrUsed - startpos );
932 memcpy(colors, bitmap->color_table + startpos, result * sizeof(RGBQUAD));
935 GDI_ReleaseObj( dc->hBitmap );
937 release_dc_ptr( dc );
938 return result;
941 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
942 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
943 { 0x00, 0x00, 0x00, 0x00 },
944 { 0x00, 0x00, 0x80, 0x00 },
945 { 0x00, 0x80, 0x00, 0x00 },
946 { 0x00, 0x80, 0x80, 0x00 },
947 { 0x80, 0x00, 0x00, 0x00 },
948 { 0x80, 0x00, 0x80, 0x00 },
949 { 0x80, 0x80, 0x00, 0x00 },
950 { 0xc0, 0xc0, 0xc0, 0x00 },
951 { 0xc0, 0xdc, 0xc0, 0x00 },
952 { 0xf0, 0xca, 0xa6, 0x00 },
953 { 0xf0, 0xfb, 0xff, 0x00 },
954 { 0xa4, 0xa0, 0xa0, 0x00 },
955 { 0x80, 0x80, 0x80, 0x00 },
956 { 0x00, 0x00, 0xff, 0x00 },
957 { 0x00, 0xff, 0x00, 0x00 },
958 { 0x00, 0xff, 0xff, 0x00 },
959 { 0xff, 0x00, 0x00, 0x00 },
960 { 0xff, 0x00, 0xff, 0x00 },
961 { 0xff, 0xff, 0x00, 0x00 },
962 { 0xff, 0xff, 0xff, 0x00 }
965 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
966 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
967 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
969 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
971 BITMAPINFOHEADER header;
973 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
974 header.biWidth = bmp->bitmap.bmWidth;
975 header.biHeight = bmp->bitmap.bmHeight;
976 header.biPlanes = 1;
978 if (bmp->dib)
980 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
981 switch (bmp->dib->dsBm.bmBitsPixel)
983 case 16:
984 case 32:
985 header.biCompression = BI_BITFIELDS;
986 break;
987 default:
988 header.biCompression = BI_RGB;
989 break;
992 else
994 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
995 header.biBitCount = bmp->bitmap.bmBitsPixel;
998 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
999 header.biXPelsPerMeter = 0;
1000 header.biYPelsPerMeter = 0;
1001 header.biClrUsed = 0;
1002 header.biClrImportant = 0;
1004 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
1006 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
1008 coreheader->bcWidth = header.biWidth;
1009 coreheader->bcHeight = header.biHeight;
1010 coreheader->bcPlanes = header.biPlanes;
1011 coreheader->bcBitCount = header.biBitCount;
1013 else
1014 info->bmiHeader = header;
1016 return abs(bmp->bitmap.bmHeight);
1019 /************************************************************************
1020 * copy_color_info
1022 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
1024 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
1026 assert( src->bmiHeader.biSize == sizeof(BITMAPINFOHEADER) );
1028 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1030 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
1031 if (coloruse == DIB_PAL_COLORS)
1032 memcpy( core->bmciColors, src->bmiColors, src->bmiHeader.biClrUsed * sizeof(WORD) );
1033 else
1035 unsigned int i;
1036 for (i = 0; i < src->bmiHeader.biClrUsed; i++)
1038 core->bmciColors[i].rgbtRed = src->bmiColors[i].rgbRed;
1039 core->bmciColors[i].rgbtGreen = src->bmiColors[i].rgbGreen;
1040 core->bmciColors[i].rgbtBlue = src->bmiColors[i].rgbBlue;
1044 else
1046 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
1047 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
1049 if (src->bmiHeader.biCompression == BI_BITFIELDS)
1050 /* bitfields are always at bmiColors even in larger structures */
1051 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
1052 else if (src->bmiHeader.biClrUsed)
1054 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
1055 unsigned int size;
1057 if (coloruse == DIB_PAL_COLORS)
1058 size = src->bmiHeader.biClrUsed * sizeof(WORD);
1059 else
1060 size = src->bmiHeader.biClrUsed * sizeof(RGBQUAD);
1061 memcpy( colorptr, src->bmiColors, size );
1066 void fill_default_color_table( BITMAPINFO *info )
1068 int i;
1070 switch (info->bmiHeader.biBitCount)
1072 case 1:
1073 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
1074 info->bmiColors[0].rgbReserved = 0;
1075 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
1076 info->bmiColors[1].rgbReserved = 0;
1077 break;
1079 case 4:
1080 /* The EGA palette is the first and last 8 colours of the default palette
1081 with the innermost pair swapped */
1082 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
1083 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
1084 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
1085 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
1086 break;
1088 case 8:
1089 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
1090 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
1091 for (i = 10; i < 246; i++)
1093 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
1094 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
1095 info->bmiColors[i].rgbBlue = i & 0xc0;
1096 info->bmiColors[i].rgbReserved = 0;
1098 break;
1100 default:
1101 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
1103 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1106 void get_ddb_bitmapinfo( BITMAPOBJ *bmp, BITMAPINFO *info )
1108 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1109 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1110 info->bmiHeader.biHeight = -bmp->bitmap.bmHeight;
1111 info->bmiHeader.biPlanes = 1;
1112 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1113 info->bmiHeader.biCompression = BI_RGB;
1114 info->bmiHeader.biXPelsPerMeter = 0;
1115 info->bmiHeader.biYPelsPerMeter = 0;
1116 info->bmiHeader.biClrUsed = 0;
1117 info->bmiHeader.biClrImportant = 0;
1118 if (info->bmiHeader.biBitCount <= 8) fill_default_color_table( info );
1121 BITMAPINFO *copy_packed_dib( const BITMAPINFO *src_info, UINT usage )
1123 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1124 BITMAPINFO *ret, *info = (BITMAPINFO *)buffer;
1125 int info_size, image_size;
1127 if (!bitmapinfo_from_user_bitmapinfo( info, src_info, usage, FALSE )) return NULL;
1129 info_size = bitmap_info_size( info, usage );
1130 image_size = get_dib_image_size( info );
1131 if ((ret = HeapAlloc( GetProcessHeap(), 0, info_size + image_size )))
1133 memcpy( ret, info, info_size );
1134 memcpy( (char *)ret + info_size, (char *)src_info + bitmap_info_size(src_info,usage), image_size );
1136 return ret;
1139 /******************************************************************************
1140 * GetDIBits [GDI32.@]
1142 * Retrieves bits of bitmap and copies to buffer.
1144 * RETURNS
1145 * Success: Number of scan lines copied from bitmap
1146 * Failure: 0
1148 INT WINAPI GetDIBits(
1149 HDC hdc, /* [in] Handle to device context */
1150 HBITMAP hbitmap, /* [in] Handle to bitmap */
1151 UINT startscan, /* [in] First scan line to set in dest bitmap */
1152 UINT lines, /* [in] Number of scan lines to copy */
1153 LPVOID bits, /* [out] Address of array for bitmap bits */
1154 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
1155 UINT coloruse) /* [in] RGB or palette index */
1157 DC * dc;
1158 BITMAPOBJ * bmp;
1159 int i, dst_to_src_offset, ret = 0;
1160 DWORD err;
1161 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1162 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
1163 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1164 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
1165 const struct gdi_dc_funcs *funcs;
1166 struct gdi_image_bits src_bits;
1167 struct bitblt_coords src, dst;
1168 BOOL empty_rect = FALSE;
1170 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
1171 own copy and transfer the colour info back at the end */
1172 if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
1173 if (bits &&
1174 (dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
1175 return 0;
1176 dst_info->bmiHeader.biClrUsed = 0;
1177 dst_info->bmiHeader.biClrImportant = 0;
1179 if (!(dc = get_dc_ptr( hdc )))
1181 SetLastError( ERROR_INVALID_PARAMETER );
1182 return 0;
1184 update_dc( dc );
1185 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
1187 release_dc_ptr( dc );
1188 return 0;
1191 funcs = get_bitmap_funcs( bmp );
1193 src.visrect.left = 0;
1194 src.visrect.top = 0;
1195 src.visrect.right = bmp->bitmap.bmWidth;
1196 src.visrect.bottom = bmp->bitmap.bmHeight;
1198 dst.visrect.left = 0;
1199 dst.visrect.top = 0;
1200 dst.visrect.right = dst_info->bmiHeader.biWidth;
1201 dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
1203 if (lines == 0 || startscan >= dst.visrect.bottom)
1204 bits = NULL;
1206 if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
1208 ret = fill_query_info( info, bmp );
1209 goto done;
1212 /* validate parameters */
1214 if (dst_info->bmiHeader.biWidth <= 0) goto done;
1215 if (dst_info->bmiHeader.biHeight == 0) goto done;
1217 switch (dst_info->bmiHeader.biCompression)
1219 case BI_RLE4:
1220 if (dst_info->bmiHeader.biBitCount != 4) goto done;
1221 if (dst_info->bmiHeader.biHeight < 0) goto done;
1222 if (bits) goto done; /* can't retrieve compressed bits */
1223 break;
1224 case BI_RLE8:
1225 if (dst_info->bmiHeader.biBitCount != 8) goto done;
1226 if (dst_info->bmiHeader.biHeight < 0) goto done;
1227 if (bits) goto done; /* can't retrieve compressed bits */
1228 break;
1229 case BI_BITFIELDS:
1230 if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
1231 /* fall through */
1232 case BI_RGB:
1233 if (lines && !dst_info->bmiHeader.biPlanes) goto done;
1234 if (dst_info->bmiHeader.biBitCount == 1) break;
1235 if (dst_info->bmiHeader.biBitCount == 4) break;
1236 if (dst_info->bmiHeader.biBitCount == 8) break;
1237 if (dst_info->bmiHeader.biBitCount == 16) break;
1238 if (dst_info->bmiHeader.biBitCount == 24) break;
1239 if (dst_info->bmiHeader.biBitCount == 32) break;
1240 /* fall through */
1241 default:
1242 goto done;
1245 if (bits)
1247 if (dst_info->bmiHeader.biHeight > 0)
1249 dst_to_src_offset = -startscan;
1250 lines = min( lines, dst.visrect.bottom - startscan );
1251 if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
1253 else
1255 dst_to_src_offset = dst.visrect.bottom - lines - startscan;
1256 if (dst_to_src_offset < 0)
1258 dst_to_src_offset = 0;
1259 lines = dst.visrect.bottom - startscan;
1261 if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
1264 offset_rect( &dst.visrect, 0, dst_to_src_offset );
1265 empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
1266 dst.visrect = src.visrect;
1267 offset_rect( &dst.visrect, 0, -dst_to_src_offset );
1269 if (dst_info->bmiHeader.biHeight > 0)
1271 if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
1273 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
1274 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1275 memset( bits, 0, pad_bytes );
1276 bits = (char *)bits + pad_bytes;
1279 else
1281 if (dst.visrect.bottom < lines)
1283 int pad_lines = lines - dst.visrect.bottom;
1284 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
1285 int pad_bytes = pad_lines * stride;
1286 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
1290 if (empty_rect) bits = NULL;
1292 src.x = src.visrect.left;
1293 src.y = src.visrect.top;
1294 src.width = src.visrect.right - src.visrect.left;
1295 src.height = src.visrect.bottom - src.visrect.top;
1297 lines = src.height;
1300 err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
1302 if (err) goto done;
1304 /* fill out the src colour table, if it needs one */
1305 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
1306 fill_default_color_table( src_info );
1308 /* if the src and dst are the same depth, copy the colour info across */
1309 if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1311 switch (src_info->bmiHeader.biBitCount)
1313 case 16:
1314 if (src_info->bmiHeader.biCompression == BI_RGB)
1316 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1317 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1319 break;
1320 case 32:
1321 if (src_info->bmiHeader.biCompression == BI_RGB)
1323 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1324 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1326 break;
1328 src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1329 copy_color_info( dst_info, src_info, coloruse );
1331 else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1333 if( coloruse == DIB_PAL_COLORS )
1335 if (!fill_color_table_from_palette( dst_info, hdc )) goto done;
1337 else
1339 fill_default_color_table( dst_info );
1343 if (bits)
1345 if(dst_info->bmiHeader.biHeight > 0)
1346 dst_info->bmiHeader.biHeight = src.height;
1347 else
1348 dst_info->bmiHeader.biHeight = -src.height;
1350 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE );
1351 if (src_bits.free) src_bits.free( &src_bits );
1352 ret = lines;
1354 else
1355 ret = empty_rect ? FALSE : TRUE;
1357 if (coloruse == DIB_PAL_COLORS)
1359 WORD *index = (WORD *)dst_info->bmiColors;
1360 for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++)
1361 *index = i;
1364 copy_color_info( info, dst_info, coloruse );
1365 if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0;
1367 done:
1368 release_dc_ptr( dc );
1369 GDI_ReleaseObj( hbitmap );
1370 return ret;
1374 /***********************************************************************
1375 * CreateDIBitmap (GDI32.@)
1377 * Creates a DDB (device dependent bitmap) from a DIB.
1378 * The DDB will have the same color depth as the reference DC.
1380 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1381 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1382 UINT coloruse )
1384 BITMAPINFOHEADER info;
1385 HBITMAP handle;
1386 LONG height;
1388 if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1389 if (info.biCompression == BI_JPEG || info.biCompression == BI_PNG) return 0;
1390 if (info.biWidth < 0) return 0;
1392 /* Top-down DIBs have a negative height */
1393 height = abs( info.biHeight );
1395 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1396 hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1397 info.biBitCount, info.biCompression);
1399 if (hdc == NULL)
1400 handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1401 else
1402 handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1404 if (handle)
1406 if (init & CBM_INIT)
1408 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1410 DeleteObject( handle );
1411 handle = 0;
1416 return handle;
1420 /***********************************************************************
1421 * CreateDIBSection (GDI32.@)
1423 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1424 VOID **bits, HANDLE section, DWORD offset)
1426 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1427 BITMAPINFO *info = (BITMAPINFO *)buffer;
1428 HBITMAP ret = 0;
1429 DC *dc;
1430 BOOL bDesktopDC = FALSE;
1431 DIBSECTION *dib;
1432 BITMAPOBJ *bmp;
1433 RGBQUAD *color_table = NULL;
1434 void *mapBits = NULL;
1436 if (bits) *bits = NULL;
1437 if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage, FALSE )) return 0;
1438 if (info->bmiHeader.biPlanes != 1)
1440 if (info->bmiHeader.biPlanes * info->bmiHeader.biBitCount > 16) return 0;
1441 WARN( "%u planes not properly supported\n", info->bmiHeader.biPlanes );
1444 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1446 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1447 info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1448 info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1449 info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1450 info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1452 dib->dsBm.bmType = 0;
1453 dib->dsBm.bmWidth = info->bmiHeader.biWidth;
1454 dib->dsBm.bmHeight = abs( info->bmiHeader.biHeight );
1455 dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1456 dib->dsBm.bmPlanes = info->bmiHeader.biPlanes;
1457 dib->dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
1458 dib->dsBm.bmBits = NULL;
1459 dib->dsBmih = info->bmiHeader;
1461 if (info->bmiHeader.biBitCount <= 8) /* build the color table */
1463 if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
1464 goto error;
1465 dib->dsBmih.biClrUsed = info->bmiHeader.biClrUsed;
1466 if (!(color_table = HeapAlloc( GetProcessHeap(), 0, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) )))
1467 goto error;
1468 memcpy( color_table, info->bmiColors, dib->dsBmih.biClrUsed * sizeof(RGBQUAD) );
1471 /* set dsBitfields values */
1472 if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1474 dib->dsBmih.biCompression = BI_BITFIELDS;
1475 dib->dsBitfields[0] = 0x7c00;
1476 dib->dsBitfields[1] = 0x03e0;
1477 dib->dsBitfields[2] = 0x001f;
1479 else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1481 if (usage == DIB_PAL_COLORS) goto error;
1482 dib->dsBitfields[0] = *(const DWORD *)info->bmiColors;
1483 dib->dsBitfields[1] = *((const DWORD *)info->bmiColors + 1);
1484 dib->dsBitfields[2] = *((const DWORD *)info->bmiColors + 2);
1485 if (!dib->dsBitfields[0] || !dib->dsBitfields[1] || !dib->dsBitfields[2]) goto error;
1487 else dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1489 /* get storage location for DIB bits */
1491 if (section)
1493 SYSTEM_INFO SystemInfo;
1494 DWORD mapOffset;
1495 INT mapSize;
1497 GetSystemInfo( &SystemInfo );
1498 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1499 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1500 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1501 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1503 else
1505 offset = 0;
1506 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1507 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1509 dib->dshSection = section;
1510 dib->dsOffset = offset;
1512 if (!dib->dsBm.bmBits) goto error;
1514 /* If the reference hdc is null, take the desktop dc */
1515 if (hdc == 0)
1517 hdc = CreateCompatibleDC(0);
1518 bDesktopDC = TRUE;
1521 if (!(dc = get_dc_ptr( hdc ))) goto error;
1523 /* create Device Dependent Bitmap and add DIB pointer */
1524 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1525 (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1527 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1529 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1530 bmp->dib = dib;
1531 bmp->funcs = physdev->funcs;
1532 bmp->color_table = color_table;
1533 GDI_ReleaseObj( ret );
1535 if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1537 DeleteObject( ret );
1538 ret = 0;
1542 release_dc_ptr( dc );
1543 if (bDesktopDC) DeleteDC( hdc );
1544 if (ret && bits) *bits = dib->dsBm.bmBits;
1545 return ret;
1547 error:
1548 if (bDesktopDC) DeleteDC( hdc );
1549 if (section) UnmapViewOfFile( mapBits );
1550 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1551 HeapFree( GetProcessHeap(), 0, color_table );
1552 HeapFree( GetProcessHeap(), 0, dib );
1553 return 0;