gdi32: Don't use a dib-section's bitfields unless its depth matches the requested...
[wine/multimedia.git] / dlls / gdi32 / dib.c
blob5103919ff29051f229ede1f17808fe768925ab60
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>
67 #include "windef.h"
68 #include "winbase.h"
69 #include "gdi_private.h"
70 #include "wine/debug.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
76 Some of the following helper functions are duplicated in
77 dlls/x11drv/dib.c
80 /***********************************************************************
81 * DIB_GetDIBWidthBytes
83 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
85 int DIB_GetDIBWidthBytes( int width, int depth )
87 int words;
89 switch(depth)
91 case 1: words = (width + 31) / 32; break;
92 case 4: words = (width + 7) / 8; break;
93 case 8: words = (width + 3) / 4; break;
94 case 15:
95 case 16: words = (width + 1) / 2; break;
96 case 24: words = (width * 3 + 3)/4; break;
98 default:
99 WARN("(%d): Unsupported depth\n", depth );
100 /* fall through */
101 case 32:
102 words = width;
104 return 4 * words;
107 /***********************************************************************
108 * DIB_GetDIBImageBytes
110 * Return the number of bytes used to hold the image in a DIB bitmap.
112 int DIB_GetDIBImageBytes( int width, int height, int depth )
114 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
118 /***********************************************************************
119 * bitmap_info_size
121 * Return the size of the bitmap info structure including color table.
123 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
125 unsigned int colors, size, masks = 0;
127 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
129 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
130 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
131 return sizeof(BITMAPCOREHEADER) + colors *
132 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
134 else /* assume BITMAPINFOHEADER */
136 colors = info->bmiHeader.biClrUsed;
137 if (colors > 256) colors = 256;
138 if (!colors && (info->bmiHeader.biBitCount <= 8))
139 colors = 1 << info->bmiHeader.biBitCount;
140 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
141 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
142 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
147 /***********************************************************************
148 * DIB_GetBitmapInfo
150 * Get the info from a bitmap header.
151 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
153 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
154 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
156 if (header->biSize == sizeof(BITMAPCOREHEADER))
158 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
159 *width = core->bcWidth;
160 *height = core->bcHeight;
161 *planes = core->bcPlanes;
162 *bpp = core->bcBitCount;
163 *compr = 0;
164 *size = 0;
165 return 0;
167 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
169 *width = header->biWidth;
170 *height = header->biHeight;
171 *planes = header->biPlanes;
172 *bpp = header->biBitCount;
173 *compr = header->biCompression;
174 *size = header->biSizeImage;
175 return 1;
177 ERR("(%d): unknown/wrong size for header\n", header->biSize );
178 return -1;
181 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
182 INT CDECL nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
183 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
184 const BITMAPINFO *info, UINT coloruse, DWORD rop )
186 DC *dc = get_nulldrv_dc( dev );
187 INT ret;
188 LONG width, height;
189 WORD planes, bpp;
190 DWORD compr, size;
191 HBITMAP hBitmap;
192 HDC hdcMem;
194 /* make sure we have a real implementation for StretchBlt and SetDIBits */
195 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pSetDIBits ) == dev)
196 return 0;
198 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
199 return 0;
201 if (width < 0) return 0;
203 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
204 info->bmiHeader.biCompression == BI_RGB)
206 /* Windows appears to have a fast case optimization
207 * that uses the wrong origin for top-down DIBs */
208 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
210 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
212 BITMAP bm;
213 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
214 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
215 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
216 bm.bmBitsPixel == bpp && bm.bmPlanes == planes)
218 /* fast path */
219 return SetDIBits( dev->hdc, hBitmap, 0, height, bits, info, coloruse );
224 hdcMem = CreateCompatibleDC( dev->hdc );
225 hBitmap = CreateCompatibleBitmap( dev->hdc, width, height );
226 SelectObject( hdcMem, hBitmap );
227 if (coloruse == DIB_PAL_COLORS)
228 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
230 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
232 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
233 * contain all the rectangle described in bmiHeader, but only part of it.
234 * This mean that those undescribed pixels must be left untouched.
235 * So, we first copy on a memory bitmap the current content of the
236 * destination rectangle, blit the DIB bits on top of it - hence leaving
237 * the gaps untouched -, and blitting the rectangle back.
238 * This insure that gaps are untouched on the destination rectangle
240 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
241 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
243 ret = SetDIBits( hdcMem, hBitmap, 0, height, bits, info, coloruse );
244 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
245 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
246 DeleteDC( hdcMem );
247 DeleteObject( hBitmap );
248 return ret;
251 /***********************************************************************
252 * StretchDIBits (GDI32.@)
254 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
255 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
256 const BITMAPINFO *info, UINT coloruse, DWORD rop )
258 DC *dc;
259 INT ret = 0;
261 if (!bits || !info) return 0;
263 if ((dc = get_dc_ptr( hdc )))
265 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
266 update_dc( dc );
267 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
268 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
269 release_dc_ptr( dc );
271 return ret;
275 /******************************************************************************
276 * SetDIBits [GDI32.@]
278 * Sets pixels in a bitmap using colors from DIB.
280 * PARAMS
281 * hdc [I] Handle to device context
282 * hbitmap [I] Handle to bitmap
283 * startscan [I] Starting scan line
284 * lines [I] Number of scan lines
285 * bits [I] Array of bitmap bits
286 * info [I] Address of structure with data
287 * coloruse [I] Type of color indexes to use
289 * RETURNS
290 * Success: Number of scan lines copied
291 * Failure: 0
293 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
294 UINT lines, LPCVOID bits, const BITMAPINFO *info,
295 UINT coloruse )
297 DC *dc = get_dc_ptr( hdc );
298 BOOL delete_hdc = FALSE;
299 PHYSDEV physdev;
300 BITMAPOBJ *bitmap;
301 INT result = 0;
303 if (coloruse == DIB_RGB_COLORS && !dc)
305 hdc = CreateCompatibleDC(0);
306 dc = get_dc_ptr( hdc );
307 delete_hdc = TRUE;
310 if (!dc) return 0;
312 update_dc( dc );
314 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
316 release_dc_ptr( dc );
317 if (delete_hdc) DeleteDC(hdc);
318 return 0;
321 physdev = GET_DC_PHYSDEV( dc, pSetDIBits );
322 if (BITMAP_SetOwnerDC( hbitmap, physdev ))
323 result = physdev->funcs->pSetDIBits( physdev, hbitmap, startscan, lines, bits, info, coloruse );
325 GDI_ReleaseObj( hbitmap );
326 release_dc_ptr( dc );
327 if (delete_hdc) DeleteDC(hdc);
328 return result;
332 /***********************************************************************
333 * SetDIBitsToDevice (GDI32.@)
335 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
336 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
337 UINT lines, LPCVOID bits, const BITMAPINFO *info,
338 UINT coloruse )
340 INT ret = 0;
341 DC *dc;
343 if (!bits) return 0;
345 if ((dc = get_dc_ptr( hdc )))
347 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
348 update_dc( dc );
349 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
350 ySrc, startscan, lines, bits, info, coloruse );
351 release_dc_ptr( dc );
353 return ret;
356 /***********************************************************************
357 * SetDIBColorTable (GDI32.@)
359 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
361 DC * dc;
362 UINT result = 0;
363 BITMAPOBJ * bitmap;
365 if (!(dc = get_dc_ptr( hdc ))) return 0;
367 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
369 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
371 /* Check if currently selected bitmap is a DIB */
372 if (bitmap->color_table)
374 if (startpos < bitmap->nb_colors)
376 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
377 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
378 result = entries;
381 GDI_ReleaseObj( dc->hBitmap );
382 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
384 release_dc_ptr( dc );
385 return result;
389 /***********************************************************************
390 * GetDIBColorTable (GDI32.@)
392 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
394 DC * dc;
395 BITMAPOBJ *bitmap;
396 UINT result = 0;
398 if (!(dc = get_dc_ptr( hdc ))) return 0;
400 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
402 /* Check if currently selected bitmap is a DIB */
403 if (bitmap->color_table)
405 if (startpos < bitmap->nb_colors)
407 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
408 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
409 result = entries;
412 GDI_ReleaseObj( dc->hBitmap );
414 release_dc_ptr( dc );
415 return result;
418 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
419 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
420 { 0x00, 0x00, 0x00, 0x00 },
421 { 0x00, 0x00, 0x80, 0x00 },
422 { 0x00, 0x80, 0x00, 0x00 },
423 { 0x00, 0x80, 0x80, 0x00 },
424 { 0x80, 0x00, 0x00, 0x00 },
425 { 0x80, 0x00, 0x80, 0x00 },
426 { 0x80, 0x80, 0x00, 0x00 },
427 { 0xc0, 0xc0, 0xc0, 0x00 },
428 { 0xc0, 0xdc, 0xc0, 0x00 },
429 { 0xf0, 0xca, 0xa6, 0x00 },
430 { 0xf0, 0xfb, 0xff, 0x00 },
431 { 0xa4, 0xa0, 0xa0, 0x00 },
432 { 0x80, 0x80, 0x80, 0x00 },
433 { 0x00, 0x00, 0xff, 0x00 },
434 { 0x00, 0xff, 0x00, 0x00 },
435 { 0x00, 0xff, 0xff, 0x00 },
436 { 0xff, 0x00, 0x00, 0x00 },
437 { 0xff, 0x00, 0xff, 0x00 },
438 { 0xff, 0xff, 0x00, 0x00 },
439 { 0xff, 0xff, 0xff, 0x00 }
442 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
443 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
444 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
446 /******************************************************************************
447 * GetDIBits [GDI32.@]
449 * Retrieves bits of bitmap and copies to buffer.
451 * RETURNS
452 * Success: Number of scan lines copied from bitmap
453 * Failure: 0
455 INT WINAPI GetDIBits(
456 HDC hdc, /* [in] Handle to device context */
457 HBITMAP hbitmap, /* [in] Handle to bitmap */
458 UINT startscan, /* [in] First scan line to set in dest bitmap */
459 UINT lines, /* [in] Number of scan lines to copy */
460 LPVOID bits, /* [out] Address of array for bitmap bits */
461 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
462 UINT coloruse) /* [in] RGB or palette index */
464 DC * dc;
465 BITMAPOBJ * bmp;
466 int i;
467 int bitmap_type;
468 BOOL core_header;
469 LONG width;
470 LONG height;
471 WORD planes, bpp;
472 DWORD compr, size;
473 void* colorPtr;
474 RGBQUAD quad_buf[256];
475 RGBQUAD* rgbQuads = quad_buf;
477 if (!info) return 0;
479 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
480 if (bitmap_type == -1)
482 ERR("Invalid bitmap format\n");
483 return 0;
485 core_header = (bitmap_type == 0);
486 if (!(dc = get_dc_ptr( hdc )))
488 SetLastError( ERROR_INVALID_PARAMETER );
489 return 0;
491 update_dc( dc );
492 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
494 release_dc_ptr( dc );
495 return 0;
498 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
499 if(!core_header) rgbQuads = colorPtr;
501 /* Transfer color info */
503 switch (bpp)
505 case 0: /* query bitmap info only */
506 if (core_header)
508 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
509 coreheader->bcWidth = bmp->bitmap.bmWidth;
510 coreheader->bcHeight = bmp->bitmap.bmHeight;
511 coreheader->bcPlanes = 1;
512 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
514 else
516 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
517 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
518 info->bmiHeader.biPlanes = 1;
519 info->bmiHeader.biSizeImage =
520 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
521 bmp->bitmap.bmHeight,
522 bmp->bitmap.bmBitsPixel );
523 if (bmp->dib)
525 info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
526 switch (bmp->dib->dsBm.bmBitsPixel)
528 case 16:
529 case 32:
530 info->bmiHeader.biCompression = BI_BITFIELDS;
531 break;
532 default:
533 info->bmiHeader.biCompression = BI_RGB;
534 break;
537 else
539 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
540 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
542 info->bmiHeader.biXPelsPerMeter = 0;
543 info->bmiHeader.biYPelsPerMeter = 0;
544 info->bmiHeader.biClrUsed = 0;
545 info->bmiHeader.biClrImportant = 0;
547 /* Windows 2000 doesn't touch the additional struct members if
548 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
550 lines = abs(bmp->bitmap.bmHeight);
551 goto done;
553 case 1:
554 case 4:
555 case 8:
557 unsigned int colors = 1 << bpp;
559 if (!core_header) info->bmiHeader.biClrUsed = 0;
561 if (coloruse == DIB_PAL_COLORS)
563 WORD *index = colorPtr;
564 for (i = 0; i < colors; i++, index++)
565 *index = i;
567 break;
570 /* If the bitmap object already has a dib section at the
571 same color depth then get the color map from it */
573 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp)
575 colors = min( colors, bmp->nb_colors );
577 if (!core_header && colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
579 memcpy(rgbQuads, bmp->color_table, colors * sizeof(RGBQUAD));
582 /* For color DDBs in native depth (mono DDBs always have a black/white palette):
583 Generate the color map from the selected palette */
585 else if (bpp > 1 && bpp == bmp->bitmap.bmBitsPixel)
587 PALETTEENTRY palEntry[256];
589 memset( palEntry, 0, sizeof(palEntry) );
590 if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
592 release_dc_ptr( dc );
593 GDI_ReleaseObj( hbitmap );
594 return 0;
596 for (i = 0; i < colors; i++)
598 rgbQuads[i].rgbRed = palEntry[i].peRed;
599 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
600 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
601 rgbQuads[i].rgbReserved = 0;
604 else
606 switch (bpp)
608 case 1:
609 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
610 rgbQuads[0].rgbReserved = 0;
611 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
612 rgbQuads[1].rgbReserved = 0;
613 break;
615 case 4:
616 /* The EGA palette is the first and last 8 colours of the default palette
617 with the innermost pair swapped */
618 memcpy(rgbQuads, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
619 memcpy(rgbQuads + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
620 memcpy(rgbQuads + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
621 memcpy(rgbQuads + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
622 break;
624 case 8:
625 memcpy(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
626 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
627 for (i = 10; i < 246; i++)
629 rgbQuads[i].rgbRed = (i & 0x07) << 5;
630 rgbQuads[i].rgbGreen = (i & 0x38) << 2;
631 rgbQuads[i].rgbBlue = i & 0xc0;
632 rgbQuads[i].rgbReserved = 0;
637 if(core_header)
639 RGBTRIPLE *triple = (RGBTRIPLE *)colorPtr;
640 for (i = 0; i < colors; i++)
642 triple[i].rgbtRed = rgbQuads[i].rgbRed;
643 triple[i].rgbtGreen = rgbQuads[i].rgbGreen;
644 triple[i].rgbtBlue = rgbQuads[i].rgbBlue;
648 break;
651 case 15:
652 if (info->bmiHeader.biCompression == BI_BITFIELDS)
653 memcpy( info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
654 break;
656 case 16:
657 if (info->bmiHeader.biCompression == BI_BITFIELDS)
659 if (bmp->dib)
661 if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
662 memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
663 else
664 memcpy( info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
666 else
667 memcpy( info->bmiColors, bit_fields_565, sizeof(bit_fields_565) );
669 break;
671 case 24:
672 case 32:
673 if (info->bmiHeader.biCompression == BI_BITFIELDS)
675 if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
676 memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
677 else
678 memcpy( info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
680 break;
683 if (bits && lines)
685 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
686 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
688 /*FIXME: Only RGB dibs supported for now */
689 unsigned int srcwidth = bmp->dib->dsBm.bmWidth;
690 int srcwidthb = bmp->dib->dsBm.bmWidthBytes;
691 unsigned int dstwidth = width;
692 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
693 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
694 unsigned int x, y, width, widthb;
697 * If copying from a top-down source bitmap, move the source
698 * pointer to the end of the source bitmap and negate the width
699 * so that we copy the bits upside-down.
701 if (bmp->dib->dsBmih.biHeight < 0)
703 sbits += (srcwidthb * (int)(abs(bmp->dib->dsBmih.biHeight) - 2 * startscan - 1));
704 srcwidthb = -srcwidthb;
706 /*Same for the destination.*/
707 if (height < 0)
709 dbits = (LPBYTE)bits + (dstwidthb * (lines - 1));
710 dstwidthb = -dstwidthb;
712 switch( bpp ) {
714 case 15:
715 case 16: /* 16 bpp dstDIB */
717 LPWORD dstbits = (LPWORD)dbits;
718 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
720 /* FIXME: BI_BITFIELDS not supported yet */
722 switch(bmp->dib->dsBm.bmBitsPixel) {
724 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
726 widthb = min(abs(srcwidthb), abs(dstwidthb));
727 /* FIXME: BI_BITFIELDS not supported yet */
728 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
729 memcpy(dbits, sbits, widthb);
731 break;
733 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
735 LPBYTE srcbits = sbits;
737 width = min(srcwidth, dstwidth);
738 for( y = 0; y < lines; y++) {
739 for( x = 0; x < width; x++, srcbits += 3)
740 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
741 (((WORD)srcbits[1] << 2) & gmask) |
742 (((WORD)srcbits[2] << 7) & rmask);
744 dstbits = (LPWORD)(dbits+=dstwidthb);
745 srcbits = (sbits += srcwidthb);
748 break;
750 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
752 LPDWORD srcbits = (LPDWORD)sbits;
753 DWORD val;
755 width = min(srcwidth, dstwidth);
756 for( y = 0; y < lines; y++) {
757 for( x = 0; x < width; x++ ) {
758 val = *srcbits++;
759 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
760 ((val >> 9) & rmask));
762 dstbits = (LPWORD)(dbits+=dstwidthb);
763 srcbits = (LPDWORD)(sbits+=srcwidthb);
766 break;
768 default: /* ? bit bmp -> 16 bit DIB */
769 FIXME("15/16 bit DIB %d bit bitmap\n",
770 bmp->bitmap.bmBitsPixel);
771 break;
774 break;
776 case 24: /* 24 bpp dstDIB */
778 LPBYTE dstbits = dbits;
780 switch(bmp->dib->dsBm.bmBitsPixel) {
782 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
784 LPWORD srcbits = (LPWORD)sbits;
785 WORD val;
787 width = min(srcwidth, dstwidth);
788 /* FIXME: BI_BITFIELDS not supported yet */
789 for( y = 0; y < lines; y++) {
790 for( x = 0; x < width; x++ ) {
791 val = *srcbits++;
792 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
793 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
794 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
796 dstbits = dbits+=dstwidthb;
797 srcbits = (LPWORD)(sbits+=srcwidthb);
800 break;
802 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
804 widthb = min(abs(srcwidthb), abs(dstwidthb));
805 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
806 memcpy(dbits, sbits, widthb);
808 break;
810 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
812 LPBYTE srcbits = sbits;
814 width = min(srcwidth, dstwidth);
815 for( y = 0; y < lines; y++) {
816 for( x = 0; x < width; x++, srcbits++ ) {
817 *dstbits++ = *srcbits++;
818 *dstbits++ = *srcbits++;
819 *dstbits++ = *srcbits++;
821 dstbits = dbits+=dstwidthb;
822 srcbits = sbits+=srcwidthb;
825 break;
827 default: /* ? bit bmp -> 24 bit DIB */
828 FIXME("24 bit DIB %d bit bitmap\n",
829 bmp->bitmap.bmBitsPixel);
830 break;
833 break;
835 case 32: /* 32 bpp dstDIB */
837 LPDWORD dstbits = (LPDWORD)dbits;
839 /* FIXME: BI_BITFIELDS not supported yet */
841 switch(bmp->dib->dsBm.bmBitsPixel) {
842 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
844 LPWORD srcbits = (LPWORD)sbits;
845 DWORD val;
847 width = min(srcwidth, dstwidth);
848 /* FIXME: BI_BITFIELDS not supported yet */
849 for( y = 0; y < lines; y++) {
850 for( x = 0; x < width; x++ ) {
851 val = (DWORD)*srcbits++;
852 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
853 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
854 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
856 dstbits=(LPDWORD)(dbits+=dstwidthb);
857 srcbits=(LPWORD)(sbits+=srcwidthb);
860 break;
862 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
864 LPBYTE srcbits = sbits;
866 width = min(srcwidth, dstwidth);
867 for( y = 0; y < lines; y++) {
868 for( x = 0; x < width; x++, srcbits+=3 )
869 *dstbits++ = srcbits[0] |
870 (srcbits[1] << 8) |
871 (srcbits[2] << 16);
872 dstbits=(LPDWORD)(dbits+=dstwidthb);
873 srcbits=(sbits+=srcwidthb);
876 break;
878 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
880 widthb = min(abs(srcwidthb), abs(dstwidthb));
881 /* FIXME: BI_BITFIELDS not supported yet */
882 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
883 memcpy(dbits, sbits, widthb);
886 break;
888 default: /* ? bit bmp -> 32 bit DIB */
889 FIXME("32 bit DIB %d bit bitmap\n",
890 bmp->bitmap.bmBitsPixel);
891 break;
894 break;
896 default: /* ? bit DIB */
897 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
898 break;
901 /* Otherwise, get bits from the XImage */
902 else
904 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDIBits );
905 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
906 else lines = physdev->funcs->pGetDIBits( physdev, hbitmap, startscan,
907 lines, bits, info, coloruse );
910 else lines = abs(height);
912 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
913 if bits == NULL and bpp != 0, only biSizeImage and the color table are
914 filled in. */
915 if (!core_header)
917 /* FIXME: biSizeImage should be calculated according to the selected
918 compression algorithm if biCompression != BI_RGB */
919 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
920 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
922 TRACE("biWidth = %d, biHeight = %d\n", width, height);
924 done:
925 release_dc_ptr( dc );
926 GDI_ReleaseObj( hbitmap );
927 return lines;
931 /***********************************************************************
932 * CreateDIBitmap (GDI32.@)
934 * Creates a DDB (device dependent bitmap) from a DIB.
935 * The DDB will have the same color depth as the reference DC.
937 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
938 DWORD init, LPCVOID bits, const BITMAPINFO *data,
939 UINT coloruse )
941 HBITMAP handle;
942 LONG width;
943 LONG height;
944 WORD planes, bpp;
945 DWORD compr, size;
947 if (!header) return 0;
949 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
951 if (width < 0)
953 TRACE("Bitmap has a negative width\n");
954 return 0;
957 /* Top-down DIBs have a negative height */
958 if (height < 0) height = -height;
960 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
961 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
963 if (hdc == NULL)
964 handle = CreateBitmap( width, height, 1, 1, NULL );
965 else
966 handle = CreateCompatibleBitmap( hdc, width, height );
968 if (handle)
970 if (init & CBM_INIT)
972 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
974 DeleteObject( handle );
975 handle = 0;
980 return handle;
983 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
984 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
986 RGBQUAD *colorTable;
987 unsigned int colors, i;
988 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
990 if (core_info)
992 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
994 else
996 colors = info->bmiHeader.biClrUsed;
997 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1000 if (colors > 256) {
1001 ERR("called with >256 colors!\n");
1002 return;
1005 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1007 if(coloruse == DIB_RGB_COLORS)
1009 if (core_info)
1011 /* Convert RGBTRIPLEs to RGBQUADs */
1012 for (i=0; i < colors; i++)
1014 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1015 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1016 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1017 colorTable[i].rgbReserved = 0;
1020 else
1022 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1025 else
1027 PALETTEENTRY entries[256];
1028 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1029 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1031 for (i = 0; i < colors; i++, index++)
1033 PALETTEENTRY *entry = &entries[*index % count];
1034 colorTable[i].rgbRed = entry->peRed;
1035 colorTable[i].rgbGreen = entry->peGreen;
1036 colorTable[i].rgbBlue = entry->peBlue;
1037 colorTable[i].rgbReserved = 0;
1040 bmp->color_table = colorTable;
1041 bmp->nb_colors = colors;
1044 /***********************************************************************
1045 * CreateDIBSection (GDI32.@)
1047 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1048 VOID **bits, HANDLE section, DWORD offset)
1050 HBITMAP ret = 0;
1051 DC *dc;
1052 BOOL bDesktopDC = FALSE;
1053 DIBSECTION *dib;
1054 BITMAPOBJ *bmp;
1055 int bitmap_type;
1056 LONG width, height;
1057 WORD planes, bpp;
1058 DWORD compression, sizeImage;
1059 void *mapBits = NULL;
1061 if(!bmi){
1062 if(bits) *bits = NULL;
1063 return NULL;
1066 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1067 &planes, &bpp, &compression, &sizeImage )) == -1))
1068 return 0;
1070 switch (bpp)
1072 case 16:
1073 case 32:
1074 if (compression == BI_BITFIELDS) break;
1075 /* fall through */
1076 case 1:
1077 case 4:
1078 case 8:
1079 case 24:
1080 if (compression == BI_RGB) break;
1081 /* fall through */
1082 default:
1083 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1084 return 0;
1087 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1089 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1090 width, height, planes, bpp, compression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1091 sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1093 dib->dsBm.bmType = 0;
1094 dib->dsBm.bmWidth = width;
1095 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1096 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1097 dib->dsBm.bmPlanes = planes;
1098 dib->dsBm.bmBitsPixel = bpp;
1099 dib->dsBm.bmBits = NULL;
1101 if (!bitmap_type) /* core header */
1103 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1104 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1105 dib->dsBmih.biWidth = width;
1106 dib->dsBmih.biHeight = height;
1107 dib->dsBmih.biPlanes = planes;
1108 dib->dsBmih.biBitCount = bpp;
1109 dib->dsBmih.biCompression = compression;
1110 dib->dsBmih.biXPelsPerMeter = 0;
1111 dib->dsBmih.biYPelsPerMeter = 0;
1112 dib->dsBmih.biClrUsed = 0;
1113 dib->dsBmih.biClrImportant = 0;
1115 else
1117 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1118 dib->dsBmih = bmi->bmiHeader;
1119 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1122 /* set number of entries in bmi.bmiColors table */
1123 if( bpp <= 8 )
1124 dib->dsBmih.biClrUsed = 1 << bpp;
1126 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1128 /* set dsBitfields values */
1129 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1131 if((bpp == 15 || bpp == 16) && compression == BI_RGB)
1133 /* In this case Windows changes biCompression to BI_BITFIELDS,
1134 however for now we won't do this, as there are a lot
1135 of places where BI_BITFIELDS is currently unsupported. */
1137 /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
1138 dib->dsBitfields[0] = 0x7c00;
1139 dib->dsBitfields[1] = 0x03e0;
1140 dib->dsBitfields[2] = 0x001f;
1142 else if(compression == BI_BITFIELDS)
1144 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1145 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1146 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1149 /* get storage location for DIB bits */
1151 if (section)
1153 SYSTEM_INFO SystemInfo;
1154 DWORD mapOffset;
1155 INT mapSize;
1157 GetSystemInfo( &SystemInfo );
1158 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1159 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1160 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1161 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1163 else
1165 offset = 0;
1166 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1167 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1169 dib->dshSection = section;
1170 dib->dsOffset = offset;
1172 if (!dib->dsBm.bmBits)
1174 HeapFree( GetProcessHeap(), 0, dib );
1175 return 0;
1178 /* If the reference hdc is null, take the desktop dc */
1179 if (hdc == 0)
1181 hdc = CreateCompatibleDC(0);
1182 bDesktopDC = TRUE;
1185 if (!(dc = get_dc_ptr( hdc ))) goto error;
1187 /* create Device Dependent Bitmap and add DIB pointer */
1188 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1189 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1191 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1193 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1194 bmp->dib = dib;
1195 bmp->funcs = physdev->funcs;
1196 /* create local copy of DIB palette */
1197 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1198 GDI_ReleaseObj( ret );
1200 if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1202 DeleteObject( ret );
1203 ret = 0;
1207 release_dc_ptr( dc );
1208 if (bDesktopDC) DeleteDC( hdc );
1209 if (ret && bits) *bits = dib->dsBm.bmBits;
1210 return ret;
1212 error:
1213 if (bDesktopDC) DeleteDC( hdc );
1214 if (section) UnmapViewOfFile( mapBits );
1215 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1216 HeapFree( GetProcessHeap(), 0, dib );
1217 return 0;