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 );
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 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
230 info->bmiHeader.biCompression == BI_RGB)
232 /* Windows appears to have a fast case optimization
233 * that uses the wrong origin for top-down DIBs */
234 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
237 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
239 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
240 widthDst == widthSrc && heightDst == heightSrc &&
241 info->bmiHeader.biCompression == BI_RGB &&
245 if ((bmp = GDI_GetObjPtr( hBitmap, OBJ_BITMAP )))
247 if (bmp->bitmap.bmBitsPixel == bpp &&
248 bmp->bitmap.bmWidth == widthSrc &&
249 bmp->bitmap.bmHeight == heightSrc &&
250 bmp->bitmap.bmPlanes == planes)
252 GDI_ReleaseObj( hBitmap );
259 TRACE("using fast path\n");
260 ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
264 /* slow path - need to use StretchBlt */
266 HPALETTE hpal = NULL;
269 hdcMem = CreateCompatibleDC( hdc );
270 hBitmap = CreateCompatibleBitmap(hdc, width, height);
271 hOldBitmap = SelectObject( hdcMem, hBitmap );
272 if(wUsage == DIB_PAL_COLORS)
274 hpal = GetCurrentObject(hdc, OBJ_PAL);
275 hpal = SelectPalette(hdcMem, hpal, FALSE);
278 if (info->bmiHeader.biCompression == BI_RLE4 ||
279 info->bmiHeader.biCompression == BI_RLE8) {
281 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
282 * contain all the rectangle described in bmiHeader, but only part of it.
283 * This mean that those undescribed pixels must be left untouched.
284 * So, we first copy on a memory bitmap the current content of the
285 * destination rectangle, blit the DIB bits on top of it - hence leaving
286 * the gaps untouched -, and blitting the rectangle back.
287 * This insure that gaps are untouched on the destination rectangle
288 * Not doing so leads to trashed images (the gaps contain what was on the
289 * memory bitmap => generally black or garbage)
290 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
291 * another speed vs correctness issue. Anyway, if speed is needed, then the
292 * pStretchDIBits function shall be implemented.
296 /* copy existing bitmap from destination dc */
297 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
298 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
302 ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
304 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
305 left (negative biHeight) */
306 if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
307 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
308 widthSrc, heightSrc, dwRop );
310 SelectPalette(hdcMem, hpal, FALSE);
311 SelectObject( hdcMem, hOldBitmap );
313 DeleteObject( hBitmap );
320 /******************************************************************************
321 * SetDIBits [GDI32.@]
323 * Sets pixels in a bitmap using colors from DIB.
326 * hdc [I] Handle to device context
327 * hbitmap [I] Handle to bitmap
328 * startscan [I] Starting scan line
329 * lines [I] Number of scan lines
330 * bits [I] Array of bitmap bits
331 * info [I] Address of structure with data
332 * coloruse [I] Type of color indexes to use
335 * Success: Number of scan lines copied
338 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
339 UINT lines, LPCVOID bits, const BITMAPINFO *info,
342 DC *dc = get_dc_ptr( hdc );
343 BOOL delete_hdc = FALSE;
347 if (coloruse == DIB_RGB_COLORS && !dc)
349 hdc = CreateCompatibleDC(0);
350 dc = get_dc_ptr( hdc );
358 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
360 release_dc_ptr( dc );
361 if (delete_hdc) DeleteDC(hdc);
365 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
370 if (bitmap->funcs != dc->funcs)
371 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
372 else if (dc->funcs->pSetDIBits)
373 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
374 bits, info, coloruse );
378 GDI_ReleaseObj( hbitmap );
379 release_dc_ptr( dc );
380 if (delete_hdc) DeleteDC(hdc);
385 /***********************************************************************
386 * SetDIBitsToDevice (GDI32.@)
388 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
389 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
390 UINT lines, LPCVOID bits, const BITMAPINFO *info,
398 if (!(dc = get_dc_ptr( hdc ))) return 0;
400 if(dc->funcs->pSetDIBitsToDevice)
403 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
404 ySrc, startscan, lines, bits,
408 FIXME("unimplemented on hdc %p\n", hdc);
412 release_dc_ptr( dc );
416 /***********************************************************************
417 * SetDIBColorTable (GDI32.@)
419 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
425 if (!(dc = get_dc_ptr( hdc ))) return 0;
427 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
429 /* Check if currently selected bitmap is a DIB */
430 if (bitmap->color_table)
432 if (startpos < bitmap->nb_colors)
434 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
435 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
439 GDI_ReleaseObj( dc->hBitmap );
442 if (dc->funcs->pSetDIBColorTable)
443 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
445 release_dc_ptr( dc );
450 /***********************************************************************
451 * GetDIBColorTable (GDI32.@)
453 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
459 if (!(dc = get_dc_ptr( hdc ))) return 0;
461 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
463 /* Check if currently selected bitmap is a DIB */
464 if (bitmap->color_table)
466 if (startpos < bitmap->nb_colors)
468 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
469 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
473 GDI_ReleaseObj( dc->hBitmap );
475 release_dc_ptr( dc );
479 /* FIXME the following two structs should be combined with __sysPalTemplate in
480 objects/color.c - this should happen after de-X11-ing both of these
482 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
485 static const RGBQUAD EGAColorsQuads[16] = {
486 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
487 { 0x00, 0x00, 0x00, 0x00 },
488 { 0x00, 0x00, 0x80, 0x00 },
489 { 0x00, 0x80, 0x00, 0x00 },
490 { 0x00, 0x80, 0x80, 0x00 },
491 { 0x80, 0x00, 0x00, 0x00 },
492 { 0x80, 0x00, 0x80, 0x00 },
493 { 0x80, 0x80, 0x00, 0x00 },
494 { 0x80, 0x80, 0x80, 0x00 },
495 { 0xc0, 0xc0, 0xc0, 0x00 },
496 { 0x00, 0x00, 0xff, 0x00 },
497 { 0x00, 0xff, 0x00, 0x00 },
498 { 0x00, 0xff, 0xff, 0x00 },
499 { 0xff, 0x00, 0x00, 0x00 },
500 { 0xff, 0x00, 0xff, 0x00 },
501 { 0xff, 0xff, 0x00, 0x00 },
502 { 0xff, 0xff, 0xff, 0x00 }
505 static const RGBTRIPLE EGAColorsTriples[16] = {
506 /* rgbBlue, rgbGreen, rgbRed */
507 { 0x00, 0x00, 0x00 },
508 { 0x00, 0x00, 0x80 },
509 { 0x00, 0x80, 0x00 },
510 { 0x00, 0x80, 0x80 },
511 { 0x80, 0x00, 0x00 },
512 { 0x80, 0x00, 0x80 },
513 { 0x80, 0x80, 0x00 },
514 { 0x80, 0x80, 0x80 },
515 { 0xc0, 0xc0, 0xc0 },
516 { 0x00, 0x00, 0xff },
517 { 0x00, 0xff, 0x00 },
518 { 0x00, 0xff, 0xff },
519 { 0xff, 0x00, 0x00 } ,
520 { 0xff, 0x00, 0xff },
521 { 0xff, 0xff, 0x00 },
525 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
526 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
527 { 0x00, 0x00, 0x00, 0x00 },
528 { 0x00, 0x00, 0x80, 0x00 },
529 { 0x00, 0x80, 0x00, 0x00 },
530 { 0x00, 0x80, 0x80, 0x00 },
531 { 0x80, 0x00, 0x00, 0x00 },
532 { 0x80, 0x00, 0x80, 0x00 },
533 { 0x80, 0x80, 0x00, 0x00 },
534 { 0xc0, 0xc0, 0xc0, 0x00 },
535 { 0xc0, 0xdc, 0xc0, 0x00 },
536 { 0xf0, 0xca, 0xa6, 0x00 },
537 { 0xf0, 0xfb, 0xff, 0x00 },
538 { 0xa4, 0xa0, 0xa0, 0x00 },
539 { 0x80, 0x80, 0x80, 0x00 },
540 { 0x00, 0x00, 0xf0, 0x00 },
541 { 0x00, 0xff, 0x00, 0x00 },
542 { 0x00, 0xff, 0xff, 0x00 },
543 { 0xff, 0x00, 0x00, 0x00 },
544 { 0xff, 0x00, 0xff, 0x00 },
545 { 0xff, 0xff, 0x00, 0x00 },
546 { 0xff, 0xff, 0xff, 0x00 }
549 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
550 /* rgbBlue, rgbGreen, rgbRed */
551 { 0x00, 0x00, 0x00 },
552 { 0x00, 0x00, 0x80 },
553 { 0x00, 0x80, 0x00 },
554 { 0x00, 0x80, 0x80 },
555 { 0x80, 0x00, 0x00 },
556 { 0x80, 0x00, 0x80 },
557 { 0x80, 0x80, 0x00 },
558 { 0xc0, 0xc0, 0xc0 },
559 { 0xc0, 0xdc, 0xc0 },
560 { 0xf0, 0xca, 0xa6 },
561 { 0xf0, 0xfb, 0xff },
562 { 0xa4, 0xa0, 0xa0 },
563 { 0x80, 0x80, 0x80 },
564 { 0x00, 0x00, 0xf0 },
565 { 0x00, 0xff, 0x00 },
566 { 0x00, 0xff, 0xff },
567 { 0xff, 0x00, 0x00 },
568 { 0xff, 0x00, 0xff },
569 { 0xff, 0xff, 0x00 },
574 /******************************************************************************
575 * GetDIBits [GDI32.@]
577 * Retrieves bits of bitmap and copies to buffer.
580 * Success: Number of scan lines copied from bitmap
583 INT WINAPI GetDIBits(
584 HDC hdc, /* [in] Handle to device context */
585 HBITMAP hbitmap, /* [in] Handle to bitmap */
586 UINT startscan, /* [in] First scan line to set in dest bitmap */
587 UINT lines, /* [in] Number of scan lines to copy */
588 LPVOID bits, /* [out] Address of array for bitmap bits */
589 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
590 UINT coloruse) /* [in] RGB or palette index */
602 RGBTRIPLE* rgbTriples;
607 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
608 if (bitmap_type == -1)
610 ERR("Invalid bitmap format\n");
613 core_header = (bitmap_type == 0);
614 if (!(dc = get_dc_ptr( hdc )))
616 SetLastError( ERROR_INVALID_PARAMETER );
620 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
622 release_dc_ptr( dc );
626 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
627 rgbTriples = colorPtr;
630 /* Transfer color info */
634 case 0: /* query bitmap info only */
637 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
638 coreheader->bcWidth = bmp->bitmap.bmWidth;
639 coreheader->bcHeight = bmp->bitmap.bmHeight;
640 coreheader->bcPlanes = 1;
641 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
645 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
646 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
647 info->bmiHeader.biPlanes = 1;
648 info->bmiHeader.biSizeImage =
649 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
650 bmp->bitmap.bmHeight,
651 bmp->bitmap.bmBitsPixel );
654 info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
655 switch (bmp->dib->dsBm.bmBitsPixel)
659 info->bmiHeader.biCompression = BI_BITFIELDS;
662 info->bmiHeader.biCompression = BI_RGB;
668 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
669 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
671 info->bmiHeader.biXPelsPerMeter = 0;
672 info->bmiHeader.biYPelsPerMeter = 0;
673 info->bmiHeader.biClrUsed = 0;
674 info->bmiHeader.biClrImportant = 0;
676 /* Windows 2000 doesn't touch the additional struct members if
677 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
679 lines = abs(bmp->bitmap.bmHeight);
685 if (!core_header) info->bmiHeader.biClrUsed = 0;
687 /* If the bitmap object already has a dib section at the
688 same color depth then get the color map from it */
689 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
690 if(coloruse == DIB_RGB_COLORS) {
691 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
695 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
696 RGBTRIPLE* index = rgbTriples;
698 for (i=0; i < colors; i++, index++)
700 index->rgbtRed = bmp->color_table[i].rgbRed;
701 index->rgbtGreen = bmp->color_table[i].rgbGreen;
702 index->rgbtBlue = bmp->color_table[i].rgbBlue;
707 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
708 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
712 WORD *index = colorPtr;
713 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
718 if (coloruse == DIB_PAL_COLORS) {
719 for (i = 0; i < (1 << bpp); i++)
720 ((WORD *)colorPtr)[i] = (WORD)i;
722 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
723 /* For color DDBs in native depth (mono DDBs always have
724 a black/white palette):
725 Generate the color map from the selected palette */
726 PALETTEENTRY palEntry[256];
728 memset( palEntry, 0, sizeof(palEntry) );
729 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
731 release_dc_ptr( dc );
732 GDI_ReleaseObj( hbitmap );
735 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
738 rgbTriples[i].rgbtRed = palEntry[i].peRed;
739 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
740 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
744 rgbQuads[i].rgbRed = palEntry[i].peRed;
745 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
746 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
747 rgbQuads[i].rgbReserved = 0;
755 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
756 rgbTriples[0].rgbtBlue = 0;
757 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
758 rgbTriples[1].rgbtBlue = 0xff;
762 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
763 rgbQuads[0].rgbBlue = 0;
764 rgbQuads[0].rgbReserved = 0;
765 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
766 rgbQuads[1].rgbBlue = 0xff;
767 rgbQuads[1].rgbReserved = 0;
773 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
775 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
786 memcpy(rgbTriples, DefLogPaletteTriples,
787 10 * sizeof(RGBTRIPLE));
788 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
789 10 * sizeof(RGBTRIPLE));
790 color = rgbTriples + 10;
791 for(r = 0; r <= 5; r++) /* FIXME */
792 for(g = 0; g <= 5; g++)
793 for(b = 0; b <= 5; b++) {
794 color->rgbtRed = (r * 0xff) / 5;
795 color->rgbtGreen = (g * 0xff) / 5;
796 color->rgbtBlue = (b * 0xff) / 5;
805 memcpy(rgbQuads, DefLogPaletteQuads,
806 10 * sizeof(RGBQUAD));
807 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
808 10 * sizeof(RGBQUAD));
809 color = rgbQuads + 10;
810 for(r = 0; r <= 5; r++) /* FIXME */
811 for(g = 0; g <= 5; g++)
812 for(b = 0; b <= 5; b++) {
813 color->rgbRed = (r * 0xff) / 5;
814 color->rgbGreen = (g * 0xff) / 5;
815 color->rgbBlue = (b * 0xff) / 5;
816 color->rgbReserved = 0;
827 if (info->bmiHeader.biCompression == BI_BITFIELDS)
829 ((PDWORD)info->bmiColors)[0] = 0x7c00;
830 ((PDWORD)info->bmiColors)[1] = 0x03e0;
831 ((PDWORD)info->bmiColors)[2] = 0x001f;
836 if (info->bmiHeader.biCompression == BI_BITFIELDS)
838 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
841 ((PDWORD)info->bmiColors)[0] = 0xf800;
842 ((PDWORD)info->bmiColors)[1] = 0x07e0;
843 ((PDWORD)info->bmiColors)[2] = 0x001f;
850 if (info->bmiHeader.biCompression == BI_BITFIELDS)
852 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
855 ((PDWORD)info->bmiColors)[0] = 0xff0000;
856 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
857 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
865 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
866 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
868 /*FIXME: Only RGB dibs supported for now */
869 unsigned int srcwidth = bmp->dib->dsBm.bmWidth;
870 int srcwidthb = bmp->dib->dsBm.bmWidthBytes;
871 unsigned int dstwidth = width;
872 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
873 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
874 unsigned int x, y, width, widthb;
877 * If copying from a top-down source bitmap, move the source
878 * pointer to the end of the source bitmap and negate the width
879 * so that we copy the bits upside-down.
881 if (bmp->dib->dsBmih.biHeight < 0)
883 sbits += (srcwidthb * (int)(abs(bmp->dib->dsBmih.biHeight) - 2 * startscan - 1));
884 srcwidthb = -srcwidthb;
886 /*Same for the destination.*/
889 dbits = (LPBYTE)bits + (dstwidthb * (lines - 1));
890 dstwidthb = -dstwidthb;
895 case 16: /* 16 bpp dstDIB */
897 LPWORD dstbits = (LPWORD)dbits;
898 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
900 /* FIXME: BI_BITFIELDS not supported yet */
902 switch(bmp->dib->dsBm.bmBitsPixel) {
904 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
906 widthb = min(abs(srcwidthb), abs(dstwidthb));
907 /* FIXME: BI_BITFIELDS not supported yet */
908 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
909 memcpy(dbits, sbits, widthb);
913 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
915 LPBYTE srcbits = sbits;
917 width = min(srcwidth, dstwidth);
918 for( y = 0; y < lines; y++) {
919 for( x = 0; x < width; x++, srcbits += 3)
920 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
921 (((WORD)srcbits[1] << 2) & gmask) |
922 (((WORD)srcbits[2] << 7) & rmask);
924 dstbits = (LPWORD)(dbits+=dstwidthb);
925 srcbits = (sbits += srcwidthb);
930 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
932 LPDWORD srcbits = (LPDWORD)sbits;
935 width = min(srcwidth, dstwidth);
936 for( y = 0; y < lines; y++) {
937 for( x = 0; x < width; x++ ) {
939 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
940 ((val >> 9) & rmask));
942 dstbits = (LPWORD)(dbits+=dstwidthb);
943 srcbits = (LPDWORD)(sbits+=srcwidthb);
948 default: /* ? bit bmp -> 16 bit DIB */
949 FIXME("15/16 bit DIB %d bit bitmap\n",
950 bmp->bitmap.bmBitsPixel);
956 case 24: /* 24 bpp dstDIB */
958 LPBYTE dstbits = dbits;
960 switch(bmp->dib->dsBm.bmBitsPixel) {
962 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
964 LPWORD srcbits = (LPWORD)sbits;
967 width = min(srcwidth, dstwidth);
968 /* FIXME: BI_BITFIELDS not supported yet */
969 for( y = 0; y < lines; y++) {
970 for( x = 0; x < width; x++ ) {
972 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
973 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
974 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
976 dstbits = dbits+=dstwidthb;
977 srcbits = (LPWORD)(sbits+=srcwidthb);
982 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
984 widthb = min(abs(srcwidthb), abs(dstwidthb));
985 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
986 memcpy(dbits, sbits, widthb);
990 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
992 LPBYTE srcbits = sbits;
994 width = min(srcwidth, dstwidth);
995 for( y = 0; y < lines; y++) {
996 for( x = 0; x < width; x++, srcbits++ ) {
997 *dstbits++ = *srcbits++;
998 *dstbits++ = *srcbits++;
999 *dstbits++ = *srcbits++;
1001 dstbits = dbits+=dstwidthb;
1002 srcbits = sbits+=srcwidthb;
1007 default: /* ? bit bmp -> 24 bit DIB */
1008 FIXME("24 bit DIB %d bit bitmap\n",
1009 bmp->bitmap.bmBitsPixel);
1015 case 32: /* 32 bpp dstDIB */
1017 LPDWORD dstbits = (LPDWORD)dbits;
1019 /* FIXME: BI_BITFIELDS not supported yet */
1021 switch(bmp->dib->dsBm.bmBitsPixel) {
1022 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
1024 LPWORD srcbits = (LPWORD)sbits;
1027 width = min(srcwidth, dstwidth);
1028 /* FIXME: BI_BITFIELDS not supported yet */
1029 for( y = 0; y < lines; y++) {
1030 for( x = 0; x < width; x++ ) {
1031 val = (DWORD)*srcbits++;
1032 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
1033 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
1034 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
1036 dstbits=(LPDWORD)(dbits+=dstwidthb);
1037 srcbits=(LPWORD)(sbits+=srcwidthb);
1042 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1044 LPBYTE srcbits = sbits;
1046 width = min(srcwidth, dstwidth);
1047 for( y = 0; y < lines; y++) {
1048 for( x = 0; x < width; x++, srcbits+=3 )
1049 *dstbits++ = srcbits[0] |
1052 dstbits=(LPDWORD)(dbits+=dstwidthb);
1053 srcbits=(sbits+=srcwidthb);
1058 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1060 widthb = min(abs(srcwidthb), abs(dstwidthb));
1061 /* FIXME: BI_BITFIELDS not supported yet */
1062 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1063 memcpy(dbits, sbits, widthb);
1068 default: /* ? bit bmp -> 32 bit DIB */
1069 FIXME("32 bit DIB %d bit bitmap\n",
1070 bmp->bitmap.bmBitsPixel);
1076 default: /* ? bit DIB */
1077 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1081 /* Otherwise, get bits from the XImage */
1084 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1087 if (bmp->funcs && bmp->funcs->pGetDIBits)
1088 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1089 lines, bits, info, coloruse );
1091 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1095 else lines = abs(height);
1097 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1098 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1102 /* FIXME: biSizeImage should be calculated according to the selected
1103 compression algorithm if biCompression != BI_RGB */
1104 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1105 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1107 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1110 release_dc_ptr( dc );
1111 GDI_ReleaseObj( hbitmap );
1116 /***********************************************************************
1117 * CreateDIBitmap (GDI32.@)
1119 * Creates a DDB (device dependent bitmap) from a DIB.
1120 * The DDB will have the same color depth as the reference DC.
1122 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1123 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1133 if (!header) return 0;
1135 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1139 TRACE("Bitmap has a negative width\n");
1143 /* Top-down DIBs have a negative height */
1144 if (height < 0) height = -height;
1146 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1147 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1150 handle = CreateBitmap( width, height, 1, 1, NULL );
1152 handle = CreateCompatibleBitmap( hdc, width, height );
1156 if (init & CBM_INIT)
1158 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1160 DeleteObject( handle );
1165 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1167 if (!BITMAP_SetOwnerDC( handle, dc ))
1169 DeleteObject( handle );
1172 release_dc_ptr( dc );
1179 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1180 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1182 RGBQUAD *colorTable;
1183 unsigned int colors, i;
1184 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1188 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1192 colors = info->bmiHeader.biClrUsed;
1193 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1197 ERR("called with >256 colors!\n");
1201 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1203 if(coloruse == DIB_RGB_COLORS)
1207 /* Convert RGBTRIPLEs to RGBQUADs */
1208 for (i=0; i < colors; i++)
1210 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1211 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1212 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1213 colorTable[i].rgbReserved = 0;
1218 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1223 PALETTEENTRY entries[256];
1224 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1225 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1227 for (i = 0; i < colors; i++, index++)
1229 PALETTEENTRY *entry = &entries[*index % count];
1230 colorTable[i].rgbRed = entry->peRed;
1231 colorTable[i].rgbGreen = entry->peGreen;
1232 colorTable[i].rgbBlue = entry->peBlue;
1233 colorTable[i].rgbReserved = 0;
1236 bmp->color_table = colorTable;
1237 bmp->nb_colors = colors;
1240 /***********************************************************************
1241 * CreateDIBSection (GDI32.@)
1243 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1244 VOID **bits, HANDLE section, DWORD offset)
1248 BOOL bDesktopDC = FALSE;
1254 DWORD compression, sizeImage;
1255 void *mapBits = NULL;
1258 if(bits) *bits = NULL;
1262 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1263 &planes, &bpp, &compression, &sizeImage )) == -1))
1270 if (compression == BI_BITFIELDS) break;
1276 if (compression == BI_RGB) break;
1279 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1283 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1285 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1286 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1288 dib->dsBm.bmType = 0;
1289 dib->dsBm.bmWidth = width;
1290 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1291 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1292 dib->dsBm.bmPlanes = planes;
1293 dib->dsBm.bmBitsPixel = bpp;
1294 dib->dsBm.bmBits = NULL;
1296 if (!bitmap_type) /* core header */
1298 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1299 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1300 dib->dsBmih.biWidth = width;
1301 dib->dsBmih.biHeight = height;
1302 dib->dsBmih.biPlanes = planes;
1303 dib->dsBmih.biBitCount = bpp;
1304 dib->dsBmih.biCompression = compression;
1305 dib->dsBmih.biXPelsPerMeter = 0;
1306 dib->dsBmih.biYPelsPerMeter = 0;
1307 dib->dsBmih.biClrUsed = 0;
1308 dib->dsBmih.biClrImportant = 0;
1312 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1313 dib->dsBmih = bmi->bmiHeader;
1314 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1317 /* set number of entries in bmi.bmiColors table */
1319 dib->dsBmih.biClrUsed = 1 << bpp;
1321 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1323 /* set dsBitfields values */
1324 if (usage == DIB_PAL_COLORS || bpp <= 8)
1326 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1332 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1333 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1334 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1338 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1339 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1340 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1344 /* get storage location for DIB bits */
1348 SYSTEM_INFO SystemInfo;
1352 GetSystemInfo( &SystemInfo );
1353 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1354 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1355 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1356 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1361 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1362 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1364 dib->dshSection = section;
1365 dib->dsOffset = offset;
1367 if (!dib->dsBm.bmBits)
1369 HeapFree( GetProcessHeap(), 0, dib );
1373 /* If the reference hdc is null, take the desktop dc */
1376 hdc = CreateCompatibleDC(0);
1380 if (!(dc = get_dc_ptr( hdc ))) goto error;
1382 /* create Device Dependent Bitmap and add DIB pointer */
1383 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1384 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1386 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1389 bmp->funcs = dc->funcs;
1390 /* create local copy of DIB palette */
1391 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1392 GDI_ReleaseObj( ret );
1394 if (dc->funcs->pCreateDIBSection)
1396 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1398 DeleteObject( ret );
1404 release_dc_ptr( dc );
1405 if (bDesktopDC) DeleteDC( hdc );
1406 if (ret && bits) *bits = dib->dsBm.bmBits;
1410 if (bDesktopDC) DeleteDC( hdc );
1411 if (section) UnmapViewOfFile( mapBits );
1412 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1413 HeapFree( GetProcessHeap(), 0, dib );