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 )
458 if (!(dc = get_dc_ptr( hdc ))) return 0;
460 if (dc->funcs->pGetDIBColorTable)
461 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
464 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP );
467 /* Check if currently selected bitmap is a DIB */
468 if (bitmap->color_table)
470 if (startpos < bitmap->nb_colors)
472 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
473 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
477 GDI_ReleaseObj( dc->hBitmap );
480 release_dc_ptr( dc );
484 /* FIXME the following two structs should be combined with __sysPalTemplate in
485 objects/color.c - this should happen after de-X11-ing both of these
487 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
490 static const RGBQUAD EGAColorsQuads[16] = {
491 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
492 { 0x00, 0x00, 0x00, 0x00 },
493 { 0x00, 0x00, 0x80, 0x00 },
494 { 0x00, 0x80, 0x00, 0x00 },
495 { 0x00, 0x80, 0x80, 0x00 },
496 { 0x80, 0x00, 0x00, 0x00 },
497 { 0x80, 0x00, 0x80, 0x00 },
498 { 0x80, 0x80, 0x00, 0x00 },
499 { 0x80, 0x80, 0x80, 0x00 },
500 { 0xc0, 0xc0, 0xc0, 0x00 },
501 { 0x00, 0x00, 0xff, 0x00 },
502 { 0x00, 0xff, 0x00, 0x00 },
503 { 0x00, 0xff, 0xff, 0x00 },
504 { 0xff, 0x00, 0x00, 0x00 },
505 { 0xff, 0x00, 0xff, 0x00 },
506 { 0xff, 0xff, 0x00, 0x00 },
507 { 0xff, 0xff, 0xff, 0x00 }
510 static const RGBTRIPLE EGAColorsTriples[16] = {
511 /* rgbBlue, rgbGreen, rgbRed */
512 { 0x00, 0x00, 0x00 },
513 { 0x00, 0x00, 0x80 },
514 { 0x00, 0x80, 0x00 },
515 { 0x00, 0x80, 0x80 },
516 { 0x80, 0x00, 0x00 },
517 { 0x80, 0x00, 0x80 },
518 { 0x80, 0x80, 0x00 },
519 { 0x80, 0x80, 0x80 },
520 { 0xc0, 0xc0, 0xc0 },
521 { 0x00, 0x00, 0xff },
522 { 0x00, 0xff, 0x00 },
523 { 0x00, 0xff, 0xff },
524 { 0xff, 0x00, 0x00 } ,
525 { 0xff, 0x00, 0xff },
526 { 0xff, 0xff, 0x00 },
530 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
531 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
532 { 0x00, 0x00, 0x00, 0x00 },
533 { 0x00, 0x00, 0x80, 0x00 },
534 { 0x00, 0x80, 0x00, 0x00 },
535 { 0x00, 0x80, 0x80, 0x00 },
536 { 0x80, 0x00, 0x00, 0x00 },
537 { 0x80, 0x00, 0x80, 0x00 },
538 { 0x80, 0x80, 0x00, 0x00 },
539 { 0xc0, 0xc0, 0xc0, 0x00 },
540 { 0xc0, 0xdc, 0xc0, 0x00 },
541 { 0xf0, 0xca, 0xa6, 0x00 },
542 { 0xf0, 0xfb, 0xff, 0x00 },
543 { 0xa4, 0xa0, 0xa0, 0x00 },
544 { 0x80, 0x80, 0x80, 0x00 },
545 { 0x00, 0x00, 0xf0, 0x00 },
546 { 0x00, 0xff, 0x00, 0x00 },
547 { 0x00, 0xff, 0xff, 0x00 },
548 { 0xff, 0x00, 0x00, 0x00 },
549 { 0xff, 0x00, 0xff, 0x00 },
550 { 0xff, 0xff, 0x00, 0x00 },
551 { 0xff, 0xff, 0xff, 0x00 }
554 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
555 /* rgbBlue, rgbGreen, rgbRed */
556 { 0x00, 0x00, 0x00 },
557 { 0x00, 0x00, 0x80 },
558 { 0x00, 0x80, 0x00 },
559 { 0x00, 0x80, 0x80 },
560 { 0x80, 0x00, 0x00 },
561 { 0x80, 0x00, 0x80 },
562 { 0x80, 0x80, 0x00 },
563 { 0xc0, 0xc0, 0xc0 },
564 { 0xc0, 0xdc, 0xc0 },
565 { 0xf0, 0xca, 0xa6 },
566 { 0xf0, 0xfb, 0xff },
567 { 0xa4, 0xa0, 0xa0 },
568 { 0x80, 0x80, 0x80 },
569 { 0x00, 0x00, 0xf0 },
570 { 0x00, 0xff, 0x00 },
571 { 0x00, 0xff, 0xff },
572 { 0xff, 0x00, 0x00 },
573 { 0xff, 0x00, 0xff },
574 { 0xff, 0xff, 0x00 },
579 /******************************************************************************
580 * GetDIBits [GDI32.@]
582 * Retrieves bits of bitmap and copies to buffer.
585 * Success: Number of scan lines copied from bitmap
588 INT WINAPI GetDIBits(
589 HDC hdc, /* [in] Handle to device context */
590 HBITMAP hbitmap, /* [in] Handle to bitmap */
591 UINT startscan, /* [in] First scan line to set in dest bitmap */
592 UINT lines, /* [in] Number of scan lines to copy */
593 LPVOID bits, /* [out] Address of array for bitmap bits */
594 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
595 UINT coloruse) /* [in] RGB or palette index */
607 RGBTRIPLE* rgbTriples;
612 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
613 if (bitmap_type == -1)
615 ERR("Invalid bitmap format\n");
618 core_header = (bitmap_type == 0);
619 if (!(dc = get_dc_ptr( hdc )))
621 SetLastError( ERROR_INVALID_PARAMETER );
625 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
627 release_dc_ptr( dc );
631 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
632 rgbTriples = colorPtr;
635 /* Transfer color info */
639 case 0: /* query bitmap info only */
642 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
643 coreheader->bcWidth = bmp->bitmap.bmWidth;
644 coreheader->bcHeight = bmp->bitmap.bmHeight;
645 coreheader->bcPlanes = 1;
646 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
650 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
651 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
652 info->bmiHeader.biPlanes = 1;
653 info->bmiHeader.biSizeImage =
654 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
655 bmp->bitmap.bmHeight,
656 bmp->bitmap.bmBitsPixel );
659 info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
660 switch (bmp->dib->dsBm.bmBitsPixel)
664 info->bmiHeader.biCompression = BI_BITFIELDS;
667 info->bmiHeader.biCompression = BI_RGB;
673 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
674 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
676 info->bmiHeader.biXPelsPerMeter = 0;
677 info->bmiHeader.biYPelsPerMeter = 0;
678 info->bmiHeader.biClrUsed = 0;
679 info->bmiHeader.biClrImportant = 0;
681 /* Windows 2000 doesn't touch the additional struct members if
682 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
684 lines = abs(bmp->bitmap.bmHeight);
690 if (!core_header) info->bmiHeader.biClrUsed = 0;
692 /* If the bitmap object already has a dib section at the
693 same color depth then get the color map from it */
694 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
695 if(coloruse == DIB_RGB_COLORS) {
696 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
700 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
701 RGBTRIPLE* index = rgbTriples;
703 for (i=0; i < colors; i++, index++)
705 index->rgbtRed = bmp->color_table[i].rgbRed;
706 index->rgbtGreen = bmp->color_table[i].rgbGreen;
707 index->rgbtBlue = bmp->color_table[i].rgbBlue;
712 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
713 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
717 WORD *index = colorPtr;
718 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
723 if (coloruse == DIB_PAL_COLORS) {
724 for (i = 0; i < (1 << bpp); i++)
725 ((WORD *)colorPtr)[i] = (WORD)i;
727 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
728 /* For color DDBs in native depth (mono DDBs always have
729 a black/white palette):
730 Generate the color map from the selected palette */
731 PALETTEENTRY palEntry[256];
733 memset( palEntry, 0, sizeof(palEntry) );
734 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
736 release_dc_ptr( dc );
737 GDI_ReleaseObj( hbitmap );
740 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
743 rgbTriples[i].rgbtRed = palEntry[i].peRed;
744 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
745 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
749 rgbQuads[i].rgbRed = palEntry[i].peRed;
750 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
751 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
752 rgbQuads[i].rgbReserved = 0;
760 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
761 rgbTriples[0].rgbtBlue = 0;
762 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
763 rgbTriples[1].rgbtBlue = 0xff;
767 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
768 rgbQuads[0].rgbBlue = 0;
769 rgbQuads[0].rgbReserved = 0;
770 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
771 rgbQuads[1].rgbBlue = 0xff;
772 rgbQuads[1].rgbReserved = 0;
778 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
780 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
791 memcpy(rgbTriples, DefLogPaletteTriples,
792 10 * sizeof(RGBTRIPLE));
793 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
794 10 * sizeof(RGBTRIPLE));
795 color = rgbTriples + 10;
796 for(r = 0; r <= 5; r++) /* FIXME */
797 for(g = 0; g <= 5; g++)
798 for(b = 0; b <= 5; b++) {
799 color->rgbtRed = (r * 0xff) / 5;
800 color->rgbtGreen = (g * 0xff) / 5;
801 color->rgbtBlue = (b * 0xff) / 5;
810 memcpy(rgbQuads, DefLogPaletteQuads,
811 10 * sizeof(RGBQUAD));
812 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
813 10 * sizeof(RGBQUAD));
814 color = rgbQuads + 10;
815 for(r = 0; r <= 5; r++) /* FIXME */
816 for(g = 0; g <= 5; g++)
817 for(b = 0; b <= 5; b++) {
818 color->rgbRed = (r * 0xff) / 5;
819 color->rgbGreen = (g * 0xff) / 5;
820 color->rgbBlue = (b * 0xff) / 5;
821 color->rgbReserved = 0;
832 if (info->bmiHeader.biCompression == BI_BITFIELDS)
834 ((PDWORD)info->bmiColors)[0] = 0x7c00;
835 ((PDWORD)info->bmiColors)[1] = 0x03e0;
836 ((PDWORD)info->bmiColors)[2] = 0x001f;
841 if (info->bmiHeader.biCompression == BI_BITFIELDS)
843 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
846 ((PDWORD)info->bmiColors)[0] = 0xf800;
847 ((PDWORD)info->bmiColors)[1] = 0x07e0;
848 ((PDWORD)info->bmiColors)[2] = 0x001f;
855 if (info->bmiHeader.biCompression == BI_BITFIELDS)
857 if (bmp->dib) memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
860 ((PDWORD)info->bmiColors)[0] = 0xff0000;
861 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
862 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
870 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
871 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
873 /*FIXME: Only RGB dibs supported for now */
874 unsigned int srcwidth = bmp->dib->dsBm.bmWidth;
875 int srcwidthb = bmp->dib->dsBm.bmWidthBytes;
876 unsigned int dstwidth = width;
877 unsigned int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
878 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
879 unsigned int x, y, width, widthb;
882 * If copying from a top-down source bitmap, move the source
883 * pointer to the end of the source bitmap and negate the width
884 * so that we copy the bits upside-down.
886 if (bmp->dib->dsBmih.biHeight < 0)
888 sbits += (srcwidthb * (abs(bmp->dib->dsBmih.biHeight) - 2 * startscan - 1));
889 srcwidthb = -srcwidthb;
894 case 16: /* 16 bpp dstDIB */
896 LPWORD dstbits = (LPWORD)dbits;
897 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
899 /* FIXME: BI_BITFIELDS not supported yet */
901 switch(bmp->dib->dsBm.bmBitsPixel) {
903 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
905 widthb = min(abs(srcwidthb), dstwidthb);
906 /* FIXME: BI_BITFIELDS not supported yet */
907 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
908 memcpy(dbits, sbits, widthb);
912 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
914 LPBYTE srcbits = sbits;
916 width = min(srcwidth, dstwidth);
917 for( y = 0; y < lines; y++) {
918 for( x = 0; x < width; x++, srcbits += 3)
919 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
920 (((WORD)srcbits[1] << 2) & gmask) |
921 (((WORD)srcbits[2] << 7) & rmask);
923 dstbits = (LPWORD)(dbits+=dstwidthb);
924 srcbits = (sbits += srcwidthb);
929 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
931 LPDWORD srcbits = (LPDWORD)sbits;
934 width = min(srcwidth, dstwidth);
935 for( y = 0; y < lines; y++) {
936 for( x = 0; x < width; x++ ) {
938 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
939 ((val >> 9) & rmask));
941 dstbits = (LPWORD)(dbits+=dstwidthb);
942 srcbits = (LPDWORD)(sbits+=srcwidthb);
947 default: /* ? bit bmp -> 16 bit DIB */
948 FIXME("15/16 bit DIB %d bit bitmap\n",
949 bmp->bitmap.bmBitsPixel);
955 case 24: /* 24 bpp dstDIB */
957 LPBYTE dstbits = dbits;
959 switch(bmp->dib->dsBm.bmBitsPixel) {
961 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
963 LPWORD srcbits = (LPWORD)sbits;
966 width = min(srcwidth, dstwidth);
967 /* FIXME: BI_BITFIELDS not supported yet */
968 for( y = 0; y < lines; y++) {
969 for( x = 0; x < width; x++ ) {
971 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
972 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
973 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
975 dstbits = dbits+=dstwidthb;
976 srcbits = (LPWORD)(sbits+=srcwidthb);
981 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
983 widthb = min(abs(srcwidthb), dstwidthb);
984 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
985 memcpy(dbits, sbits, widthb);
989 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
991 LPBYTE srcbits = sbits;
993 width = min(srcwidth, dstwidth);
994 for( y = 0; y < lines; y++) {
995 for( x = 0; x < width; x++, srcbits++ ) {
996 *dstbits++ = *srcbits++;
997 *dstbits++ = *srcbits++;
998 *dstbits++ = *srcbits++;
1000 dstbits = dbits+=dstwidthb;
1001 srcbits = sbits+=srcwidthb;
1006 default: /* ? bit bmp -> 24 bit DIB */
1007 FIXME("24 bit DIB %d bit bitmap\n",
1008 bmp->bitmap.bmBitsPixel);
1014 case 32: /* 32 bpp dstDIB */
1016 LPDWORD dstbits = (LPDWORD)dbits;
1018 /* FIXME: BI_BITFIELDS not supported yet */
1020 switch(bmp->dib->dsBm.bmBitsPixel) {
1021 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
1023 LPWORD srcbits = (LPWORD)sbits;
1026 width = min(srcwidth, dstwidth);
1027 /* FIXME: BI_BITFIELDS not supported yet */
1028 for( y = 0; y < lines; y++) {
1029 for( x = 0; x < width; x++ ) {
1030 val = (DWORD)*srcbits++;
1031 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
1032 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
1033 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
1035 dstbits=(LPDWORD)(dbits+=dstwidthb);
1036 srcbits=(LPWORD)(sbits+=srcwidthb);
1041 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1043 LPBYTE srcbits = sbits;
1045 width = min(srcwidth, dstwidth);
1046 for( y = 0; y < lines; y++) {
1047 for( x = 0; x < width; x++, srcbits+=3 )
1048 *dstbits++ = srcbits[0] |
1051 dstbits=(LPDWORD)(dbits+=dstwidthb);
1052 srcbits=(sbits+=srcwidthb);
1057 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
1059 widthb = min(abs(srcwidthb), dstwidthb);
1060 /* FIXME: BI_BITFIELDS not supported yet */
1061 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1062 memcpy(dbits, sbits, widthb);
1067 default: /* ? bit bmp -> 32 bit DIB */
1068 FIXME("32 bit DIB %d bit bitmap\n",
1069 bmp->bitmap.bmBitsPixel);
1075 default: /* ? bit DIB */
1076 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1080 /* Otherwise, get bits from the XImage */
1083 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1086 if (bmp->funcs && bmp->funcs->pGetDIBits)
1087 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1088 lines, bits, info, coloruse );
1090 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1094 else lines = abs(height);
1096 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1097 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1101 /* FIXME: biSizeImage should be calculated according to the selected
1102 compression algorithm if biCompression != BI_RGB */
1103 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1104 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1106 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1109 release_dc_ptr( dc );
1110 GDI_ReleaseObj( hbitmap );
1115 /***********************************************************************
1116 * CreateDIBitmap (GDI32.@)
1118 * Creates a DDB (device dependent bitmap) from a DIB.
1119 * The DDB will have the same color depth as the reference DC.
1121 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1122 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1132 if (!header) return 0;
1134 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1138 TRACE("Bitmap has a negative width\n");
1142 /* Top-down DIBs have a negative height */
1143 if (height < 0) height = -height;
1145 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1146 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1149 handle = CreateBitmap( width, height, 1, 1, NULL );
1151 handle = CreateCompatibleBitmap( hdc, width, height );
1155 if (init & CBM_INIT)
1157 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1159 DeleteObject( handle );
1164 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1166 if (!BITMAP_SetOwnerDC( handle, dc ))
1168 DeleteObject( handle );
1171 release_dc_ptr( dc );
1178 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1179 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1181 RGBQUAD *colorTable;
1182 unsigned int colors, i;
1183 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1187 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1191 colors = info->bmiHeader.biClrUsed;
1192 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1196 ERR("called with >256 colors!\n");
1200 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1202 if(coloruse == DIB_RGB_COLORS)
1206 /* Convert RGBTRIPLEs to RGBQUADs */
1207 for (i=0; i < colors; i++)
1209 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1210 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1211 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1212 colorTable[i].rgbReserved = 0;
1217 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1222 PALETTEENTRY entries[256];
1223 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1224 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1226 for (i = 0; i < colors; i++, index++)
1228 PALETTEENTRY *entry = &entries[*index % count];
1229 colorTable[i].rgbRed = entry->peRed;
1230 colorTable[i].rgbGreen = entry->peGreen;
1231 colorTable[i].rgbBlue = entry->peBlue;
1232 colorTable[i].rgbReserved = 0;
1235 bmp->color_table = colorTable;
1236 bmp->nb_colors = colors;
1239 /***********************************************************************
1240 * CreateDIBSection (GDI32.@)
1242 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1243 VOID **bits, HANDLE section, DWORD offset)
1247 BOOL bDesktopDC = FALSE;
1253 DWORD compression, sizeImage;
1254 void *mapBits = NULL;
1257 if(bits) *bits = NULL;
1261 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1262 &planes, &bpp, &compression, &sizeImage )) == -1))
1269 if (compression == BI_BITFIELDS) break;
1275 if (compression == BI_RGB) break;
1278 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1282 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1284 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1285 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1287 dib->dsBm.bmType = 0;
1288 dib->dsBm.bmWidth = width;
1289 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1290 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1291 dib->dsBm.bmPlanes = planes;
1292 dib->dsBm.bmBitsPixel = bpp;
1293 dib->dsBm.bmBits = NULL;
1295 if (!bitmap_type) /* core header */
1297 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1298 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1299 dib->dsBmih.biWidth = width;
1300 dib->dsBmih.biHeight = height;
1301 dib->dsBmih.biPlanes = planes;
1302 dib->dsBmih.biBitCount = bpp;
1303 dib->dsBmih.biCompression = compression;
1304 dib->dsBmih.biXPelsPerMeter = 0;
1305 dib->dsBmih.biYPelsPerMeter = 0;
1306 dib->dsBmih.biClrUsed = 0;
1307 dib->dsBmih.biClrImportant = 0;
1311 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1312 dib->dsBmih = bmi->bmiHeader;
1313 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1316 /* set number of entries in bmi.bmiColors table */
1318 dib->dsBmih.biClrUsed = 1 << bpp;
1320 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1322 /* set dsBitfields values */
1323 if (usage == DIB_PAL_COLORS || bpp <= 8)
1325 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1331 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1332 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1333 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1337 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1338 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1339 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1343 /* get storage location for DIB bits */
1347 SYSTEM_INFO SystemInfo;
1351 GetSystemInfo( &SystemInfo );
1352 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1353 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1354 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1355 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1360 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1361 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1363 dib->dshSection = section;
1364 dib->dsOffset = offset;
1366 if (!dib->dsBm.bmBits)
1368 HeapFree( GetProcessHeap(), 0, dib );
1372 /* If the reference hdc is null, take the desktop dc */
1375 hdc = CreateCompatibleDC(0);
1379 if (!(dc = get_dc_ptr( hdc ))) goto error;
1381 /* create Device Dependent Bitmap and add DIB pointer */
1382 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1383 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1385 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1388 bmp->funcs = dc->funcs;
1389 /* create local copy of DIB palette */
1390 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1391 GDI_ReleaseObj( ret );
1393 if (dc->funcs->pCreateDIBSection)
1395 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1397 DeleteObject( ret );
1403 release_dc_ptr( dc );
1404 if (bDesktopDC) DeleteDC( hdc );
1405 if (ret && bits) *bits = dib->dsBm.bmBits;
1409 if (bDesktopDC) DeleteDC( hdc );
1410 if (section) UnmapViewOfFile( mapBits );
1411 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1412 HeapFree( GetProcessHeap(), 0, dib );