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 bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
126 unsigned int colors, size, masks = 0;
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 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
142 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
143 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
148 /***********************************************************************
151 * Get the info from a bitmap header.
152 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
154 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
155 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
157 if (header->biSize == sizeof(BITMAPCOREHEADER))
159 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
160 *width = core->bcWidth;
161 *height = core->bcHeight;
162 *planes = core->bcPlanes;
163 *bpp = core->bcBitCount;
168 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
170 *width = header->biWidth;
171 *height = header->biHeight;
172 *planes = header->biPlanes;
173 *bpp = header->biBitCount;
174 *compr = header->biCompression;
175 *size = header->biSizeImage;
178 ERR("(%d): unknown/wrong size for header\n", header->biSize );
183 /***********************************************************************
184 * StretchDIBits (GDI32.@)
186 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
187 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
188 INT heightSrc, const void *bits,
189 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
197 if (!(dc = get_dc_ptr( hdc ))) return 0;
199 if(dc->funcs->pStretchDIBits)
202 ret = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
203 heightDst, xSrc, ySrc, widthSrc,
204 heightSrc, bits, info, wUsage, dwRop);
205 release_dc_ptr( dc );
207 else /* use StretchBlt */
214 BOOL fastpath = FALSE;
216 release_dc_ptr( dc );
218 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
220 ERR("Invalid bitmap\n");
226 ERR("Bitmap has a negative width\n");
230 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
232 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
233 widthDst == widthSrc && heightDst == heightSrc &&
234 info->bmiHeader.biCompression == BI_RGB &&
238 if ((bmp = GDI_GetObjPtr( hBitmap, OBJ_BITMAP )))
240 if (bmp->bitmap.bmBitsPixel == bpp &&
241 bmp->bitmap.bmWidth == widthSrc &&
242 bmp->bitmap.bmHeight == heightSrc &&
243 bmp->bitmap.bmPlanes == planes)
245 GDI_ReleaseObj( hBitmap );
252 TRACE("using fast path\n");
253 ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
257 /* slow path - need to use StretchBlt */
259 HPALETTE hpal = NULL;
262 hdcMem = CreateCompatibleDC( hdc );
263 hBitmap = CreateCompatibleBitmap(hdc, width, height);
264 hOldBitmap = SelectObject( hdcMem, hBitmap );
265 if(wUsage == DIB_PAL_COLORS)
267 hpal = GetCurrentObject(hdc, OBJ_PAL);
268 hpal = SelectPalette(hdcMem, hpal, FALSE);
271 if (info->bmiHeader.biCompression == BI_RLE4 ||
272 info->bmiHeader.biCompression == BI_RLE8) {
274 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
275 * contain all the rectangle described in bmiHeader, but only part of it.
276 * This mean that those undescribed pixels must be left untouched.
277 * So, we first copy on a memory bitmap the current content of the
278 * destination rectangle, blit the DIB bits on top of it - hence leaving
279 * the gaps untouched -, and blitting the rectangle back.
280 * This insure that gaps are untouched on the destination rectangle
281 * Not doing so leads to trashed images (the gaps contain what was on the
282 * memory bitmap => generally black or garbage)
283 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
284 * another speed vs correctness issue. Anyway, if speed is needed, then the
285 * pStretchDIBits function shall be implemented.
289 /* copy existing bitmap from destination dc */
290 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
291 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
295 ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
297 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
298 left (negative biHeight) */
299 if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
300 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
301 widthSrc, heightSrc, dwRop );
303 SelectPalette(hdcMem, hpal, FALSE);
304 SelectObject( hdcMem, hOldBitmap );
306 DeleteObject( hBitmap );
313 /******************************************************************************
314 * SetDIBits [GDI32.@]
316 * Sets pixels in a bitmap using colors from DIB.
319 * hdc [I] Handle to device context
320 * hbitmap [I] Handle to bitmap
321 * startscan [I] Starting scan line
322 * lines [I] Number of scan lines
323 * bits [I] Array of bitmap bits
324 * info [I] Address of structure with data
325 * coloruse [I] Type of color indexes to use
328 * Success: Number of scan lines copied
331 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
332 UINT lines, LPCVOID bits, const BITMAPINFO *info,
335 DC *dc = get_dc_ptr( hdc );
336 BOOL delete_hdc = FALSE;
340 if (coloruse == DIB_RGB_COLORS && !dc)
342 hdc = CreateCompatibleDC(0);
343 dc = get_dc_ptr( hdc );
351 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
353 release_dc_ptr( dc );
354 if (delete_hdc) DeleteDC(hdc);
358 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
363 if (bitmap->funcs != dc->funcs)
364 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
365 else if (dc->funcs->pSetDIBits)
366 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
367 bits, info, coloruse );
371 GDI_ReleaseObj( hbitmap );
372 release_dc_ptr( dc );
373 if (delete_hdc) DeleteDC(hdc);
378 /***********************************************************************
379 * SetDIBitsToDevice (GDI32.@)
381 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
382 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
383 UINT lines, LPCVOID bits, const BITMAPINFO *info,
391 if (!(dc = get_dc_ptr( hdc ))) return 0;
393 if(dc->funcs->pSetDIBitsToDevice)
396 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
397 ySrc, startscan, lines, bits,
401 FIXME("unimplemented on hdc %p\n", hdc);
405 release_dc_ptr( dc );
409 /***********************************************************************
410 * SetDIBColorTable (GDI32.@)
412 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
418 if (!(dc = get_dc_ptr( hdc ))) return 0;
420 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
422 /* Check if currently selected bitmap is a DIB */
423 if (bitmap->color_table)
425 if (startpos < bitmap->nb_colors)
427 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
428 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
432 GDI_ReleaseObj( dc->hBitmap );
435 if (dc->funcs->pSetDIBColorTable)
436 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
438 release_dc_ptr( dc );
443 /***********************************************************************
444 * GetDIBColorTable (GDI32.@)
446 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
451 if (!(dc = get_dc_ptr( hdc ))) return 0;
453 if (dc->funcs->pGetDIBColorTable)
454 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
457 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP );
460 /* Check if currently selected bitmap is a DIB */
461 if (bitmap->color_table)
463 if (startpos < bitmap->nb_colors)
465 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
466 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
470 GDI_ReleaseObj( dc->hBitmap );
473 release_dc_ptr( dc );
477 /* FIXME the following two structs should be combined with __sysPalTemplate in
478 objects/color.c - this should happen after de-X11-ing both of these
480 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
483 static const RGBQUAD EGAColorsQuads[16] = {
484 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
485 { 0x00, 0x00, 0x00, 0x00 },
486 { 0x00, 0x00, 0x80, 0x00 },
487 { 0x00, 0x80, 0x00, 0x00 },
488 { 0x00, 0x80, 0x80, 0x00 },
489 { 0x80, 0x00, 0x00, 0x00 },
490 { 0x80, 0x00, 0x80, 0x00 },
491 { 0x80, 0x80, 0x00, 0x00 },
492 { 0x80, 0x80, 0x80, 0x00 },
493 { 0xc0, 0xc0, 0xc0, 0x00 },
494 { 0x00, 0x00, 0xff, 0x00 },
495 { 0x00, 0xff, 0x00, 0x00 },
496 { 0x00, 0xff, 0xff, 0x00 },
497 { 0xff, 0x00, 0x00, 0x00 },
498 { 0xff, 0x00, 0xff, 0x00 },
499 { 0xff, 0xff, 0x00, 0x00 },
500 { 0xff, 0xff, 0xff, 0x00 }
503 static const RGBTRIPLE EGAColorsTriples[16] = {
504 /* rgbBlue, rgbGreen, rgbRed */
505 { 0x00, 0x00, 0x00 },
506 { 0x00, 0x00, 0x80 },
507 { 0x00, 0x80, 0x00 },
508 { 0x00, 0x80, 0x80 },
509 { 0x80, 0x00, 0x00 },
510 { 0x80, 0x00, 0x80 },
511 { 0x80, 0x80, 0x00 },
512 { 0x80, 0x80, 0x80 },
513 { 0xc0, 0xc0, 0xc0 },
514 { 0x00, 0x00, 0xff },
515 { 0x00, 0xff, 0x00 },
516 { 0x00, 0xff, 0xff },
517 { 0xff, 0x00, 0x00 } ,
518 { 0xff, 0x00, 0xff },
519 { 0xff, 0xff, 0x00 },
523 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
524 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
525 { 0x00, 0x00, 0x00, 0x00 },
526 { 0x00, 0x00, 0x80, 0x00 },
527 { 0x00, 0x80, 0x00, 0x00 },
528 { 0x00, 0x80, 0x80, 0x00 },
529 { 0x80, 0x00, 0x00, 0x00 },
530 { 0x80, 0x00, 0x80, 0x00 },
531 { 0x80, 0x80, 0x00, 0x00 },
532 { 0xc0, 0xc0, 0xc0, 0x00 },
533 { 0xc0, 0xdc, 0xc0, 0x00 },
534 { 0xf0, 0xca, 0xa6, 0x00 },
535 { 0xf0, 0xfb, 0xff, 0x00 },
536 { 0xa4, 0xa0, 0xa0, 0x00 },
537 { 0x80, 0x80, 0x80, 0x00 },
538 { 0x00, 0x00, 0xf0, 0x00 },
539 { 0x00, 0xff, 0x00, 0x00 },
540 { 0x00, 0xff, 0xff, 0x00 },
541 { 0xff, 0x00, 0x00, 0x00 },
542 { 0xff, 0x00, 0xff, 0x00 },
543 { 0xff, 0xff, 0x00, 0x00 },
544 { 0xff, 0xff, 0xff, 0x00 }
547 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
548 /* rgbBlue, rgbGreen, rgbRed */
549 { 0x00, 0x00, 0x00 },
550 { 0x00, 0x00, 0x80 },
551 { 0x00, 0x80, 0x00 },
552 { 0x00, 0x80, 0x80 },
553 { 0x80, 0x00, 0x00 },
554 { 0x80, 0x00, 0x80 },
555 { 0x80, 0x80, 0x00 },
556 { 0xc0, 0xc0, 0xc0 },
557 { 0xc0, 0xdc, 0xc0 },
558 { 0xf0, 0xca, 0xa6 },
559 { 0xf0, 0xfb, 0xff },
560 { 0xa4, 0xa0, 0xa0 },
561 { 0x80, 0x80, 0x80 },
562 { 0x00, 0x00, 0xf0 },
563 { 0x00, 0xff, 0x00 },
564 { 0x00, 0xff, 0xff },
565 { 0xff, 0x00, 0x00 },
566 { 0xff, 0x00, 0xff },
567 { 0xff, 0xff, 0x00 },
572 /******************************************************************************
573 * GetDIBits [GDI32.@]
575 * Retrieves bits of bitmap and copies to buffer.
578 * Success: Number of scan lines copied from bitmap
581 INT WINAPI GetDIBits(
582 HDC hdc, /* [in] Handle to device context */
583 HBITMAP hbitmap, /* [in] Handle to bitmap */
584 UINT startscan, /* [in] First scan line to set in dest bitmap */
585 UINT lines, /* [in] Number of scan lines to copy */
586 LPVOID bits, /* [out] Address of array for bitmap bits */
587 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
588 UINT coloruse) /* [in] RGB or palette index */
600 RGBTRIPLE* rgbTriples;
605 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
606 if (bitmap_type == -1)
608 ERR("Invalid bitmap format\n");
611 core_header = (bitmap_type == 0);
612 if (!(dc = get_dc_ptr( hdc )))
614 SetLastError( ERROR_INVALID_PARAMETER );
618 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
620 release_dc_ptr( dc );
624 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
625 rgbTriples = colorPtr;
628 /* Transfer color info */
632 case 0: /* query bitmap info only */
635 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
636 coreheader->bcWidth = bmp->bitmap.bmWidth;
637 coreheader->bcHeight = bmp->bitmap.bmHeight;
638 coreheader->bcPlanes = 1;
639 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
643 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
644 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
645 info->bmiHeader.biPlanes = 1;
646 info->bmiHeader.biSizeImage =
647 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
648 bmp->bitmap.bmHeight,
649 bmp->bitmap.bmBitsPixel );
650 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
651 switch(bmp->bitmap.bmBitsPixel)
654 info->bmiHeader.biBitCount = 16;
657 info->bmiHeader.biBitCount = 32;
660 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
663 info->bmiHeader.biXPelsPerMeter = 0;
664 info->bmiHeader.biYPelsPerMeter = 0;
665 info->bmiHeader.biClrUsed = 0;
666 info->bmiHeader.biClrImportant = 0;
668 /* Windows 2000 doesn't touch the additional struct members if
669 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
671 lines = abs(bmp->bitmap.bmHeight);
677 if (!core_header) info->bmiHeader.biClrUsed = 0;
679 /* If the bitmap object already has a dib section at the
680 same color depth then get the color map from it */
681 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
682 if(coloruse == DIB_RGB_COLORS) {
683 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
687 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
688 RGBTRIPLE* index = rgbTriples;
690 for (i=0; i < colors; i++, index++)
692 index->rgbtRed = bmp->color_table[i].rgbRed;
693 index->rgbtGreen = bmp->color_table[i].rgbGreen;
694 index->rgbtBlue = bmp->color_table[i].rgbBlue;
699 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
700 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
704 WORD *index = colorPtr;
705 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
710 if (coloruse == DIB_PAL_COLORS) {
711 for (i = 0; i < (1 << bpp); i++)
712 ((WORD *)colorPtr)[i] = (WORD)i;
714 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
715 /* For color DDBs in native depth (mono DDBs always have
716 a black/white palette):
717 Generate the color map from the selected palette */
718 PALETTEENTRY palEntry[256];
720 memset( palEntry, 0, sizeof(palEntry) );
721 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
723 release_dc_ptr( dc );
724 GDI_ReleaseObj( hbitmap );
727 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
730 rgbTriples[i].rgbtRed = palEntry[i].peRed;
731 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
732 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
736 rgbQuads[i].rgbRed = palEntry[i].peRed;
737 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
738 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
739 rgbQuads[i].rgbReserved = 0;
747 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
748 rgbTriples[0].rgbtBlue = 0;
749 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
750 rgbTriples[1].rgbtBlue = 0xff;
754 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
755 rgbQuads[0].rgbBlue = 0;
756 rgbQuads[0].rgbReserved = 0;
757 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
758 rgbQuads[1].rgbBlue = 0xff;
759 rgbQuads[1].rgbReserved = 0;
765 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
767 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
778 memcpy(rgbTriples, DefLogPaletteTriples,
779 10 * sizeof(RGBTRIPLE));
780 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
781 10 * sizeof(RGBTRIPLE));
782 color = rgbTriples + 10;
783 for(r = 0; r <= 5; r++) /* FIXME */
784 for(g = 0; g <= 5; g++)
785 for(b = 0; b <= 5; b++) {
786 color->rgbtRed = (r * 0xff) / 5;
787 color->rgbtGreen = (g * 0xff) / 5;
788 color->rgbtBlue = (b * 0xff) / 5;
797 memcpy(rgbQuads, DefLogPaletteQuads,
798 10 * sizeof(RGBQUAD));
799 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
800 10 * sizeof(RGBQUAD));
801 color = rgbQuads + 10;
802 for(r = 0; r <= 5; r++) /* FIXME */
803 for(g = 0; g <= 5; g++)
804 for(b = 0; b <= 5; b++) {
805 color->rgbRed = (r * 0xff) / 5;
806 color->rgbGreen = (g * 0xff) / 5;
807 color->rgbBlue = (b * 0xff) / 5;
808 color->rgbReserved = 0;
819 if (info->bmiHeader.biCompression == BI_BITFIELDS)
821 ((PDWORD)info->bmiColors)[0] = 0x7c00;
822 ((PDWORD)info->bmiColors)[1] = 0x03e0;
823 ((PDWORD)info->bmiColors)[2] = 0x001f;
828 if (info->bmiHeader.biCompression == BI_BITFIELDS)
830 ((PDWORD)info->bmiColors)[0] = 0xf800;
831 ((PDWORD)info->bmiColors)[1] = 0x07e0;
832 ((PDWORD)info->bmiColors)[2] = 0x001f;
838 if (info->bmiHeader.biCompression == BI_BITFIELDS)
840 ((PDWORD)info->bmiColors)[0] = 0xff0000;
841 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
842 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
849 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
850 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
852 /*FIXME: Only RGB dibs supported for now */
853 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
854 unsigned int dstwidth = width;
855 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
856 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
857 unsigned int x, y, width, widthb;
859 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
861 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
862 dstwidthb = -dstwidthb;
868 case 16: /* 16 bpp dstDIB */
870 LPWORD dstbits = (LPWORD)dbits;
871 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
873 /* FIXME: BI_BITFIELDS not supported yet */
875 switch(bmp->dib->dsBm.bmBitsPixel) {
877 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
879 widthb = min(srcwidthb, abs(dstwidthb));
880 /* FIXME: BI_BITFIELDS not supported yet */
881 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
882 memcpy(dbits, sbits, widthb);
886 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
888 LPBYTE srcbits = sbits;
890 width = min(srcwidth, dstwidth);
891 for( y = 0; y < lines; y++) {
892 for( x = 0; x < width; x++, srcbits += 3)
893 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
894 (((WORD)srcbits[1] << 2) & gmask) |
895 (((WORD)srcbits[2] << 7) & rmask);
897 dstbits = (LPWORD)(dbits+=dstwidthb);
898 srcbits = (sbits += srcwidthb);
903 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
905 LPDWORD srcbits = (LPDWORD)sbits;
908 width = min(srcwidth, dstwidth);
909 for( y = 0; y < lines; y++) {
910 for( x = 0; x < width; x++ ) {
912 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
913 ((val >> 9) & rmask));
915 dstbits = (LPWORD)(dbits+=dstwidthb);
916 srcbits = (LPDWORD)(sbits+=srcwidthb);
921 default: /* ? bit bmp -> 16 bit DIB */
922 FIXME("15/16 bit DIB %d bit bitmap\n",
923 bmp->bitmap.bmBitsPixel);
929 case 24: /* 24 bpp dstDIB */
931 LPBYTE dstbits = dbits;
933 switch(bmp->dib->dsBm.bmBitsPixel) {
935 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
937 LPWORD srcbits = (LPWORD)sbits;
940 width = min(srcwidth, dstwidth);
941 /* FIXME: BI_BITFIELDS not supported yet */
942 for( y = 0; y < lines; y++) {
943 for( x = 0; x < width; x++ ) {
945 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
946 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
947 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
949 dstbits = dbits+=dstwidthb;
950 srcbits = (LPWORD)(sbits+=srcwidthb);
955 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
957 widthb = min(srcwidthb, abs(dstwidthb));
958 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
959 memcpy(dbits, sbits, widthb);
963 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
965 LPBYTE srcbits = sbits;
967 width = min(srcwidth, dstwidth);
968 for( y = 0; y < lines; y++) {
969 for( x = 0; x < width; x++, srcbits++ ) {
970 *dstbits++ = *srcbits++;
971 *dstbits++ = *srcbits++;
972 *dstbits++ = *srcbits++;
974 dstbits = dbits+=dstwidthb;
975 srcbits = sbits+=srcwidthb;
980 default: /* ? bit bmp -> 24 bit DIB */
981 FIXME("24 bit DIB %d bit bitmap\n",
982 bmp->bitmap.bmBitsPixel);
988 case 32: /* 32 bpp dstDIB */
990 LPDWORD dstbits = (LPDWORD)dbits;
992 /* FIXME: BI_BITFIELDS not supported yet */
994 switch(bmp->dib->dsBm.bmBitsPixel) {
995 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
997 LPWORD srcbits = (LPWORD)sbits;
1000 width = min(srcwidth, dstwidth);
1001 /* FIXME: BI_BITFIELDS not supported yet */
1002 for( y = 0; y < lines; y++) {
1003 for( x = 0; x < width; x++ ) {
1004 val = (DWORD)*srcbits++;
1005 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
1006 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
1007 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
1009 dstbits=(LPDWORD)(dbits+=dstwidthb);
1010 srcbits=(LPWORD)(sbits+=srcwidthb);
1015 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1017 LPBYTE srcbits = sbits;
1019 width = min(srcwidth, dstwidth);
1020 for( y = 0; y < lines; y++) {
1021 for( x = 0; x < width; x++, srcbits+=3 )
1022 *dstbits++ = srcbits[0] |
1025 dstbits=(LPDWORD)(dbits+=dstwidthb);
1026 srcbits=(sbits+=srcwidthb);
1031 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1033 widthb = min(srcwidthb, abs(dstwidthb));
1034 /* FIXME: BI_BITFIELDS not supported yet */
1035 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1036 memcpy(dbits, sbits, widthb);
1041 default: /* ? bit bmp -> 32 bit DIB */
1042 FIXME("32 bit DIB %d bit bitmap\n",
1043 bmp->bitmap.bmBitsPixel);
1049 default: /* ? bit DIB */
1050 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1054 /* Otherwise, get bits from the XImage */
1057 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1060 if (bmp->funcs && bmp->funcs->pGetDIBits)
1061 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1062 lines, bits, info, coloruse );
1064 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1068 else lines = abs(height);
1070 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1071 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1075 /* FIXME: biSizeImage should be calculated according to the selected
1076 compression algorithm if biCompression != BI_RGB */
1077 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1078 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1080 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1083 release_dc_ptr( dc );
1084 GDI_ReleaseObj( hbitmap );
1089 /***********************************************************************
1090 * CreateDIBitmap (GDI32.@)
1092 * Creates a DDB (device dependent bitmap) from a DIB.
1093 * The DDB will have the same color depth as the reference DC.
1095 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1096 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1106 if (!header) return 0;
1108 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1112 TRACE("Bitmap has a negative width\n");
1116 /* Top-down DIBs have a negative height */
1117 if (height < 0) height = -height;
1119 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1120 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1123 handle = CreateBitmap( width, height, 1, 1, NULL );
1125 handle = CreateCompatibleBitmap( hdc, width, height );
1129 if (init & CBM_INIT)
1131 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1133 DeleteObject( handle );
1138 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1140 if (!BITMAP_SetOwnerDC( handle, dc ))
1142 DeleteObject( handle );
1145 release_dc_ptr( dc );
1152 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1153 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1155 RGBQUAD *colorTable;
1156 unsigned int colors, i;
1157 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1161 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1165 colors = info->bmiHeader.biClrUsed;
1166 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1170 ERR("called with >256 colors!\n");
1174 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1176 if(coloruse == DIB_RGB_COLORS)
1180 /* Convert RGBTRIPLEs to RGBQUADs */
1181 for (i=0; i < colors; i++)
1183 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1184 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1185 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1186 colorTable[i].rgbReserved = 0;
1191 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1196 PALETTEENTRY entries[256];
1197 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1198 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1200 for (i = 0; i < colors; i++, index++)
1202 PALETTEENTRY *entry = &entries[*index % count];
1203 colorTable[i].rgbRed = entry->peRed;
1204 colorTable[i].rgbGreen = entry->peGreen;
1205 colorTable[i].rgbBlue = entry->peBlue;
1206 colorTable[i].rgbReserved = 0;
1209 bmp->color_table = colorTable;
1210 bmp->nb_colors = colors;
1213 /***********************************************************************
1214 * CreateDIBSection (GDI32.@)
1216 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1217 VOID **bits, HANDLE section, DWORD offset)
1221 BOOL bDesktopDC = FALSE;
1227 DWORD compression, sizeImage;
1228 void *mapBits = NULL;
1231 if(bits) *bits = NULL;
1235 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1236 &planes, &bpp, &compression, &sizeImage )) == -1))
1239 if (compression != BI_RGB && compression != BI_BITFIELDS)
1241 TRACE("can't create a compressed (%u) dibsection\n", compression);
1245 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1247 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1248 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1250 dib->dsBm.bmType = 0;
1251 dib->dsBm.bmWidth = width;
1252 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1253 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1254 dib->dsBm.bmPlanes = planes;
1255 dib->dsBm.bmBitsPixel = bpp;
1256 dib->dsBm.bmBits = NULL;
1258 if (!bitmap_type) /* core header */
1260 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1261 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1262 dib->dsBmih.biWidth = width;
1263 dib->dsBmih.biHeight = height;
1264 dib->dsBmih.biPlanes = planes;
1265 dib->dsBmih.biBitCount = bpp;
1266 dib->dsBmih.biCompression = compression;
1267 dib->dsBmih.biXPelsPerMeter = 0;
1268 dib->dsBmih.biYPelsPerMeter = 0;
1269 dib->dsBmih.biClrUsed = 0;
1270 dib->dsBmih.biClrImportant = 0;
1274 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1275 dib->dsBmih = bmi->bmiHeader;
1276 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1279 /* set number of entries in bmi.bmiColors table */
1281 dib->dsBmih.biClrUsed = 1 << bpp;
1283 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1285 /* set dsBitfields values */
1286 if (usage == DIB_PAL_COLORS || bpp <= 8)
1288 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1294 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1295 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1296 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1300 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1301 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1302 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1306 /* get storage location for DIB bits */
1310 SYSTEM_INFO SystemInfo;
1314 GetSystemInfo( &SystemInfo );
1315 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1316 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1317 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1318 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1323 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1324 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1326 dib->dshSection = section;
1327 dib->dsOffset = offset;
1329 if (!dib->dsBm.bmBits)
1331 HeapFree( GetProcessHeap(), 0, dib );
1335 /* If the reference hdc is null, take the desktop dc */
1338 hdc = CreateCompatibleDC(0);
1342 if (!(dc = get_dc_ptr( hdc ))) goto error;
1344 /* create Device Dependent Bitmap and add DIB pointer */
1345 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1346 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1348 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1351 bmp->funcs = dc->funcs;
1352 /* create local copy of DIB palette */
1353 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1354 GDI_ReleaseObj( ret );
1356 if (dc->funcs->pCreateDIBSection)
1358 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1360 DeleteObject( ret );
1366 release_dc_ptr( dc );
1367 if (bDesktopDC) DeleteDC( hdc );
1368 if (ret && bits) *bits = dib->dsBm.bmBits;
1372 if (bDesktopDC) DeleteDC( hdc );
1373 if (section) UnmapViewOfFile( mapBits );
1374 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1375 HeapFree( GetProcessHeap(), 0, dib );