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
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
77 Some of the following helper functions are duplicated in
81 /***********************************************************************
82 * DIB_GetDIBWidthBytes
84 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
86 int DIB_GetDIBWidthBytes( int width, int depth )
92 case 1: words = (width + 31) / 32; break;
93 case 4: words = (width + 7) / 8; break;
94 case 8: words = (width + 3) / 4; break;
96 case 16: words = (width + 1) / 2; break;
97 case 24: words = (width * 3 + 3)/4; break;
100 WARN("(%d): Unsupported depth\n", depth );
108 /***********************************************************************
109 * DIB_GetDIBImageBytes
111 * Return the number of bytes used to hold the image in a DIB bitmap.
113 int DIB_GetDIBImageBytes( int width, int height, int depth )
115 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
119 /***********************************************************************
122 * Return the size of the bitmap info structure including color table.
124 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
128 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
130 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
131 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
132 return sizeof(BITMAPCOREHEADER) + colors *
133 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
135 else /* assume BITMAPINFOHEADER */
137 colors = info->bmiHeader.biClrUsed;
138 if (colors > 256) colors = 256;
139 if (!colors && (info->bmiHeader.biBitCount <= 8))
140 colors = 1 << info->bmiHeader.biBitCount;
141 return sizeof(BITMAPINFOHEADER) + colors *
142 ((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 static 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 );
182 /***********************************************************************
183 * StretchDIBits (GDI32.@)
185 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
186 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
187 INT heightSrc, const void *bits,
188 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
196 if (!(dc = get_dc_ptr( hdc ))) return 0;
198 if(dc->funcs->pStretchDIBits)
201 ret = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
202 heightDst, xSrc, ySrc, widthSrc,
203 heightSrc, bits, info, wUsage, dwRop);
204 release_dc_ptr( dc );
206 else /* use StretchBlt */
213 BOOL fastpath = FALSE;
215 release_dc_ptr( dc );
217 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
219 ERR("Invalid bitmap\n");
225 ERR("Bitmap has a negative width\n");
229 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
231 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
232 widthDst == widthSrc && heightDst == heightSrc &&
233 info->bmiHeader.biCompression == BI_RGB &&
237 if ((bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC )))
239 if (bmp->bitmap.bmBitsPixel == bpp &&
240 bmp->bitmap.bmWidth == widthSrc &&
241 bmp->bitmap.bmHeight == heightSrc &&
242 bmp->bitmap.bmPlanes == planes)
244 GDI_ReleaseObj( hBitmap );
251 TRACE("using fast path\n");
252 ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
256 /* slow path - need to use StretchBlt */
258 HPALETTE hpal = NULL;
261 hdcMem = CreateCompatibleDC( hdc );
262 hBitmap = CreateCompatibleBitmap(hdc, width, height);
263 hOldBitmap = SelectObject( hdcMem, hBitmap );
264 if(wUsage == DIB_PAL_COLORS)
266 hpal = GetCurrentObject(hdc, OBJ_PAL);
267 hpal = SelectPalette(hdcMem, hpal, FALSE);
270 if (info->bmiHeader.biCompression == BI_RLE4 ||
271 info->bmiHeader.biCompression == BI_RLE8) {
273 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
274 * contain all the rectangle described in bmiHeader, but only part of it.
275 * This mean that those undescribed pixels must be left untouched.
276 * So, we first copy on a memory bitmap the current content of the
277 * destination rectangle, blit the DIB bits on top of it - hence leaving
278 * the gaps untouched -, and blitting the rectangle back.
279 * This insure that gaps are untouched on the destination rectangle
280 * Not doing so leads to trashed images (the gaps contain what was on the
281 * memory bitmap => generally black or garbage)
282 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
283 * another speed vs correctness issue. Anyway, if speed is needed, then the
284 * pStretchDIBits function shall be implemented.
288 /* copy existing bitmap from destination dc */
289 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
290 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
294 ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
296 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
297 left (negative biHeight) */
298 if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
299 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
300 widthSrc, heightSrc, dwRop );
302 SelectPalette(hdcMem, hpal, FALSE);
303 SelectObject( hdcMem, hOldBitmap );
305 DeleteObject( hBitmap );
312 /******************************************************************************
313 * SetDIBits [GDI32.@]
315 * Sets pixels in a bitmap using colors from DIB.
318 * hdc [I] Handle to device context
319 * hbitmap [I] Handle to bitmap
320 * startscan [I] Starting scan line
321 * lines [I] Number of scan lines
322 * bits [I] Array of bitmap bits
323 * info [I] Address of structure with data
324 * coloruse [I] Type of color indexes to use
327 * Success: Number of scan lines copied
330 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
331 UINT lines, LPCVOID bits, const BITMAPINFO *info,
338 if (!(dc = get_dc_ptr( hdc )))
340 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
346 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
348 release_dc_ptr( dc );
352 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
357 if (bitmap->funcs != dc->funcs)
358 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
359 else if (dc->funcs->pSetDIBits)
360 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
361 bits, info, coloruse );
365 GDI_ReleaseObj( hbitmap );
366 release_dc_ptr( dc );
371 /***********************************************************************
372 * SetDIBitsToDevice (GDI32.@)
374 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
375 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
376 UINT lines, LPCVOID bits, const BITMAPINFO *info,
384 if (!(dc = get_dc_ptr( hdc ))) return 0;
386 if(dc->funcs->pSetDIBitsToDevice)
389 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
390 ySrc, startscan, lines, bits,
394 FIXME("unimplemented on hdc %p\n", hdc);
398 release_dc_ptr( dc );
402 /***********************************************************************
403 * SetDIBColorTable (GDI32.@)
405 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
411 if (!(dc = get_dc_ptr( hdc ))) return 0;
413 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
415 /* Check if currently selected bitmap is a DIB */
416 if (bitmap->color_table)
418 if (startpos < bitmap->nb_colors)
420 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
421 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
425 GDI_ReleaseObj( dc->hBitmap );
428 if (dc->funcs->pSetDIBColorTable)
429 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
431 release_dc_ptr( dc );
436 /***********************************************************************
437 * GetDIBColorTable (GDI32.@)
439 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
444 if (!(dc = get_dc_ptr( hdc ))) return 0;
446 if (dc->funcs->pGetDIBColorTable)
447 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
450 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
453 /* Check if currently selected bitmap is a DIB */
454 if (bitmap->color_table)
456 if (startpos < bitmap->nb_colors)
458 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
459 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
463 GDI_ReleaseObj( dc->hBitmap );
466 release_dc_ptr( dc );
470 /* FIXME the following two structs should be combined with __sysPalTemplate in
471 objects/color.c - this should happen after de-X11-ing both of these
473 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
476 static const RGBQUAD EGAColorsQuads[16] = {
477 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
478 { 0x00, 0x00, 0x00, 0x00 },
479 { 0x00, 0x00, 0x80, 0x00 },
480 { 0x00, 0x80, 0x00, 0x00 },
481 { 0x00, 0x80, 0x80, 0x00 },
482 { 0x80, 0x00, 0x00, 0x00 },
483 { 0x80, 0x00, 0x80, 0x00 },
484 { 0x80, 0x80, 0x00, 0x00 },
485 { 0x80, 0x80, 0x80, 0x00 },
486 { 0xc0, 0xc0, 0xc0, 0x00 },
487 { 0x00, 0x00, 0xff, 0x00 },
488 { 0x00, 0xff, 0x00, 0x00 },
489 { 0x00, 0xff, 0xff, 0x00 },
490 { 0xff, 0x00, 0x00, 0x00 },
491 { 0xff, 0x00, 0xff, 0x00 },
492 { 0xff, 0xff, 0x00, 0x00 },
493 { 0xff, 0xff, 0xff, 0x00 }
496 static const RGBTRIPLE EGAColorsTriples[16] = {
497 /* rgbBlue, rgbGreen, rgbRed */
498 { 0x00, 0x00, 0x00 },
499 { 0x00, 0x00, 0x80 },
500 { 0x00, 0x80, 0x00 },
501 { 0x00, 0x80, 0x80 },
502 { 0x80, 0x00, 0x00 },
503 { 0x80, 0x00, 0x80 },
504 { 0x80, 0x80, 0x00 },
505 { 0x80, 0x80, 0x80 },
506 { 0xc0, 0xc0, 0xc0 },
507 { 0x00, 0x00, 0xff },
508 { 0x00, 0xff, 0x00 },
509 { 0x00, 0xff, 0xff },
510 { 0xff, 0x00, 0x00 } ,
511 { 0xff, 0x00, 0xff },
512 { 0xff, 0xff, 0x00 },
516 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
517 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
518 { 0x00, 0x00, 0x00, 0x00 },
519 { 0x00, 0x00, 0x80, 0x00 },
520 { 0x00, 0x80, 0x00, 0x00 },
521 { 0x00, 0x80, 0x80, 0x00 },
522 { 0x80, 0x00, 0x00, 0x00 },
523 { 0x80, 0x00, 0x80, 0x00 },
524 { 0x80, 0x80, 0x00, 0x00 },
525 { 0xc0, 0xc0, 0xc0, 0x00 },
526 { 0xc0, 0xdc, 0xc0, 0x00 },
527 { 0xf0, 0xca, 0xa6, 0x00 },
528 { 0xf0, 0xfb, 0xff, 0x00 },
529 { 0xa4, 0xa0, 0xa0, 0x00 },
530 { 0x80, 0x80, 0x80, 0x00 },
531 { 0x00, 0x00, 0xf0, 0x00 },
532 { 0x00, 0xff, 0x00, 0x00 },
533 { 0x00, 0xff, 0xff, 0x00 },
534 { 0xff, 0x00, 0x00, 0x00 },
535 { 0xff, 0x00, 0xff, 0x00 },
536 { 0xff, 0xff, 0x00, 0x00 },
537 { 0xff, 0xff, 0xff, 0x00 }
540 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
541 /* rgbBlue, rgbGreen, rgbRed */
542 { 0x00, 0x00, 0x00 },
543 { 0x00, 0x00, 0x80 },
544 { 0x00, 0x80, 0x00 },
545 { 0x00, 0x80, 0x80 },
546 { 0x80, 0x00, 0x00 },
547 { 0x80, 0x00, 0x80 },
548 { 0x80, 0x80, 0x00 },
549 { 0xc0, 0xc0, 0xc0 },
550 { 0xc0, 0xdc, 0xc0 },
551 { 0xf0, 0xca, 0xa6 },
552 { 0xf0, 0xfb, 0xff },
553 { 0xa4, 0xa0, 0xa0 },
554 { 0x80, 0x80, 0x80 },
555 { 0x00, 0x00, 0xf0 },
556 { 0x00, 0xff, 0x00 },
557 { 0x00, 0xff, 0xff },
558 { 0xff, 0x00, 0x00 },
559 { 0xff, 0x00, 0xff },
560 { 0xff, 0xff, 0x00 },
565 /******************************************************************************
566 * GetDIBits [GDI32.@]
568 * Retrieves bits of bitmap and copies to buffer.
571 * Success: Number of scan lines copied from bitmap
574 INT WINAPI GetDIBits(
575 HDC hdc, /* [in] Handle to device context */
576 HBITMAP hbitmap, /* [in] Handle to bitmap */
577 UINT startscan, /* [in] First scan line to set in dest bitmap */
578 UINT lines, /* [in] Number of scan lines to copy */
579 LPVOID bits, /* [out] Address of array for bitmap bits */
580 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
581 UINT coloruse) /* [in] RGB or palette index */
593 RGBTRIPLE* rgbTriples;
598 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
599 if (bitmap_type == -1)
601 ERR("Invalid bitmap format\n");
604 core_header = (bitmap_type == 0);
605 if (!(dc = get_dc_ptr( hdc )))
607 SetLastError( ERROR_INVALID_PARAMETER );
611 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
613 release_dc_ptr( dc );
617 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
618 rgbTriples = (RGBTRIPLE *) colorPtr;
619 rgbQuads = (RGBQUAD *) colorPtr;
621 /* Transfer color info */
625 case 0: /* query bitmap info only */
628 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
629 coreheader->bcWidth = bmp->bitmap.bmWidth;
630 coreheader->bcHeight = bmp->bitmap.bmHeight;
631 coreheader->bcPlanes = 1;
632 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
636 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
637 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
638 info->bmiHeader.biPlanes = 1;
639 info->bmiHeader.biSizeImage =
640 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
641 bmp->bitmap.bmHeight,
642 bmp->bitmap.bmBitsPixel );
643 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
644 switch(bmp->bitmap.bmBitsPixel)
647 info->bmiHeader.biBitCount = 16;
650 info->bmiHeader.biBitCount = 32;
653 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
656 info->bmiHeader.biXPelsPerMeter = 0;
657 info->bmiHeader.biYPelsPerMeter = 0;
658 info->bmiHeader.biClrUsed = 0;
659 info->bmiHeader.biClrImportant = 0;
661 /* Windows 2000 doesn't touch the additional struct members if
662 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
664 lines = abs(bmp->bitmap.bmHeight);
670 if (!core_header) info->bmiHeader.biClrUsed = 0;
672 /* If the bitmap object already has a dib section at the
673 same color depth then get the color map from it */
674 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
675 if(coloruse == DIB_RGB_COLORS) {
676 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
680 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
681 RGBTRIPLE* index = rgbTriples;
683 for (i=0; i < colors; i++, index++)
685 index->rgbtRed = bmp->color_table[i].rgbRed;
686 index->rgbtGreen = bmp->color_table[i].rgbGreen;
687 index->rgbtBlue = bmp->color_table[i].rgbBlue;
692 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
693 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
697 WORD *index = colorPtr;
698 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
703 if(bpp >= bmp->bitmap.bmBitsPixel) {
704 /* Generate the color map from the selected palette */
705 PALETTEENTRY palEntry[256];
707 memset( palEntry, 0, sizeof(palEntry) );
708 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
710 release_dc_ptr( dc );
711 GDI_ReleaseObj( hbitmap );
714 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
715 if (coloruse == DIB_RGB_COLORS) {
718 rgbTriples[i].rgbtRed = palEntry[i].peRed;
719 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
720 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
724 rgbQuads[i].rgbRed = palEntry[i].peRed;
725 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
726 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
727 rgbQuads[i].rgbReserved = 0;
730 else ((WORD *)colorPtr)[i] = (WORD)i;
737 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
738 rgbTriples[0].rgbtBlue = 0;
739 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
740 rgbTriples[1].rgbtBlue = 0xff;
744 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
745 rgbQuads[0].rgbBlue = 0;
746 rgbQuads[0].rgbReserved = 0;
747 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
748 rgbQuads[1].rgbBlue = 0xff;
749 rgbQuads[1].rgbReserved = 0;
755 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
757 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
768 memcpy(rgbTriples, DefLogPaletteTriples,
769 10 * sizeof(RGBTRIPLE));
770 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
771 10 * sizeof(RGBTRIPLE));
772 color = rgbTriples + 10;
773 for(r = 0; r <= 5; r++) /* FIXME */
774 for(g = 0; g <= 5; g++)
775 for(b = 0; b <= 5; b++) {
776 color->rgbtRed = (r * 0xff) / 5;
777 color->rgbtGreen = (g * 0xff) / 5;
778 color->rgbtBlue = (b * 0xff) / 5;
787 memcpy(rgbQuads, DefLogPaletteQuads,
788 10 * sizeof(RGBQUAD));
789 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
790 10 * sizeof(RGBQUAD));
791 color = rgbQuads + 10;
792 for(r = 0; r <= 5; r++) /* FIXME */
793 for(g = 0; g <= 5; g++)
794 for(b = 0; b <= 5; b++) {
795 color->rgbRed = (r * 0xff) / 5;
796 color->rgbGreen = (g * 0xff) / 5;
797 color->rgbBlue = (b * 0xff) / 5;
798 color->rgbReserved = 0;
809 if (info->bmiHeader.biCompression == BI_BITFIELDS)
811 ((PDWORD)info->bmiColors)[0] = 0x7c00;
812 ((PDWORD)info->bmiColors)[1] = 0x03e0;
813 ((PDWORD)info->bmiColors)[2] = 0x001f;
818 if (info->bmiHeader.biCompression == BI_BITFIELDS)
820 ((PDWORD)info->bmiColors)[0] = 0xf800;
821 ((PDWORD)info->bmiColors)[1] = 0x07e0;
822 ((PDWORD)info->bmiColors)[2] = 0x001f;
828 if (info->bmiHeader.biCompression == BI_BITFIELDS)
830 ((PDWORD)info->bmiColors)[0] = 0xff0000;
831 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
832 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
839 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
840 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
842 /*FIXME: Only RGB dibs supported for now */
843 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
844 unsigned int dstwidth = width;
845 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
846 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
847 unsigned int x, y, width, widthb;
849 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
851 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
852 dstwidthb = -dstwidthb;
858 case 16: /* 16 bpp dstDIB */
860 LPWORD dstbits = (LPWORD)dbits;
861 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
863 /* FIXME: BI_BITFIELDS not supported yet */
865 switch(bmp->dib->dsBm.bmBitsPixel) {
867 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
869 widthb = min(srcwidthb, abs(dstwidthb));
870 /* FIXME: BI_BITFIELDS not supported yet */
871 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
872 memcpy(dbits, sbits, widthb);
876 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
878 LPBYTE srcbits = sbits;
880 width = min(srcwidth, dstwidth);
881 for( y = 0; y < lines; y++) {
882 for( x = 0; x < width; x++, srcbits += 3)
883 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
884 (((WORD)srcbits[1] << 2) & gmask) |
885 (((WORD)srcbits[2] << 7) & rmask);
887 dstbits = (LPWORD)(dbits+=dstwidthb);
888 srcbits = (sbits += srcwidthb);
893 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
895 LPDWORD srcbits = (LPDWORD)sbits;
898 width = min(srcwidth, dstwidth);
899 for( y = 0; y < lines; y++) {
900 for( x = 0; x < width; x++ ) {
902 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
903 ((val >> 9) & rmask));
905 dstbits = (LPWORD)(dbits+=dstwidthb);
906 srcbits = (LPDWORD)(sbits+=srcwidthb);
911 default: /* ? bit bmp -> 16 bit DIB */
912 FIXME("15/16 bit DIB %d bit bitmap\n",
913 bmp->bitmap.bmBitsPixel);
919 case 24: /* 24 bpp dstDIB */
921 LPBYTE dstbits = dbits;
923 switch(bmp->dib->dsBm.bmBitsPixel) {
925 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
927 LPWORD srcbits = (LPWORD)sbits;
930 width = min(srcwidth, dstwidth);
931 /* FIXME: BI_BITFIELDS not supported yet */
932 for( y = 0; y < lines; y++) {
933 for( x = 0; x < width; x++ ) {
935 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
936 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
937 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
939 dstbits = dbits+=dstwidthb;
940 srcbits = (LPWORD)(sbits+=srcwidthb);
945 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
947 widthb = min(srcwidthb, abs(dstwidthb));
948 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
949 memcpy(dbits, sbits, widthb);
953 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
955 LPBYTE srcbits = sbits;
957 width = min(srcwidth, dstwidth);
958 for( y = 0; y < lines; y++) {
959 for( x = 0; x < width; x++, srcbits++ ) {
960 *dstbits++ = *srcbits++;
961 *dstbits++ = *srcbits++;
962 *dstbits++ = *srcbits++;
964 dstbits = dbits+=dstwidthb;
965 srcbits = sbits+=srcwidthb;
970 default: /* ? bit bmp -> 24 bit DIB */
971 FIXME("24 bit DIB %d bit bitmap\n",
972 bmp->bitmap.bmBitsPixel);
978 case 32: /* 32 bpp dstDIB */
980 LPDWORD dstbits = (LPDWORD)dbits;
982 /* FIXME: BI_BITFIELDS not supported yet */
984 switch(bmp->dib->dsBm.bmBitsPixel) {
985 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
987 LPWORD srcbits = (LPWORD)sbits;
990 width = min(srcwidth, dstwidth);
991 /* FIXME: BI_BITFIELDS not supported yet */
992 for( y = 0; y < lines; y++) {
993 for( x = 0; x < width; x++ ) {
994 val = (DWORD)*srcbits++;
995 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
996 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
997 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
999 dstbits=(LPDWORD)(dbits+=dstwidthb);
1000 srcbits=(LPWORD)(sbits+=srcwidthb);
1005 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1007 LPBYTE srcbits = sbits;
1009 width = min(srcwidth, dstwidth);
1010 for( y = 0; y < lines; y++) {
1011 for( x = 0; x < width; x++, srcbits+=3 )
1012 *dstbits++ = srcbits[0] |
1015 dstbits=(LPDWORD)(dbits+=dstwidthb);
1016 srcbits=(sbits+=srcwidthb);
1021 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1023 widthb = min(srcwidthb, abs(dstwidthb));
1024 /* FIXME: BI_BITFIELDS not supported yet */
1025 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1026 memcpy(dbits, sbits, widthb);
1031 default: /* ? bit bmp -> 32 bit DIB */
1032 FIXME("32 bit DIB %d bit bitmap\n",
1033 bmp->bitmap.bmBitsPixel);
1039 default: /* ? bit DIB */
1040 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1044 /* Otherwise, get bits from the XImage */
1047 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1050 if (bmp->funcs && bmp->funcs->pGetDIBits)
1051 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1052 lines, bits, info, coloruse );
1054 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1058 else lines = abs(height);
1060 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1061 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1065 /* FIXME: biSizeImage should be calculated according to the selected
1066 compression algorithm if biCompression != BI_RGB */
1067 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1068 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1070 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1073 release_dc_ptr( dc );
1074 GDI_ReleaseObj( hbitmap );
1079 /***********************************************************************
1080 * CreateDIBitmap (GDI32.@)
1082 * Creates a DDB (device dependent bitmap) from a DIB.
1083 * The DDB will have the same color depth as the reference DC.
1085 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1086 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1096 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1100 TRACE("Bitmap has a negative width\n");
1104 /* Top-down DIBs have a negative height */
1105 if (height < 0) height = -height;
1107 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1108 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1111 handle = CreateBitmap( width, height, 1, 1, NULL );
1113 handle = CreateCompatibleBitmap( hdc, width, height );
1117 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1119 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1121 if (!BITMAP_SetOwnerDC( handle, dc ))
1123 DeleteObject( handle );
1126 release_dc_ptr( dc );
1133 /***********************************************************************
1134 * CreateDIBSection (GDI.489)
1136 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1137 SEGPTR *bits16, HANDLE section, DWORD offset)
1142 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1145 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1146 if (bmp && bmp->dib && bits32)
1148 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1156 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1158 height = height >= 0 ? height : -height;
1159 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1161 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1163 /* calculate number of sel's needed for size with 64K steps */
1164 count = (size + 0xffff) / 0x10000;
1165 sel = AllocSelectorArray16(count);
1167 for (i = 0; i < count; i++)
1169 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1170 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1173 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1174 if (bits16) *bits16 = bmp->segptr_bits;
1176 if (bmp) GDI_ReleaseObj( hbitmap );
1178 return HBITMAP_16(hbitmap);
1181 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1182 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1184 RGBQUAD *colorTable;
1185 unsigned int colors;
1187 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1191 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1195 colors = info->bmiHeader.biClrUsed;
1196 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1200 ERR("called with >256 colors!\n");
1204 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1206 if(coloruse == DIB_RGB_COLORS)
1210 /* Convert RGBTRIPLEs to RGBQUADs */
1211 for (i=0; i < colors; i++)
1213 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1214 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1215 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1216 colorTable[i].rgbReserved = 0;
1221 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1226 PALETTEENTRY entries[256];
1227 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1228 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1230 for (i = 0; i < colors; i++, index++)
1232 PALETTEENTRY *entry = &entries[*index % count];
1233 colorTable[i].rgbRed = entry->peRed;
1234 colorTable[i].rgbGreen = entry->peGreen;
1235 colorTable[i].rgbBlue = entry->peBlue;
1236 colorTable[i].rgbReserved = 0;
1239 bmp->color_table = colorTable;
1240 bmp->nb_colors = colors;
1243 /***********************************************************************
1244 * CreateDIBSection (GDI32.@)
1246 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1247 VOID **bits, HANDLE section, DWORD offset)
1251 BOOL bDesktopDC = FALSE;
1257 DWORD compression, sizeImage;
1258 void *mapBits = NULL;
1260 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1261 &planes, &bpp, &compression, &sizeImage )) == -1))
1264 if (compression != BI_RGB && compression != BI_BITFIELDS)
1266 TRACE("can't create a compressed (%u) dibsection\n", compression);
1270 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1272 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1273 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1275 dib->dsBm.bmType = 0;
1276 dib->dsBm.bmWidth = width;
1277 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1278 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1279 dib->dsBm.bmPlanes = planes;
1280 dib->dsBm.bmBitsPixel = bpp;
1281 dib->dsBm.bmBits = NULL;
1283 if (!bitmap_type) /* core header */
1285 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1286 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1287 dib->dsBmih.biWidth = width;
1288 dib->dsBmih.biHeight = height;
1289 dib->dsBmih.biPlanes = planes;
1290 dib->dsBmih.biBitCount = bpp;
1291 dib->dsBmih.biCompression = compression;
1292 dib->dsBmih.biXPelsPerMeter = 0;
1293 dib->dsBmih.biYPelsPerMeter = 0;
1294 dib->dsBmih.biClrUsed = 0;
1295 dib->dsBmih.biClrImportant = 0;
1299 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1300 dib->dsBmih = bmi->bmiHeader;
1301 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1304 /* set number of entries in bmi.bmiColors table */
1306 dib->dsBmih.biClrUsed = 1 << bpp;
1308 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1310 /* set dsBitfields values */
1311 if (usage == DIB_PAL_COLORS || bpp <= 8)
1313 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1319 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1320 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1321 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1325 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1326 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1327 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1331 /* get storage location for DIB bits */
1335 SYSTEM_INFO SystemInfo;
1339 GetSystemInfo( &SystemInfo );
1340 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1341 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1342 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1343 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1348 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1349 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1351 dib->dshSection = section;
1352 dib->dsOffset = offset;
1354 if (!dib->dsBm.bmBits)
1356 HeapFree( GetProcessHeap(), 0, dib );
1360 /* If the reference hdc is null, take the desktop dc */
1363 hdc = CreateCompatibleDC(0);
1367 if (!(dc = get_dc_ptr( hdc ))) goto error;
1369 /* create Device Dependent Bitmap and add DIB pointer */
1370 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1371 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1373 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1376 bmp->funcs = dc->funcs;
1377 /* create local copy of DIB palette */
1378 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1379 GDI_ReleaseObj( ret );
1381 if (dc->funcs->pCreateDIBSection)
1383 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1385 DeleteObject( ret );
1391 release_dc_ptr( dc );
1392 if (bDesktopDC) DeleteDC( hdc );
1393 if (ret && bits) *bits = dib->dsBm.bmBits;
1397 if (bDesktopDC) DeleteDC( hdc );
1398 if (section) UnmapViewOfFile( mapBits );
1399 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1400 HeapFree( GetProcessHeap(), 0, dib );