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;
348 if (coloruse == DIB_RGB_COLORS && !dc)
350 hdc = CreateCompatibleDC(0);
351 dc = get_dc_ptr( hdc );
359 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
361 release_dc_ptr( dc );
362 if (delete_hdc) DeleteDC(hdc);
366 physdev = GET_DC_PHYSDEV( dc, pSetDIBits );
367 if (BITMAP_SetOwnerDC( hbitmap, physdev ))
368 result = physdev->funcs->pSetDIBits( physdev, hbitmap, startscan, lines, bits, info, coloruse );
370 GDI_ReleaseObj( hbitmap );
371 release_dc_ptr( dc );
372 if (delete_hdc) DeleteDC(hdc);
377 /***********************************************************************
378 * SetDIBitsToDevice (GDI32.@)
380 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
381 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
382 UINT lines, LPCVOID bits, const BITMAPINFO *info,
390 if ((dc = get_dc_ptr( hdc )))
392 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
394 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
395 ySrc, startscan, lines, bits, info, coloruse );
396 release_dc_ptr( dc );
401 /***********************************************************************
402 * SetDIBColorTable (GDI32.@)
404 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
410 if (!(dc = get_dc_ptr( hdc ))) return 0;
412 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
414 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
416 /* Check if currently selected bitmap is a DIB */
417 if (bitmap->color_table)
419 if (startpos < bitmap->nb_colors)
421 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
422 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
426 GDI_ReleaseObj( dc->hBitmap );
427 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
429 release_dc_ptr( dc );
434 /***********************************************************************
435 * GetDIBColorTable (GDI32.@)
437 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
443 if (!(dc = get_dc_ptr( hdc ))) return 0;
445 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
447 /* Check if currently selected bitmap is a DIB */
448 if (bitmap->color_table)
450 if (startpos < bitmap->nb_colors)
452 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
453 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
457 GDI_ReleaseObj( dc->hBitmap );
459 release_dc_ptr( dc );
463 /* FIXME the following two structs should be combined with __sysPalTemplate in
464 objects/color.c - this should happen after de-X11-ing both of these
466 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
469 static const RGBQUAD EGAColorsQuads[16] = {
470 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
471 { 0x00, 0x00, 0x00, 0x00 },
472 { 0x00, 0x00, 0x80, 0x00 },
473 { 0x00, 0x80, 0x00, 0x00 },
474 { 0x00, 0x80, 0x80, 0x00 },
475 { 0x80, 0x00, 0x00, 0x00 },
476 { 0x80, 0x00, 0x80, 0x00 },
477 { 0x80, 0x80, 0x00, 0x00 },
478 { 0x80, 0x80, 0x80, 0x00 },
479 { 0xc0, 0xc0, 0xc0, 0x00 },
480 { 0x00, 0x00, 0xff, 0x00 },
481 { 0x00, 0xff, 0x00, 0x00 },
482 { 0x00, 0xff, 0xff, 0x00 },
483 { 0xff, 0x00, 0x00, 0x00 },
484 { 0xff, 0x00, 0xff, 0x00 },
485 { 0xff, 0xff, 0x00, 0x00 },
486 { 0xff, 0xff, 0xff, 0x00 }
489 static const RGBTRIPLE EGAColorsTriples[16] = {
490 /* rgbBlue, rgbGreen, rgbRed */
491 { 0x00, 0x00, 0x00 },
492 { 0x00, 0x00, 0x80 },
493 { 0x00, 0x80, 0x00 },
494 { 0x00, 0x80, 0x80 },
495 { 0x80, 0x00, 0x00 },
496 { 0x80, 0x00, 0x80 },
497 { 0x80, 0x80, 0x00 },
498 { 0x80, 0x80, 0x80 },
499 { 0xc0, 0xc0, 0xc0 },
500 { 0x00, 0x00, 0xff },
501 { 0x00, 0xff, 0x00 },
502 { 0x00, 0xff, 0xff },
503 { 0xff, 0x00, 0x00 } ,
504 { 0xff, 0x00, 0xff },
505 { 0xff, 0xff, 0x00 },
509 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
510 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
511 { 0x00, 0x00, 0x00, 0x00 },
512 { 0x00, 0x00, 0x80, 0x00 },
513 { 0x00, 0x80, 0x00, 0x00 },
514 { 0x00, 0x80, 0x80, 0x00 },
515 { 0x80, 0x00, 0x00, 0x00 },
516 { 0x80, 0x00, 0x80, 0x00 },
517 { 0x80, 0x80, 0x00, 0x00 },
518 { 0xc0, 0xc0, 0xc0, 0x00 },
519 { 0xc0, 0xdc, 0xc0, 0x00 },
520 { 0xf0, 0xca, 0xa6, 0x00 },
521 { 0xf0, 0xfb, 0xff, 0x00 },
522 { 0xa4, 0xa0, 0xa0, 0x00 },
523 { 0x80, 0x80, 0x80, 0x00 },
524 { 0x00, 0x00, 0xf0, 0x00 },
525 { 0x00, 0xff, 0x00, 0x00 },
526 { 0x00, 0xff, 0xff, 0x00 },
527 { 0xff, 0x00, 0x00, 0x00 },
528 { 0xff, 0x00, 0xff, 0x00 },
529 { 0xff, 0xff, 0x00, 0x00 },
530 { 0xff, 0xff, 0xff, 0x00 }
533 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
534 /* rgbBlue, rgbGreen, rgbRed */
535 { 0x00, 0x00, 0x00 },
536 { 0x00, 0x00, 0x80 },
537 { 0x00, 0x80, 0x00 },
538 { 0x00, 0x80, 0x80 },
539 { 0x80, 0x00, 0x00 },
540 { 0x80, 0x00, 0x80 },
541 { 0x80, 0x80, 0x00 },
542 { 0xc0, 0xc0, 0xc0 },
543 { 0xc0, 0xdc, 0xc0 },
544 { 0xf0, 0xca, 0xa6 },
545 { 0xf0, 0xfb, 0xff },
546 { 0xa4, 0xa0, 0xa0 },
547 { 0x80, 0x80, 0x80 },
548 { 0x00, 0x00, 0xf0 },
549 { 0x00, 0xff, 0x00 },
550 { 0x00, 0xff, 0xff },
551 { 0xff, 0x00, 0x00 },
552 { 0xff, 0x00, 0xff },
553 { 0xff, 0xff, 0x00 },
558 /******************************************************************************
559 * GetDIBits [GDI32.@]
561 * Retrieves bits of bitmap and copies to buffer.
564 * Success: Number of scan lines copied from bitmap
567 INT WINAPI GetDIBits(
568 HDC hdc, /* [in] Handle to device context */
569 HBITMAP hbitmap, /* [in] Handle to bitmap */
570 UINT startscan, /* [in] First scan line to set in dest bitmap */
571 UINT lines, /* [in] Number of scan lines to copy */
572 LPVOID bits, /* [out] Address of array for bitmap bits */
573 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
574 UINT coloruse) /* [in] RGB or palette index */
586 RGBTRIPLE* rgbTriples;
591 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
592 if (bitmap_type == -1)
594 ERR("Invalid bitmap format\n");
597 core_header = (bitmap_type == 0);
598 if (!(dc = get_dc_ptr( hdc )))
600 SetLastError( ERROR_INVALID_PARAMETER );
604 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
606 release_dc_ptr( dc );
610 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
611 rgbTriples = colorPtr;
614 /* Transfer color info */
618 case 0: /* query bitmap info only */
621 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
622 coreheader->bcWidth = bmp->bitmap.bmWidth;
623 coreheader->bcHeight = bmp->bitmap.bmHeight;
624 coreheader->bcPlanes = 1;
625 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
629 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
630 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
631 info->bmiHeader.biPlanes = 1;
632 info->bmiHeader.biSizeImage =
633 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
634 bmp->bitmap.bmHeight,
635 bmp->bitmap.bmBitsPixel );
638 info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
639 switch (bmp->dib->dsBm.bmBitsPixel)
643 info->bmiHeader.biCompression = BI_BITFIELDS;
646 info->bmiHeader.biCompression = BI_RGB;
652 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
653 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
655 info->bmiHeader.biXPelsPerMeter = 0;
656 info->bmiHeader.biYPelsPerMeter = 0;
657 info->bmiHeader.biClrUsed = 0;
658 info->bmiHeader.biClrImportant = 0;
660 /* Windows 2000 doesn't touch the additional struct members if
661 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
663 lines = abs(bmp->bitmap.bmHeight);
669 if (!core_header) info->bmiHeader.biClrUsed = 0;
671 /* If the bitmap object already has a dib section at the
672 same color depth then get the color map from it */
673 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
674 if(coloruse == DIB_RGB_COLORS) {
675 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
679 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
680 RGBTRIPLE* index = rgbTriples;
682 for (i=0; i < colors; i++, index++)
684 index->rgbtRed = bmp->color_table[i].rgbRed;
685 index->rgbtGreen = bmp->color_table[i].rgbGreen;
686 index->rgbtBlue = bmp->color_table[i].rgbBlue;
691 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
692 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
696 WORD *index = colorPtr;
697 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
702 if (coloruse == DIB_PAL_COLORS) {
703 for (i = 0; i < (1 << bpp); i++)
704 ((WORD *)colorPtr)[i] = (WORD)i;
706 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
707 /* For color DDBs in native depth (mono DDBs always have
708 a black/white palette):
709 Generate the color map from the selected palette */
710 PALETTEENTRY palEntry[256];
712 memset( palEntry, 0, sizeof(palEntry) );
713 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
715 release_dc_ptr( dc );
716 GDI_ReleaseObj( hbitmap );
719 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
722 rgbTriples[i].rgbtRed = palEntry[i].peRed;
723 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
724 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
728 rgbQuads[i].rgbRed = palEntry[i].peRed;
729 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
730 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
731 rgbQuads[i].rgbReserved = 0;
739 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
740 rgbTriples[0].rgbtBlue = 0;
741 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
742 rgbTriples[1].rgbtBlue = 0xff;
746 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
747 rgbQuads[0].rgbBlue = 0;
748 rgbQuads[0].rgbReserved = 0;
749 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
750 rgbQuads[1].rgbBlue = 0xff;
751 rgbQuads[1].rgbReserved = 0;
757 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
759 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
770 memcpy(rgbTriples, DefLogPaletteTriples,
771 10 * sizeof(RGBTRIPLE));
772 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
773 10 * sizeof(RGBTRIPLE));
774 color = rgbTriples + 10;
775 for(r = 0; r <= 5; r++) /* FIXME */
776 for(g = 0; g <= 5; g++)
777 for(b = 0; b <= 5; b++) {
778 color->rgbtRed = (r * 0xff) / 5;
779 color->rgbtGreen = (g * 0xff) / 5;
780 color->rgbtBlue = (b * 0xff) / 5;
789 memcpy(rgbQuads, DefLogPaletteQuads,
790 10 * sizeof(RGBQUAD));
791 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
792 10 * sizeof(RGBQUAD));
793 color = rgbQuads + 10;
794 for(r = 0; r <= 5; r++) /* FIXME */
795 for(g = 0; g <= 5; g++)
796 for(b = 0; b <= 5; b++) {
797 color->rgbRed = (r * 0xff) / 5;
798 color->rgbGreen = (g * 0xff) / 5;
799 color->rgbBlue = (b * 0xff) / 5;
800 color->rgbReserved = 0;
811 if (info->bmiHeader.biCompression == BI_BITFIELDS)
813 ((PDWORD)info->bmiColors)[0] = 0x7c00;
814 ((PDWORD)info->bmiColors)[1] = 0x03e0;
815 ((PDWORD)info->bmiColors)[2] = 0x001f;
820 if (info->bmiHeader.biCompression == BI_BITFIELDS)
822 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
825 ((PDWORD)info->bmiColors)[0] = 0xf800;
826 ((PDWORD)info->bmiColors)[1] = 0x07e0;
827 ((PDWORD)info->bmiColors)[2] = 0x001f;
834 if (info->bmiHeader.biCompression == BI_BITFIELDS)
836 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
839 ((PDWORD)info->bmiColors)[0] = 0xff0000;
840 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
841 ((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;
854 int srcwidthb = bmp->dib->dsBm.bmWidthBytes;
855 unsigned int dstwidth = width;
856 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
857 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
858 unsigned int x, y, width, widthb;
861 * If copying from a top-down source bitmap, move the source
862 * pointer to the end of the source bitmap and negate the width
863 * so that we copy the bits upside-down.
865 if (bmp->dib->dsBmih.biHeight < 0)
867 sbits += (srcwidthb * (int)(abs(bmp->dib->dsBmih.biHeight) - 2 * startscan - 1));
868 srcwidthb = -srcwidthb;
870 /*Same for the destination.*/
873 dbits = (LPBYTE)bits + (dstwidthb * (lines - 1));
874 dstwidthb = -dstwidthb;
879 case 16: /* 16 bpp dstDIB */
881 LPWORD dstbits = (LPWORD)dbits;
882 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
884 /* FIXME: BI_BITFIELDS not supported yet */
886 switch(bmp->dib->dsBm.bmBitsPixel) {
888 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
890 widthb = min(abs(srcwidthb), abs(dstwidthb));
891 /* FIXME: BI_BITFIELDS not supported yet */
892 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
893 memcpy(dbits, sbits, widthb);
897 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
899 LPBYTE srcbits = sbits;
901 width = min(srcwidth, dstwidth);
902 for( y = 0; y < lines; y++) {
903 for( x = 0; x < width; x++, srcbits += 3)
904 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
905 (((WORD)srcbits[1] << 2) & gmask) |
906 (((WORD)srcbits[2] << 7) & rmask);
908 dstbits = (LPWORD)(dbits+=dstwidthb);
909 srcbits = (sbits += srcwidthb);
914 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
916 LPDWORD srcbits = (LPDWORD)sbits;
919 width = min(srcwidth, dstwidth);
920 for( y = 0; y < lines; y++) {
921 for( x = 0; x < width; x++ ) {
923 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
924 ((val >> 9) & rmask));
926 dstbits = (LPWORD)(dbits+=dstwidthb);
927 srcbits = (LPDWORD)(sbits+=srcwidthb);
932 default: /* ? bit bmp -> 16 bit DIB */
933 FIXME("15/16 bit DIB %d bit bitmap\n",
934 bmp->bitmap.bmBitsPixel);
940 case 24: /* 24 bpp dstDIB */
942 LPBYTE dstbits = dbits;
944 switch(bmp->dib->dsBm.bmBitsPixel) {
946 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
948 LPWORD srcbits = (LPWORD)sbits;
951 width = min(srcwidth, dstwidth);
952 /* FIXME: BI_BITFIELDS not supported yet */
953 for( y = 0; y < lines; y++) {
954 for( x = 0; x < width; x++ ) {
956 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
957 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
958 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
960 dstbits = dbits+=dstwidthb;
961 srcbits = (LPWORD)(sbits+=srcwidthb);
966 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
968 widthb = min(abs(srcwidthb), abs(dstwidthb));
969 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
970 memcpy(dbits, sbits, widthb);
974 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
976 LPBYTE srcbits = sbits;
978 width = min(srcwidth, dstwidth);
979 for( y = 0; y < lines; y++) {
980 for( x = 0; x < width; x++, srcbits++ ) {
981 *dstbits++ = *srcbits++;
982 *dstbits++ = *srcbits++;
983 *dstbits++ = *srcbits++;
985 dstbits = dbits+=dstwidthb;
986 srcbits = sbits+=srcwidthb;
991 default: /* ? bit bmp -> 24 bit DIB */
992 FIXME("24 bit DIB %d bit bitmap\n",
993 bmp->bitmap.bmBitsPixel);
999 case 32: /* 32 bpp dstDIB */
1001 LPDWORD dstbits = (LPDWORD)dbits;
1003 /* FIXME: BI_BITFIELDS not supported yet */
1005 switch(bmp->dib->dsBm.bmBitsPixel) {
1006 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
1008 LPWORD srcbits = (LPWORD)sbits;
1011 width = min(srcwidth, dstwidth);
1012 /* FIXME: BI_BITFIELDS not supported yet */
1013 for( y = 0; y < lines; y++) {
1014 for( x = 0; x < width; x++ ) {
1015 val = (DWORD)*srcbits++;
1016 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
1017 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
1018 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
1020 dstbits=(LPDWORD)(dbits+=dstwidthb);
1021 srcbits=(LPWORD)(sbits+=srcwidthb);
1026 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1028 LPBYTE srcbits = sbits;
1030 width = min(srcwidth, dstwidth);
1031 for( y = 0; y < lines; y++) {
1032 for( x = 0; x < width; x++, srcbits+=3 )
1033 *dstbits++ = srcbits[0] |
1036 dstbits=(LPDWORD)(dbits+=dstwidthb);
1037 srcbits=(sbits+=srcwidthb);
1042 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1044 widthb = min(abs(srcwidthb), abs(dstwidthb));
1045 /* FIXME: BI_BITFIELDS not supported yet */
1046 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1047 memcpy(dbits, sbits, widthb);
1052 default: /* ? bit bmp -> 32 bit DIB */
1053 FIXME("32 bit DIB %d bit bitmap\n",
1054 bmp->bitmap.bmBitsPixel);
1060 default: /* ? bit DIB */
1061 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1065 /* Otherwise, get bits from the XImage */
1068 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDIBits );
1069 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
1070 else lines = physdev->funcs->pGetDIBits( physdev, hbitmap, startscan,
1071 lines, bits, info, coloruse );
1074 else lines = abs(height);
1076 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1077 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1081 /* FIXME: biSizeImage should be calculated according to the selected
1082 compression algorithm if biCompression != BI_RGB */
1083 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1084 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1086 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1089 release_dc_ptr( dc );
1090 GDI_ReleaseObj( hbitmap );
1095 /***********************************************************************
1096 * CreateDIBitmap (GDI32.@)
1098 * Creates a DDB (device dependent bitmap) from a DIB.
1099 * The DDB will have the same color depth as the reference DC.
1101 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1102 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1111 if (!header) return 0;
1113 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1117 TRACE("Bitmap has a negative width\n");
1121 /* Top-down DIBs have a negative height */
1122 if (height < 0) height = -height;
1124 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1125 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1128 handle = CreateBitmap( width, height, 1, 1, NULL );
1130 handle = CreateCompatibleBitmap( hdc, width, height );
1134 if (init & CBM_INIT)
1136 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1138 DeleteObject( handle );
1147 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1148 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1150 RGBQUAD *colorTable;
1151 unsigned int colors, i;
1152 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1156 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1160 colors = info->bmiHeader.biClrUsed;
1161 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1165 ERR("called with >256 colors!\n");
1169 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1171 if(coloruse == DIB_RGB_COLORS)
1175 /* Convert RGBTRIPLEs to RGBQUADs */
1176 for (i=0; i < colors; i++)
1178 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1179 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1180 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1181 colorTable[i].rgbReserved = 0;
1186 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1191 PALETTEENTRY entries[256];
1192 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1193 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1195 for (i = 0; i < colors; i++, index++)
1197 PALETTEENTRY *entry = &entries[*index % count];
1198 colorTable[i].rgbRed = entry->peRed;
1199 colorTable[i].rgbGreen = entry->peGreen;
1200 colorTable[i].rgbBlue = entry->peBlue;
1201 colorTable[i].rgbReserved = 0;
1204 bmp->color_table = colorTable;
1205 bmp->nb_colors = colors;
1208 /***********************************************************************
1209 * CreateDIBSection (GDI32.@)
1211 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1212 VOID **bits, HANDLE section, DWORD offset)
1216 BOOL bDesktopDC = FALSE;
1222 DWORD compression, sizeImage;
1223 void *mapBits = NULL;
1226 if(bits) *bits = NULL;
1230 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1231 &planes, &bpp, &compression, &sizeImage )) == -1))
1238 if (compression == BI_BITFIELDS) break;
1244 if (compression == BI_RGB) break;
1247 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1251 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1253 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1254 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1256 dib->dsBm.bmType = 0;
1257 dib->dsBm.bmWidth = width;
1258 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1259 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1260 dib->dsBm.bmPlanes = planes;
1261 dib->dsBm.bmBitsPixel = bpp;
1262 dib->dsBm.bmBits = NULL;
1264 if (!bitmap_type) /* core header */
1266 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1267 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1268 dib->dsBmih.biWidth = width;
1269 dib->dsBmih.biHeight = height;
1270 dib->dsBmih.biPlanes = planes;
1271 dib->dsBmih.biBitCount = bpp;
1272 dib->dsBmih.biCompression = compression;
1273 dib->dsBmih.biXPelsPerMeter = 0;
1274 dib->dsBmih.biYPelsPerMeter = 0;
1275 dib->dsBmih.biClrUsed = 0;
1276 dib->dsBmih.biClrImportant = 0;
1280 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1281 dib->dsBmih = bmi->bmiHeader;
1282 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1285 /* set number of entries in bmi.bmiColors table */
1287 dib->dsBmih.biClrUsed = 1 << bpp;
1289 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1291 /* set dsBitfields values */
1292 if (usage == DIB_PAL_COLORS || bpp <= 8)
1294 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1300 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1301 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1302 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1306 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1307 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1308 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1312 /* get storage location for DIB bits */
1316 SYSTEM_INFO SystemInfo;
1320 GetSystemInfo( &SystemInfo );
1321 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1322 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1323 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1324 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1329 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1330 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1332 dib->dshSection = section;
1333 dib->dsOffset = offset;
1335 if (!dib->dsBm.bmBits)
1337 HeapFree( GetProcessHeap(), 0, dib );
1341 /* If the reference hdc is null, take the desktop dc */
1344 hdc = CreateCompatibleDC(0);
1348 if (!(dc = get_dc_ptr( hdc ))) goto error;
1350 /* create Device Dependent Bitmap and add DIB pointer */
1351 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1352 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1354 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1356 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1358 bmp->funcs = physdev->funcs;
1359 /* create local copy of DIB palette */
1360 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1361 GDI_ReleaseObj( ret );
1363 if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1365 DeleteObject( ret );
1370 release_dc_ptr( dc );
1371 if (bDesktopDC) DeleteDC( hdc );
1372 if (ret && bits) *bits = dib->dsBm.bmBits;
1376 if (bDesktopDC) DeleteDC( hdc );
1377 if (section) UnmapViewOfFile( mapBits );
1378 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1379 HeapFree( GetProcessHeap(), 0, dib );