gdi32: Add a helper to fill out the colour table from the current palette.
[wine.git] / dlls / gdi32 / dib.c
blob995c5d72803f9fcc7bafc47dd0f9852aa38553d5
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),
32 or use the internal function DIB_GetBitmapInfo.
35 * The palettes are stored in different formats:
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
46 If biCompression is BI_BITFIELDS, the color masks are at the same position
47 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48 the new headers have structure members for the masks.
51 * You should never access the color table using the bmiColors member,
52 because the passed structure may have one of the extended headers
53 mentioned above. Use this to calculate the location:
55 BITMAPINFO* info;
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 * More information:
60 Search for "Bitmap Structures" in MSDN
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include <assert.h>
68 #include "windef.h"
69 #include "winbase.h"
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
76 /***********************************************************************
77 * bitmap_info_size
79 * Return the size of the bitmap info structure including color table.
81 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
83 unsigned int colors, size, masks = 0;
85 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
87 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
88 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
89 return sizeof(BITMAPCOREHEADER) + colors *
90 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
92 else /* assume BITMAPINFOHEADER */
94 colors = info->bmiHeader.biClrUsed;
95 if (colors > 256) colors = 256;
96 if (!colors && (info->bmiHeader.biBitCount <= 8))
97 colors = 1 << info->bmiHeader.biBitCount;
98 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
99 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
100 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
105 /***********************************************************************
106 * DIB_GetBitmapInfo
108 * Get the info from a bitmap header.
109 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
111 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
112 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
114 if (header->biSize == sizeof(BITMAPCOREHEADER))
116 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
117 *width = core->bcWidth;
118 *height = core->bcHeight;
119 *planes = core->bcPlanes;
120 *bpp = core->bcBitCount;
121 *compr = 0;
122 *size = 0;
123 return 0;
125 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
127 *width = header->biWidth;
128 *height = header->biHeight;
129 *planes = header->biPlanes;
130 *bpp = header->biBitCount;
131 *compr = header->biCompression;
132 *size = header->biSizeImage;
133 return 1;
135 ERR("(%d): unknown/wrong size for header\n", header->biSize );
136 return -1;
139 /*******************************************************************************************
140 * Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
142 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info, UINT coloruse )
144 LONG width, height;
145 WORD planes, bpp;
146 DWORD compr, size;
147 void *src_colors = (char *)info + info->bmiHeader.biSize;
148 unsigned int colors;
149 int bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size );
151 if (bitmap_type == -1) return FALSE;
153 colors = (bpp > 8) ? 0 : 1 << bpp;
155 if (bitmap_type == 1)
157 dst->bmiHeader = info->bmiHeader;
158 dst->bmiHeader.biSize = sizeof(dst->bmiHeader);
160 if (info->bmiHeader.biClrUsed) colors = info->bmiHeader.biClrUsed;
162 if (info->bmiHeader.biCompression == BI_BITFIELDS)
163 /* bitfields are always at bmiColors even in larger structures */
164 memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
165 else if (colors)
167 unsigned int size;
169 if (coloruse == DIB_PAL_COLORS)
170 size = colors * sizeof(WORD);
171 else
172 size = colors * sizeof(RGBQUAD);
173 memcpy( dst->bmiColors, src_colors, size );
176 else
178 dst->bmiHeader.biSize = sizeof(dst->bmiHeader);
179 dst->bmiHeader.biWidth = width;
180 dst->bmiHeader.biHeight = height;
181 dst->bmiHeader.biPlanes = planes;
182 dst->bmiHeader.biBitCount = bpp;
183 dst->bmiHeader.biCompression = compr;
184 dst->bmiHeader.biSizeImage = size;
185 dst->bmiHeader.biXPelsPerMeter = 0;
186 dst->bmiHeader.biYPelsPerMeter = 0;
187 dst->bmiHeader.biClrUsed = 0;
188 dst->bmiHeader.biClrImportant = 0;
190 if (colors)
192 if (coloruse == DIB_PAL_COLORS)
193 memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
194 else
196 unsigned int i;
197 RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
198 for (i = 0; i < colors; i++)
200 dst->bmiColors[i].rgbRed = triple[i].rgbtRed;
201 dst->bmiColors[i].rgbGreen = triple[i].rgbtGreen;
202 dst->bmiColors[i].rgbBlue = triple[i].rgbtBlue;
203 dst->bmiColors[i].rgbReserved = 0;
209 return TRUE;
212 static int fill_color_table_from_palette( BITMAPINFO *info, DC *dc )
214 PALETTEENTRY palEntry[256];
215 int i, colors = (info->bmiHeader.biBitCount > 8) ? 0 : 1 << info->bmiHeader.biBitCount;
217 if (info->bmiHeader.biClrUsed) colors = info->bmiHeader.biClrUsed;
219 if (!colors) return 0;
221 memset( palEntry, 0, sizeof(palEntry) );
222 if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
223 return 0;
225 for (i = 0; i < colors; i++)
227 info->bmiColors[i].rgbRed = palEntry[i].peRed;
228 info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
229 info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
230 info->bmiColors[i].rgbReserved = 0;
233 return colors;
236 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
237 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
238 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
239 const BITMAPINFO *info, UINT coloruse, DWORD rop )
241 DC *dc = get_nulldrv_dc( dev );
242 INT ret;
243 LONG width, height;
244 WORD planes, bpp;
245 DWORD compr, size;
246 HBITMAP hBitmap;
247 HDC hdcMem;
249 /* make sure we have a real implementation for StretchBlt and SetDIBits */
250 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pSetDIBits ) == dev)
251 return 0;
253 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
254 return 0;
256 if (width < 0) return 0;
258 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
259 info->bmiHeader.biCompression == BI_RGB)
261 /* Windows appears to have a fast case optimization
262 * that uses the wrong origin for top-down DIBs */
263 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
265 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
267 BITMAP bm;
268 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
269 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
270 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
271 bm.bmBitsPixel == bpp && bm.bmPlanes == planes)
273 /* fast path */
274 return SetDIBits( dev->hdc, hBitmap, 0, height, bits, info, coloruse );
279 hdcMem = CreateCompatibleDC( dev->hdc );
280 hBitmap = CreateCompatibleBitmap( dev->hdc, width, height );
281 SelectObject( hdcMem, hBitmap );
282 if (coloruse == DIB_PAL_COLORS)
283 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
285 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
287 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
288 * contain all the rectangle described in bmiHeader, but only part of it.
289 * This mean that those undescribed pixels must be left untouched.
290 * So, we first copy on a memory bitmap the current content of the
291 * destination rectangle, blit the DIB bits on top of it - hence leaving
292 * the gaps untouched -, and blitting the rectangle back.
293 * This insure that gaps are untouched on the destination rectangle
295 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
296 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
298 ret = SetDIBits( hdcMem, hBitmap, 0, height, bits, info, coloruse );
299 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
300 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
301 DeleteDC( hdcMem );
302 DeleteObject( hBitmap );
303 return ret;
306 /***********************************************************************
307 * StretchDIBits (GDI32.@)
309 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
310 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
311 const BITMAPINFO *info, UINT coloruse, DWORD rop )
313 DC *dc;
314 INT ret = 0;
316 if (!bits || !info) return 0;
318 if ((dc = get_dc_ptr( hdc )))
320 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
321 update_dc( dc );
322 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
323 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
324 release_dc_ptr( dc );
326 return ret;
330 /******************************************************************************
331 * SetDIBits [GDI32.@]
333 * Sets pixels in a bitmap using colors from DIB.
335 * PARAMS
336 * hdc [I] Handle to device context
337 * hbitmap [I] Handle to bitmap
338 * startscan [I] Starting scan line
339 * lines [I] Number of scan lines
340 * bits [I] Array of bitmap bits
341 * info [I] Address of structure with data
342 * coloruse [I] Type of color indexes to use
344 * RETURNS
345 * Success: Number of scan lines copied
346 * Failure: 0
348 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
349 UINT lines, LPCVOID bits, const BITMAPINFO *info,
350 UINT coloruse )
352 DC *dc = get_dc_ptr( hdc );
353 BOOL delete_hdc = FALSE;
354 PHYSDEV physdev;
355 BITMAPOBJ *bitmap;
356 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
357 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
358 INT result = 0;
360 if (coloruse == DIB_RGB_COLORS && !dc)
362 hdc = CreateCompatibleDC(0);
363 dc = get_dc_ptr( hdc );
364 delete_hdc = TRUE;
367 if (!dc) return 0;
369 update_dc( dc );
371 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
373 release_dc_ptr( dc );
374 if (delete_hdc) DeleteDC(hdc);
375 return 0;
378 if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse )) goto done;
380 physdev = GET_DC_PHYSDEV( dc, pSetDIBits );
381 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) goto done;
383 result = physdev->funcs->pSetDIBits( physdev, hbitmap, startscan, lines, bits, src_info, coloruse );
385 done:
386 GDI_ReleaseObj( hbitmap );
387 release_dc_ptr( dc );
388 if (delete_hdc) DeleteDC(hdc);
389 return result;
393 /***********************************************************************
394 * SetDIBitsToDevice (GDI32.@)
396 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
397 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
398 UINT lines, LPCVOID bits, const BITMAPINFO *info,
399 UINT coloruse )
401 INT ret = 0;
402 DC *dc;
404 if (!bits) return 0;
406 if ((dc = get_dc_ptr( hdc )))
408 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
409 update_dc( dc );
410 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
411 ySrc, startscan, lines, bits, info, coloruse );
412 release_dc_ptr( dc );
414 return ret;
417 /***********************************************************************
418 * SetDIBColorTable (GDI32.@)
420 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
422 DC * dc;
423 UINT result = 0;
424 BITMAPOBJ * bitmap;
426 if (!(dc = get_dc_ptr( hdc ))) return 0;
428 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
430 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
432 /* Check if currently selected bitmap is a DIB */
433 if (bitmap->color_table)
435 if (startpos < bitmap->nb_colors)
437 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
438 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
439 result = entries;
442 GDI_ReleaseObj( dc->hBitmap );
443 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
445 release_dc_ptr( dc );
446 return result;
450 /***********************************************************************
451 * GetDIBColorTable (GDI32.@)
453 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
455 DC * dc;
456 BITMAPOBJ *bitmap;
457 UINT result = 0;
459 if (!(dc = get_dc_ptr( hdc ))) return 0;
461 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
463 /* Check if currently selected bitmap is a DIB */
464 if (bitmap->color_table)
466 if (startpos < bitmap->nb_colors)
468 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
469 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
470 result = entries;
473 GDI_ReleaseObj( dc->hBitmap );
475 release_dc_ptr( dc );
476 return result;
479 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
480 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
481 { 0x00, 0x00, 0x00, 0x00 },
482 { 0x00, 0x00, 0x80, 0x00 },
483 { 0x00, 0x80, 0x00, 0x00 },
484 { 0x00, 0x80, 0x80, 0x00 },
485 { 0x80, 0x00, 0x00, 0x00 },
486 { 0x80, 0x00, 0x80, 0x00 },
487 { 0x80, 0x80, 0x00, 0x00 },
488 { 0xc0, 0xc0, 0xc0, 0x00 },
489 { 0xc0, 0xdc, 0xc0, 0x00 },
490 { 0xf0, 0xca, 0xa6, 0x00 },
491 { 0xf0, 0xfb, 0xff, 0x00 },
492 { 0xa4, 0xa0, 0xa0, 0x00 },
493 { 0x80, 0x80, 0x80, 0x00 },
494 { 0x00, 0x00, 0xff, 0x00 },
495 { 0x00, 0xff, 0x00, 0x00 },
496 { 0x00, 0xff, 0xff, 0x00 },
497 { 0xff, 0x00, 0x00, 0x00 },
498 { 0xff, 0x00, 0xff, 0x00 },
499 { 0xff, 0xff, 0x00, 0x00 },
500 { 0xff, 0xff, 0xff, 0x00 }
503 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
504 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
505 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
507 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
509 BITMAPINFOHEADER header;
511 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
512 header.biWidth = bmp->bitmap.bmWidth;
513 header.biHeight = bmp->bitmap.bmHeight;
514 header.biPlanes = 1;
516 if (bmp->dib)
518 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
519 switch (bmp->dib->dsBm.bmBitsPixel)
521 case 16:
522 case 32:
523 header.biCompression = BI_BITFIELDS;
524 break;
525 default:
526 header.biCompression = BI_RGB;
527 break;
530 else
532 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
533 header.biBitCount = bmp->bitmap.bmBitsPixel;
536 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
537 header.biXPelsPerMeter = 0;
538 header.biYPelsPerMeter = 0;
539 header.biClrUsed = 0;
540 header.biClrImportant = 0;
542 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
544 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
546 coreheader->bcWidth = header.biWidth;
547 coreheader->bcHeight = header.biHeight;
548 coreheader->bcPlanes = header.biPlanes;
549 coreheader->bcBitCount = header.biBitCount;
551 else
552 info->bmiHeader = header;
554 return abs(bmp->bitmap.bmHeight);
557 /************************************************************************
558 * copy_color_info
560 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
562 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
564 unsigned int colors = src->bmiHeader.biBitCount > 8 ? 0 : 1 << src->bmiHeader.biBitCount;
565 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
567 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
569 if (src->bmiHeader.biClrUsed) colors = src->bmiHeader.biClrUsed;
571 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
573 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
574 if (coloruse == DIB_PAL_COLORS)
575 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
576 else
578 unsigned int i;
579 for (i = 0; i < colors; i++)
581 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
582 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
583 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
587 else
589 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
590 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
592 if (src->bmiHeader.biCompression == BI_BITFIELDS)
593 /* bitfields are always at bmiColors even in larger structures */
594 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
595 else if (colors)
597 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
598 unsigned int size;
600 if (coloruse == DIB_PAL_COLORS)
601 size = colors * sizeof(WORD);
602 else
603 size = colors * sizeof(RGBQUAD);
604 memcpy( colorptr, src_colors, size );
609 static void fill_default_color_table( BITMAPINFO *info )
611 int i;
613 switch (info->bmiHeader.biBitCount)
615 case 1:
616 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
617 info->bmiColors[0].rgbReserved = 0;
618 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
619 info->bmiColors[1].rgbReserved = 0;
620 break;
622 case 4:
623 /* The EGA palette is the first and last 8 colours of the default palette
624 with the innermost pair swapped */
625 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
626 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
627 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
628 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
629 break;
631 case 8:
632 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
633 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
634 for (i = 10; i < 246; i++)
636 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
637 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
638 info->bmiColors[i].rgbBlue = i & 0xc0;
639 info->bmiColors[i].rgbReserved = 0;
641 break;
643 default:
644 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
648 /******************************************************************************
649 * GetDIBits [GDI32.@]
651 * Retrieves bits of bitmap and copies to buffer.
653 * RETURNS
654 * Success: Number of scan lines copied from bitmap
655 * Failure: 0
657 INT WINAPI GetDIBits(
658 HDC hdc, /* [in] Handle to device context */
659 HBITMAP hbitmap, /* [in] Handle to bitmap */
660 UINT startscan, /* [in] First scan line to set in dest bitmap */
661 UINT lines, /* [in] Number of scan lines to copy */
662 LPVOID bits, /* [out] Address of array for bitmap bits */
663 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
664 UINT coloruse) /* [in] RGB or palette index */
666 DC * dc;
667 BITMAPOBJ * bmp;
668 int i;
669 int bitmap_type;
670 LONG width;
671 LONG height;
672 WORD planes, bpp;
673 DWORD compr, size;
674 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
675 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
676 unsigned int colors = 0;
678 if (!info) return 0;
680 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
681 if (bitmap_type == -1)
683 ERR("Invalid bitmap format\n");
684 return 0;
686 if (!(dc = get_dc_ptr( hdc )))
688 SetLastError( ERROR_INVALID_PARAMETER );
689 return 0;
691 update_dc( dc );
692 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
694 release_dc_ptr( dc );
695 return 0;
699 if (bpp == 0) /* query bitmap info only */
701 lines = fill_query_info( info, bmp );
702 goto done;
705 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
706 own copy and transfer the colour info back at the end */
708 dst_info->bmiHeader.biSize = sizeof(dst_info->bmiHeader);
709 dst_info->bmiHeader.biWidth = width;
710 dst_info->bmiHeader.biHeight = height;
711 dst_info->bmiHeader.biPlanes = planes;
712 dst_info->bmiHeader.biBitCount = bpp;
713 dst_info->bmiHeader.biCompression = compr;
714 dst_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
715 dst_info->bmiHeader.biXPelsPerMeter = 0;
716 dst_info->bmiHeader.biYPelsPerMeter = 0;
717 dst_info->bmiHeader.biClrUsed = 0;
718 dst_info->bmiHeader.biClrImportant = 0;
720 switch (bpp)
722 case 1:
723 case 4:
724 case 8:
726 colors = 1 << bpp;
728 /* If the bitmap object is a dib section at the
729 same color depth then get the color map from it */
730 if (bmp->dib && bpp == bmp->dib->dsBm.bmBitsPixel && coloruse == DIB_RGB_COLORS)
732 colors = min( colors, bmp->nb_colors );
733 if (colors != 1 << bpp) dst_info->bmiHeader.biClrUsed = colors;
734 memcpy( dst_info->bmiColors, bmp->color_table, colors * sizeof(RGBQUAD) );
737 /* For color DDBs in native depth (mono DDBs always have a black/white palette):
738 Generate the color map from the selected palette. In the DIB_PAL_COLORS
739 case we'll fix up the indices after the format conversion. */
740 else if ( (bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) || coloruse == DIB_PAL_COLORS )
742 if (!fill_color_table_from_palette( dst_info, dc ))
744 lines = 0;
745 goto done;
748 else
749 fill_default_color_table( dst_info );
750 break;
753 case 15:
754 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
755 memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
756 break;
758 case 16:
759 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
761 if (bmp->dib)
763 if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
764 memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
765 else
766 memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
768 else
769 memcpy( dst_info->bmiColors, bit_fields_565, sizeof(bit_fields_565) );
771 break;
773 case 24:
774 case 32:
775 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
777 if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
778 memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
779 else
780 memcpy( dst_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
782 break;
785 if (bits && lines)
787 PHYSDEV physdev;
788 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
789 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
790 struct gdi_image_bits src_bits;
791 struct bitblt_coords src;
792 DWORD err;
794 /* FIXME: will need updating once the dib driver has pGetImage. */
795 physdev = GET_DC_PHYSDEV( dc, pGetImage );
797 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
799 src.visrect.left = 0;
800 src.visrect.right = min( width, bmp->bitmap.bmWidth );
802 if (startscan >= bmp->bitmap.bmHeight) /* constrain lines to within src bitmap */
803 lines = 0;
804 else
805 lines = min( lines, bmp->bitmap.bmHeight - startscan );
806 lines = min( lines, abs(height) ); /* and constrain to within dest bitmap */
808 if (lines == 0) goto done;
810 src.visrect.bottom = bmp->bitmap.bmHeight - startscan;
811 src.visrect.top = src.visrect.bottom - lines;
812 src.x = src.visrect.left;
813 src.y = src.visrect.top;
814 src.width = src.visrect.right - src.visrect.left;
815 src.height = src.visrect.bottom - src.visrect.top;
817 err = physdev->funcs->pGetImage( physdev, hbitmap, src_info, &src_bits, &src );
819 if(err)
821 lines = 0;
822 goto done;
825 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
827 if (bmp->dib)
828 memcpy( src_info->bmiColors, bmp->color_table, bmp->nb_colors * sizeof(RGBQUAD) );
829 else
830 fill_default_color_table( src_info );
833 if(dst_info->bmiHeader.biHeight > 0)
834 dst_info->bmiHeader.biHeight = lines;
835 else
836 dst_info->bmiHeader.biHeight = -lines;
838 convert_bitmapinfo( src_info, src_bits.ptr, &src.visrect, dst_info, bits );
839 if (src_bits.free) src_bits.free( &src_bits );
841 else lines = abs(height);
843 if (coloruse == DIB_PAL_COLORS)
845 WORD *index = (WORD *)dst_info->bmiColors;
846 for (i = 0; i < colors; i++, index++)
847 *index = i;
850 copy_color_info( info, dst_info, coloruse );
852 done:
853 release_dc_ptr( dc );
854 GDI_ReleaseObj( hbitmap );
855 return lines;
859 /***********************************************************************
860 * CreateDIBitmap (GDI32.@)
862 * Creates a DDB (device dependent bitmap) from a DIB.
863 * The DDB will have the same color depth as the reference DC.
865 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
866 DWORD init, LPCVOID bits, const BITMAPINFO *data,
867 UINT coloruse )
869 HBITMAP handle;
870 LONG width;
871 LONG height;
872 WORD planes, bpp;
873 DWORD compr, size;
875 if (!header) return 0;
877 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
879 if (width < 0)
881 TRACE("Bitmap has a negative width\n");
882 return 0;
885 /* Top-down DIBs have a negative height */
886 if (height < 0) height = -height;
888 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
889 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
891 if (hdc == NULL)
892 handle = CreateBitmap( width, height, 1, 1, NULL );
893 else
894 handle = CreateCompatibleBitmap( hdc, width, height );
896 if (handle)
898 if (init & CBM_INIT)
900 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
902 DeleteObject( handle );
903 handle = 0;
908 return handle;
911 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
912 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
914 RGBQUAD *colorTable;
915 unsigned int colors, i;
916 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
918 if (core_info)
920 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
922 else
924 colors = info->bmiHeader.biClrUsed;
925 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
928 if (colors > 256) {
929 ERR("called with >256 colors!\n");
930 return;
933 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
935 if(coloruse == DIB_RGB_COLORS)
937 if (core_info)
939 /* Convert RGBTRIPLEs to RGBQUADs */
940 for (i=0; i < colors; i++)
942 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
943 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
944 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
945 colorTable[i].rgbReserved = 0;
948 else
950 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
953 else
955 PALETTEENTRY entries[256];
956 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
957 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
959 for (i = 0; i < colors; i++, index++)
961 PALETTEENTRY *entry = &entries[*index % count];
962 colorTable[i].rgbRed = entry->peRed;
963 colorTable[i].rgbGreen = entry->peGreen;
964 colorTable[i].rgbBlue = entry->peBlue;
965 colorTable[i].rgbReserved = 0;
968 bmp->color_table = colorTable;
969 bmp->nb_colors = colors;
972 /***********************************************************************
973 * CreateDIBSection (GDI32.@)
975 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
976 VOID **bits, HANDLE section, DWORD offset)
978 HBITMAP ret = 0;
979 DC *dc;
980 BOOL bDesktopDC = FALSE;
981 DIBSECTION *dib;
982 BITMAPOBJ *bmp;
983 int bitmap_type;
984 LONG width, height;
985 WORD planes, bpp;
986 DWORD compression, sizeImage;
987 void *mapBits = NULL;
989 if(!bmi){
990 if(bits) *bits = NULL;
991 return NULL;
994 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
995 &planes, &bpp, &compression, &sizeImage )) == -1))
996 return 0;
998 switch (bpp)
1000 case 16:
1001 case 32:
1002 if (compression == BI_BITFIELDS) break;
1003 /* fall through */
1004 case 1:
1005 case 4:
1006 case 8:
1007 case 24:
1008 if (compression == BI_RGB) break;
1009 /* fall through */
1010 default:
1011 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1012 return 0;
1015 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1017 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1018 width, height, planes, bpp, compression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1019 sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1021 dib->dsBm.bmType = 0;
1022 dib->dsBm.bmWidth = width;
1023 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1024 dib->dsBm.bmWidthBytes = get_dib_stride( width, bpp );
1025 dib->dsBm.bmPlanes = planes;
1026 dib->dsBm.bmBitsPixel = bpp;
1027 dib->dsBm.bmBits = NULL;
1029 if (!bitmap_type) /* core header */
1031 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1032 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1033 dib->dsBmih.biWidth = width;
1034 dib->dsBmih.biHeight = height;
1035 dib->dsBmih.biPlanes = planes;
1036 dib->dsBmih.biBitCount = bpp;
1037 dib->dsBmih.biCompression = compression;
1038 dib->dsBmih.biXPelsPerMeter = 0;
1039 dib->dsBmih.biYPelsPerMeter = 0;
1040 dib->dsBmih.biClrUsed = 0;
1041 dib->dsBmih.biClrImportant = 0;
1043 else
1045 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1046 dib->dsBmih = bmi->bmiHeader;
1047 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1050 /* set number of entries in bmi.bmiColors table */
1051 if( bpp <= 8 )
1052 dib->dsBmih.biClrUsed = 1 << bpp;
1054 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1056 /* set dsBitfields values */
1057 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1059 if((bpp == 15 || bpp == 16) && compression == BI_RGB)
1061 /* In this case Windows changes biCompression to BI_BITFIELDS,
1062 however for now we won't do this, as there are a lot
1063 of places where BI_BITFIELDS is currently unsupported. */
1065 /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
1066 dib->dsBitfields[0] = 0x7c00;
1067 dib->dsBitfields[1] = 0x03e0;
1068 dib->dsBitfields[2] = 0x001f;
1070 else if(compression == BI_BITFIELDS)
1072 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1073 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1074 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1077 /* get storage location for DIB bits */
1079 if (section)
1081 SYSTEM_INFO SystemInfo;
1082 DWORD mapOffset;
1083 INT mapSize;
1085 GetSystemInfo( &SystemInfo );
1086 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1087 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1088 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1089 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1091 else
1093 offset = 0;
1094 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1095 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1097 dib->dshSection = section;
1098 dib->dsOffset = offset;
1100 if (!dib->dsBm.bmBits)
1102 HeapFree( GetProcessHeap(), 0, dib );
1103 return 0;
1106 /* If the reference hdc is null, take the desktop dc */
1107 if (hdc == 0)
1109 hdc = CreateCompatibleDC(0);
1110 bDesktopDC = TRUE;
1113 if (!(dc = get_dc_ptr( hdc ))) goto error;
1115 /* create Device Dependent Bitmap and add DIB pointer */
1116 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1117 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1119 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1121 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1122 bmp->dib = dib;
1123 bmp->funcs = physdev->funcs;
1124 /* create local copy of DIB palette */
1125 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1126 GDI_ReleaseObj( ret );
1128 if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1130 DeleteObject( ret );
1131 ret = 0;
1135 release_dc_ptr( dc );
1136 if (bDesktopDC) DeleteDC( hdc );
1137 if (ret && bits) *bits = dib->dsBm.bmBits;
1138 return ret;
1140 error:
1141 if (bDesktopDC) DeleteDC( hdc );
1142 if (section) UnmapViewOfFile( mapBits );
1143 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1144 HeapFree( GetProcessHeap(), 0, dib );
1145 return 0;