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:
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
60 Search for "Bitmap Structures" in MSDN
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
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 )
91 case 1: words = (width + 31) / 32; break;
92 case 4: words = (width + 7) / 8; break;
93 case 8: words = (width + 3) / 4; break;
95 case 16: words = (width + 1) / 2; break;
96 case 24: words = (width * 3 + 3)/4; break;
99 WARN("(%d): Unsupported depth\n", depth );
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 /***********************************************************************
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 /***********************************************************************
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;
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;
177 ERR("(%d): unknown/wrong size for header\n", header->biSize );
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 );
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)
198 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
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)
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)
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 );
247 DeleteObject( hBitmap );
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 )
261 if (!bits || !info) return 0;
263 if ((dc = get_dc_ptr( hdc )))
265 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
267 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
268 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
269 release_dc_ptr( dc );
275 /******************************************************************************
276 * SetDIBits [GDI32.@]
278 * Sets pixels in a bitmap using colors from DIB.
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
290 * Success: Number of scan lines copied
293 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
294 UINT lines, LPCVOID bits, const BITMAPINFO *info,
297 DC *dc = get_dc_ptr( hdc );
298 BOOL delete_hdc = FALSE;
303 if (coloruse == DIB_RGB_COLORS && !dc)
305 hdc = CreateCompatibleDC(0);
306 dc = get_dc_ptr( hdc );
314 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
316 release_dc_ptr( dc );
317 if (delete_hdc) DeleteDC(hdc);
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);
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,
345 if ((dc = get_dc_ptr( hdc )))
347 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
349 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
350 ySrc, startscan, lines, bits, info, coloruse );
351 release_dc_ptr( dc );
356 /***********************************************************************
357 * SetDIBColorTable (GDI32.@)
359 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
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));
381 GDI_ReleaseObj( dc->hBitmap );
382 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
384 release_dc_ptr( dc );
389 /***********************************************************************
390 * GetDIBColorTable (GDI32.@)
392 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
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));
412 GDI_ReleaseObj( dc->hBitmap );
414 release_dc_ptr( dc );
418 /* FIXME the following two structs should be combined with __sysPalTemplate in
419 objects/color.c - this should happen after de-X11-ing both of these
421 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
424 static const RGBQUAD EGAColorsQuads[16] = {
425 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
426 { 0x00, 0x00, 0x00, 0x00 },
427 { 0x00, 0x00, 0x80, 0x00 },
428 { 0x00, 0x80, 0x00, 0x00 },
429 { 0x00, 0x80, 0x80, 0x00 },
430 { 0x80, 0x00, 0x00, 0x00 },
431 { 0x80, 0x00, 0x80, 0x00 },
432 { 0x80, 0x80, 0x00, 0x00 },
433 { 0x80, 0x80, 0x80, 0x00 },
434 { 0xc0, 0xc0, 0xc0, 0x00 },
435 { 0x00, 0x00, 0xff, 0x00 },
436 { 0x00, 0xff, 0x00, 0x00 },
437 { 0x00, 0xff, 0xff, 0x00 },
438 { 0xff, 0x00, 0x00, 0x00 },
439 { 0xff, 0x00, 0xff, 0x00 },
440 { 0xff, 0xff, 0x00, 0x00 },
441 { 0xff, 0xff, 0xff, 0x00 }
444 static const RGBTRIPLE EGAColorsTriples[16] = {
445 /* rgbBlue, rgbGreen, rgbRed */
446 { 0x00, 0x00, 0x00 },
447 { 0x00, 0x00, 0x80 },
448 { 0x00, 0x80, 0x00 },
449 { 0x00, 0x80, 0x80 },
450 { 0x80, 0x00, 0x00 },
451 { 0x80, 0x00, 0x80 },
452 { 0x80, 0x80, 0x00 },
453 { 0x80, 0x80, 0x80 },
454 { 0xc0, 0xc0, 0xc0 },
455 { 0x00, 0x00, 0xff },
456 { 0x00, 0xff, 0x00 },
457 { 0x00, 0xff, 0xff },
458 { 0xff, 0x00, 0x00 } ,
459 { 0xff, 0x00, 0xff },
460 { 0xff, 0xff, 0x00 },
464 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
465 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
466 { 0x00, 0x00, 0x00, 0x00 },
467 { 0x00, 0x00, 0x80, 0x00 },
468 { 0x00, 0x80, 0x00, 0x00 },
469 { 0x00, 0x80, 0x80, 0x00 },
470 { 0x80, 0x00, 0x00, 0x00 },
471 { 0x80, 0x00, 0x80, 0x00 },
472 { 0x80, 0x80, 0x00, 0x00 },
473 { 0xc0, 0xc0, 0xc0, 0x00 },
474 { 0xc0, 0xdc, 0xc0, 0x00 },
475 { 0xf0, 0xca, 0xa6, 0x00 },
476 { 0xf0, 0xfb, 0xff, 0x00 },
477 { 0xa4, 0xa0, 0xa0, 0x00 },
478 { 0x80, 0x80, 0x80, 0x00 },
479 { 0x00, 0x00, 0xf0, 0x00 },
480 { 0x00, 0xff, 0x00, 0x00 },
481 { 0x00, 0xff, 0xff, 0x00 },
482 { 0xff, 0x00, 0x00, 0x00 },
483 { 0xff, 0x00, 0xff, 0x00 },
484 { 0xff, 0xff, 0x00, 0x00 },
485 { 0xff, 0xff, 0xff, 0x00 }
488 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
489 /* rgbBlue, rgbGreen, rgbRed */
490 { 0x00, 0x00, 0x00 },
491 { 0x00, 0x00, 0x80 },
492 { 0x00, 0x80, 0x00 },
493 { 0x00, 0x80, 0x80 },
494 { 0x80, 0x00, 0x00 },
495 { 0x80, 0x00, 0x80 },
496 { 0x80, 0x80, 0x00 },
497 { 0xc0, 0xc0, 0xc0 },
498 { 0xc0, 0xdc, 0xc0 },
499 { 0xf0, 0xca, 0xa6 },
500 { 0xf0, 0xfb, 0xff },
501 { 0xa4, 0xa0, 0xa0 },
502 { 0x80, 0x80, 0x80 },
503 { 0x00, 0x00, 0xf0 },
504 { 0x00, 0xff, 0x00 },
505 { 0x00, 0xff, 0xff },
506 { 0xff, 0x00, 0x00 },
507 { 0xff, 0x00, 0xff },
508 { 0xff, 0xff, 0x00 },
513 /******************************************************************************
514 * GetDIBits [GDI32.@]
516 * Retrieves bits of bitmap and copies to buffer.
519 * Success: Number of scan lines copied from bitmap
522 INT WINAPI GetDIBits(
523 HDC hdc, /* [in] Handle to device context */
524 HBITMAP hbitmap, /* [in] Handle to bitmap */
525 UINT startscan, /* [in] First scan line to set in dest bitmap */
526 UINT lines, /* [in] Number of scan lines to copy */
527 LPVOID bits, /* [out] Address of array for bitmap bits */
528 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
529 UINT coloruse) /* [in] RGB or palette index */
541 RGBTRIPLE* rgbTriples;
546 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
547 if (bitmap_type == -1)
549 ERR("Invalid bitmap format\n");
552 core_header = (bitmap_type == 0);
553 if (!(dc = get_dc_ptr( hdc )))
555 SetLastError( ERROR_INVALID_PARAMETER );
559 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
561 release_dc_ptr( dc );
565 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
566 rgbTriples = colorPtr;
569 /* Transfer color info */
573 case 0: /* query bitmap info only */
576 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
577 coreheader->bcWidth = bmp->bitmap.bmWidth;
578 coreheader->bcHeight = bmp->bitmap.bmHeight;
579 coreheader->bcPlanes = 1;
580 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
584 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
585 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
586 info->bmiHeader.biPlanes = 1;
587 info->bmiHeader.biSizeImage =
588 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
589 bmp->bitmap.bmHeight,
590 bmp->bitmap.bmBitsPixel );
593 info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
594 switch (bmp->dib->dsBm.bmBitsPixel)
598 info->bmiHeader.biCompression = BI_BITFIELDS;
601 info->bmiHeader.biCompression = BI_RGB;
607 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
608 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
610 info->bmiHeader.biXPelsPerMeter = 0;
611 info->bmiHeader.biYPelsPerMeter = 0;
612 info->bmiHeader.biClrUsed = 0;
613 info->bmiHeader.biClrImportant = 0;
615 /* Windows 2000 doesn't touch the additional struct members if
616 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
618 lines = abs(bmp->bitmap.bmHeight);
624 if (!core_header) info->bmiHeader.biClrUsed = 0;
626 /* If the bitmap object already has a dib section at the
627 same color depth then get the color map from it */
628 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
629 if(coloruse == DIB_RGB_COLORS) {
630 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
634 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
635 RGBTRIPLE* index = rgbTriples;
637 for (i=0; i < colors; i++, index++)
639 index->rgbtRed = bmp->color_table[i].rgbRed;
640 index->rgbtGreen = bmp->color_table[i].rgbGreen;
641 index->rgbtBlue = bmp->color_table[i].rgbBlue;
646 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
647 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
651 WORD *index = colorPtr;
652 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
657 if (coloruse == DIB_PAL_COLORS) {
658 for (i = 0; i < (1 << bpp); i++)
659 ((WORD *)colorPtr)[i] = (WORD)i;
661 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
662 /* For color DDBs in native depth (mono DDBs always have
663 a black/white palette):
664 Generate the color map from the selected palette */
665 PALETTEENTRY palEntry[256];
667 memset( palEntry, 0, sizeof(palEntry) );
668 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
670 release_dc_ptr( dc );
671 GDI_ReleaseObj( hbitmap );
674 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
677 rgbTriples[i].rgbtRed = palEntry[i].peRed;
678 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
679 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
683 rgbQuads[i].rgbRed = palEntry[i].peRed;
684 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
685 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
686 rgbQuads[i].rgbReserved = 0;
694 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
695 rgbTriples[0].rgbtBlue = 0;
696 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
697 rgbTriples[1].rgbtBlue = 0xff;
701 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
702 rgbQuads[0].rgbBlue = 0;
703 rgbQuads[0].rgbReserved = 0;
704 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
705 rgbQuads[1].rgbBlue = 0xff;
706 rgbQuads[1].rgbReserved = 0;
712 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
714 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
725 memcpy(rgbTriples, DefLogPaletteTriples,
726 10 * sizeof(RGBTRIPLE));
727 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
728 10 * sizeof(RGBTRIPLE));
729 color = rgbTriples + 10;
730 for(r = 0; r <= 5; r++) /* FIXME */
731 for(g = 0; g <= 5; g++)
732 for(b = 0; b <= 5; b++) {
733 color->rgbtRed = (r * 0xff) / 5;
734 color->rgbtGreen = (g * 0xff) / 5;
735 color->rgbtBlue = (b * 0xff) / 5;
744 memcpy(rgbQuads, DefLogPaletteQuads,
745 10 * sizeof(RGBQUAD));
746 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
747 10 * sizeof(RGBQUAD));
748 color = rgbQuads + 10;
749 for(r = 0; r <= 5; r++) /* FIXME */
750 for(g = 0; g <= 5; g++)
751 for(b = 0; b <= 5; b++) {
752 color->rgbRed = (r * 0xff) / 5;
753 color->rgbGreen = (g * 0xff) / 5;
754 color->rgbBlue = (b * 0xff) / 5;
755 color->rgbReserved = 0;
766 if (info->bmiHeader.biCompression == BI_BITFIELDS)
768 ((PDWORD)info->bmiColors)[0] = 0x7c00;
769 ((PDWORD)info->bmiColors)[1] = 0x03e0;
770 ((PDWORD)info->bmiColors)[2] = 0x001f;
775 if (info->bmiHeader.biCompression == BI_BITFIELDS)
777 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
780 ((PDWORD)info->bmiColors)[0] = 0xf800;
781 ((PDWORD)info->bmiColors)[1] = 0x07e0;
782 ((PDWORD)info->bmiColors)[2] = 0x001f;
789 if (info->bmiHeader.biCompression == BI_BITFIELDS)
791 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
794 ((PDWORD)info->bmiColors)[0] = 0xff0000;
795 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
796 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
804 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
805 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
807 /*FIXME: Only RGB dibs supported for now */
808 unsigned int srcwidth = bmp->dib->dsBm.bmWidth;
809 int srcwidthb = bmp->dib->dsBm.bmWidthBytes;
810 unsigned int dstwidth = width;
811 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
812 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
813 unsigned int x, y, width, widthb;
816 * If copying from a top-down source bitmap, move the source
817 * pointer to the end of the source bitmap and negate the width
818 * so that we copy the bits upside-down.
820 if (bmp->dib->dsBmih.biHeight < 0)
822 sbits += (srcwidthb * (int)(abs(bmp->dib->dsBmih.biHeight) - 2 * startscan - 1));
823 srcwidthb = -srcwidthb;
825 /*Same for the destination.*/
828 dbits = (LPBYTE)bits + (dstwidthb * (lines - 1));
829 dstwidthb = -dstwidthb;
834 case 16: /* 16 bpp dstDIB */
836 LPWORD dstbits = (LPWORD)dbits;
837 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
839 /* FIXME: BI_BITFIELDS not supported yet */
841 switch(bmp->dib->dsBm.bmBitsPixel) {
843 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
845 widthb = min(abs(srcwidthb), abs(dstwidthb));
846 /* FIXME: BI_BITFIELDS not supported yet */
847 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
848 memcpy(dbits, sbits, widthb);
852 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
854 LPBYTE srcbits = sbits;
856 width = min(srcwidth, dstwidth);
857 for( y = 0; y < lines; y++) {
858 for( x = 0; x < width; x++, srcbits += 3)
859 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
860 (((WORD)srcbits[1] << 2) & gmask) |
861 (((WORD)srcbits[2] << 7) & rmask);
863 dstbits = (LPWORD)(dbits+=dstwidthb);
864 srcbits = (sbits += srcwidthb);
869 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
871 LPDWORD srcbits = (LPDWORD)sbits;
874 width = min(srcwidth, dstwidth);
875 for( y = 0; y < lines; y++) {
876 for( x = 0; x < width; x++ ) {
878 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
879 ((val >> 9) & rmask));
881 dstbits = (LPWORD)(dbits+=dstwidthb);
882 srcbits = (LPDWORD)(sbits+=srcwidthb);
887 default: /* ? bit bmp -> 16 bit DIB */
888 FIXME("15/16 bit DIB %d bit bitmap\n",
889 bmp->bitmap.bmBitsPixel);
895 case 24: /* 24 bpp dstDIB */
897 LPBYTE dstbits = dbits;
899 switch(bmp->dib->dsBm.bmBitsPixel) {
901 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
903 LPWORD srcbits = (LPWORD)sbits;
906 width = min(srcwidth, dstwidth);
907 /* FIXME: BI_BITFIELDS not supported yet */
908 for( y = 0; y < lines; y++) {
909 for( x = 0; x < width; x++ ) {
911 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
912 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
913 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
915 dstbits = dbits+=dstwidthb;
916 srcbits = (LPWORD)(sbits+=srcwidthb);
921 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
923 widthb = min(abs(srcwidthb), abs(dstwidthb));
924 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
925 memcpy(dbits, sbits, widthb);
929 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
931 LPBYTE srcbits = sbits;
933 width = min(srcwidth, dstwidth);
934 for( y = 0; y < lines; y++) {
935 for( x = 0; x < width; x++, srcbits++ ) {
936 *dstbits++ = *srcbits++;
937 *dstbits++ = *srcbits++;
938 *dstbits++ = *srcbits++;
940 dstbits = dbits+=dstwidthb;
941 srcbits = sbits+=srcwidthb;
946 default: /* ? bit bmp -> 24 bit DIB */
947 FIXME("24 bit DIB %d bit bitmap\n",
948 bmp->bitmap.bmBitsPixel);
954 case 32: /* 32 bpp dstDIB */
956 LPDWORD dstbits = (LPDWORD)dbits;
958 /* FIXME: BI_BITFIELDS not supported yet */
960 switch(bmp->dib->dsBm.bmBitsPixel) {
961 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
963 LPWORD srcbits = (LPWORD)sbits;
966 width = min(srcwidth, dstwidth);
967 /* FIXME: BI_BITFIELDS not supported yet */
968 for( y = 0; y < lines; y++) {
969 for( x = 0; x < width; x++ ) {
970 val = (DWORD)*srcbits++;
971 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
972 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
973 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
975 dstbits=(LPDWORD)(dbits+=dstwidthb);
976 srcbits=(LPWORD)(sbits+=srcwidthb);
981 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
983 LPBYTE srcbits = sbits;
985 width = min(srcwidth, dstwidth);
986 for( y = 0; y < lines; y++) {
987 for( x = 0; x < width; x++, srcbits+=3 )
988 *dstbits++ = srcbits[0] |
991 dstbits=(LPDWORD)(dbits+=dstwidthb);
992 srcbits=(sbits+=srcwidthb);
997 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
999 widthb = min(abs(srcwidthb), abs(dstwidthb));
1000 /* FIXME: BI_BITFIELDS not supported yet */
1001 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1002 memcpy(dbits, sbits, widthb);
1007 default: /* ? bit bmp -> 32 bit DIB */
1008 FIXME("32 bit DIB %d bit bitmap\n",
1009 bmp->bitmap.bmBitsPixel);
1015 default: /* ? bit DIB */
1016 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1020 /* Otherwise, get bits from the XImage */
1023 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDIBits );
1024 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
1025 else lines = physdev->funcs->pGetDIBits( physdev, hbitmap, startscan,
1026 lines, bits, info, coloruse );
1029 else lines = abs(height);
1031 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1032 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1036 /* FIXME: biSizeImage should be calculated according to the selected
1037 compression algorithm if biCompression != BI_RGB */
1038 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1039 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1041 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1044 release_dc_ptr( dc );
1045 GDI_ReleaseObj( hbitmap );
1050 /***********************************************************************
1051 * CreateDIBitmap (GDI32.@)
1053 * Creates a DDB (device dependent bitmap) from a DIB.
1054 * The DDB will have the same color depth as the reference DC.
1056 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1057 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1066 if (!header) return 0;
1068 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1072 TRACE("Bitmap has a negative width\n");
1076 /* Top-down DIBs have a negative height */
1077 if (height < 0) height = -height;
1079 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1080 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1083 handle = CreateBitmap( width, height, 1, 1, NULL );
1085 handle = CreateCompatibleBitmap( hdc, width, height );
1089 if (init & CBM_INIT)
1091 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1093 DeleteObject( handle );
1102 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1103 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1105 RGBQUAD *colorTable;
1106 unsigned int colors, i;
1107 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1111 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1115 colors = info->bmiHeader.biClrUsed;
1116 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1120 ERR("called with >256 colors!\n");
1124 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1126 if(coloruse == DIB_RGB_COLORS)
1130 /* Convert RGBTRIPLEs to RGBQUADs */
1131 for (i=0; i < colors; i++)
1133 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1134 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1135 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1136 colorTable[i].rgbReserved = 0;
1141 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1146 PALETTEENTRY entries[256];
1147 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1148 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1150 for (i = 0; i < colors; i++, index++)
1152 PALETTEENTRY *entry = &entries[*index % count];
1153 colorTable[i].rgbRed = entry->peRed;
1154 colorTable[i].rgbGreen = entry->peGreen;
1155 colorTable[i].rgbBlue = entry->peBlue;
1156 colorTable[i].rgbReserved = 0;
1159 bmp->color_table = colorTable;
1160 bmp->nb_colors = colors;
1163 /***********************************************************************
1164 * CreateDIBSection (GDI32.@)
1166 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1167 VOID **bits, HANDLE section, DWORD offset)
1171 BOOL bDesktopDC = FALSE;
1177 DWORD compression, sizeImage;
1178 void *mapBits = NULL;
1181 if(bits) *bits = NULL;
1185 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1186 &planes, &bpp, &compression, &sizeImage )) == -1))
1193 if (compression == BI_BITFIELDS) break;
1199 if (compression == BI_RGB) break;
1202 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1206 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1208 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1209 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1211 dib->dsBm.bmType = 0;
1212 dib->dsBm.bmWidth = width;
1213 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1214 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1215 dib->dsBm.bmPlanes = planes;
1216 dib->dsBm.bmBitsPixel = bpp;
1217 dib->dsBm.bmBits = NULL;
1219 if (!bitmap_type) /* core header */
1221 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1222 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1223 dib->dsBmih.biWidth = width;
1224 dib->dsBmih.biHeight = height;
1225 dib->dsBmih.biPlanes = planes;
1226 dib->dsBmih.biBitCount = bpp;
1227 dib->dsBmih.biCompression = compression;
1228 dib->dsBmih.biXPelsPerMeter = 0;
1229 dib->dsBmih.biYPelsPerMeter = 0;
1230 dib->dsBmih.biClrUsed = 0;
1231 dib->dsBmih.biClrImportant = 0;
1235 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1236 dib->dsBmih = bmi->bmiHeader;
1237 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1240 /* set number of entries in bmi.bmiColors table */
1242 dib->dsBmih.biClrUsed = 1 << bpp;
1244 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1246 /* set dsBitfields values */
1247 if (usage == DIB_PAL_COLORS || bpp <= 8)
1249 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1255 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1256 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1257 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1261 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1262 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1263 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1267 /* get storage location for DIB bits */
1271 SYSTEM_INFO SystemInfo;
1275 GetSystemInfo( &SystemInfo );
1276 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1277 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1278 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1279 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1284 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1285 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1287 dib->dshSection = section;
1288 dib->dsOffset = offset;
1290 if (!dib->dsBm.bmBits)
1292 HeapFree( GetProcessHeap(), 0, dib );
1296 /* If the reference hdc is null, take the desktop dc */
1299 hdc = CreateCompatibleDC(0);
1303 if (!(dc = get_dc_ptr( hdc ))) goto error;
1305 /* create Device Dependent Bitmap and add DIB pointer */
1306 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1307 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1309 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1311 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1313 bmp->funcs = physdev->funcs;
1314 /* create local copy of DIB palette */
1315 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1316 GDI_ReleaseObj( ret );
1318 if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1320 DeleteObject( ret );
1325 release_dc_ptr( dc );
1326 if (bDesktopDC) DeleteDC( hdc );
1327 if (ret && bits) *bits = dib->dsBm.bmBits;
1331 if (bDesktopDC) DeleteDC( hdc );
1332 if (section) UnmapViewOfFile( mapBits );
1333 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1334 HeapFree( GetProcessHeap(), 0, dib );