2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize),
32 or use the internal function DIB_GetBitmapInfo.
35 * The palettes are stored in different formats:
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
46 If biCompression is BI_BITFIELDS, the color masks are at the same position
47 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48 the new headers have structure members for the masks.
51 * You should never access the color table using the bmiColors member,
52 because the passed structure may have one of the extended headers
53 mentioned above. Use this to calculate the location:
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
60 Search for "Bitmap Structures" in MSDN
70 #include "gdi_private.h"
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
77 Some of the following helper functions are duplicated in
81 /***********************************************************************
82 * DIB_GetDIBWidthBytes
84 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
86 int DIB_GetDIBWidthBytes( int width, int depth )
92 case 1: words = (width + 31) / 32; break;
93 case 4: words = (width + 7) / 8; break;
94 case 8: words = (width + 3) / 4; break;
96 case 16: words = (width + 1) / 2; break;
97 case 24: words = (width * 3 + 3)/4; break;
100 WARN("(%d): Unsupported depth\n", depth );
108 /***********************************************************************
109 * DIB_GetDIBImageBytes
111 * Return the number of bytes used to hold the image in a DIB bitmap.
113 int DIB_GetDIBImageBytes( int width, int height, int depth )
115 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
119 /***********************************************************************
122 * Return the size of the bitmap info structure including color table.
124 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
128 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
130 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
131 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
132 return sizeof(BITMAPCOREHEADER) + colors *
133 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
135 else /* assume BITMAPINFOHEADER */
137 colors = info->bmiHeader.biClrUsed;
138 if (colors > 256) colors = 256;
139 if (!colors && (info->bmiHeader.biBitCount <= 8))
140 colors = 1 << info->bmiHeader.biBitCount;
141 return sizeof(BITMAPINFOHEADER) + colors *
142 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
147 /***********************************************************************
150 * Get the info from a bitmap header.
151 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
153 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
154 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
156 if (header->biSize == sizeof(BITMAPCOREHEADER))
158 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
159 *width = core->bcWidth;
160 *height = core->bcHeight;
161 *planes = core->bcPlanes;
162 *bpp = core->bcBitCount;
167 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
169 *width = header->biWidth;
170 *height = header->biHeight;
171 *planes = header->biPlanes;
172 *bpp = header->biBitCount;
173 *compr = header->biCompression;
174 *size = header->biSizeImage;
177 ERR("(%d): unknown/wrong size for header\n", header->biSize );
182 /***********************************************************************
183 * StretchDIBits (GDI32.@)
185 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
186 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
187 INT heightSrc, const void *bits,
188 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
195 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
197 if(dc->funcs->pStretchDIBits)
200 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
201 heightDst, xSrc, ySrc, widthSrc,
202 heightSrc, bits, info, wUsage, dwRop);
203 release_dc_ptr( dc );
205 else /* use StretchBlt */
212 BOOL fastpath = FALSE;
214 release_dc_ptr( dc );
216 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
218 ERR("Invalid bitmap\n");
224 ERR("Bitmap has a negative width\n");
228 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
230 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
231 widthDst == widthSrc && heightDst == heightSrc &&
232 info->bmiHeader.biCompression == BI_RGB &&
236 if ((bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC )))
238 if (bmp->bitmap.bmBitsPixel == bpp &&
239 bmp->bitmap.bmWidth == widthSrc &&
240 bmp->bitmap.bmHeight == heightSrc &&
241 bmp->bitmap.bmPlanes == planes)
243 GDI_ReleaseObj( hBitmap );
250 TRACE("using fast path\n");
251 heightSrc = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
255 /* slow path - need to use StretchBlt */
257 HPALETTE hpal = NULL;
260 hdcMem = CreateCompatibleDC( hdc );
261 hBitmap = CreateCompatibleBitmap(hdc, width, height);
262 hOldBitmap = SelectObject( hdcMem, hBitmap );
263 if(wUsage == DIB_PAL_COLORS)
265 hpal = GetCurrentObject(hdc, OBJ_PAL);
266 hpal = SelectPalette(hdcMem, hpal, FALSE);
269 if (info->bmiHeader.biCompression == BI_RLE4 ||
270 info->bmiHeader.biCompression == BI_RLE8) {
272 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
273 * contain all the rectangle described in bmiHeader, but only part of it.
274 * This mean that those undescribed pixels must be left untouched.
275 * So, we first copy on a memory bitmap the current content of the
276 * destination rectangle, blit the DIB bits on top of it - hence leaving
277 * the gaps untouched -, and blitting the rectangle back.
278 * This insure that gaps are untouched on the destination rectangle
279 * Not doing so leads to trashed images (the gaps contain what was on the
280 * memory bitmap => generally black or garbage)
281 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
282 * another speed vs correctness issue. Anyway, if speed is needed, then the
283 * pStretchDIBits function shall be implemented.
287 /* copy existing bitmap from destination dc */
288 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
289 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
293 heightSrc = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
295 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
296 left (negative biHeight) */
297 if (heightSrc) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
298 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
299 widthSrc, heightSrc, dwRop );
301 SelectPalette(hdcMem, hpal, FALSE);
302 SelectObject( hdcMem, hOldBitmap );
304 DeleteObject( hBitmap );
311 /******************************************************************************
312 * SetDIBits [GDI32.@]
314 * Sets pixels in a bitmap using colors from DIB.
317 * hdc [I] Handle to device context
318 * hbitmap [I] Handle to bitmap
319 * startscan [I] Starting scan line
320 * lines [I] Number of scan lines
321 * bits [I] Array of bitmap bits
322 * info [I] Address of structure with data
323 * coloruse [I] Type of color indexes to use
326 * Success: Number of scan lines copied
329 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
330 UINT lines, LPCVOID bits, const BITMAPINFO *info,
337 if (!(dc = get_dc_ptr( hdc )))
339 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
345 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
347 release_dc_ptr( dc );
351 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
356 if (bitmap->funcs != dc->funcs)
357 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
358 else if (dc->funcs->pSetDIBits)
359 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
360 bits, info, coloruse );
364 GDI_ReleaseObj( hbitmap );
365 release_dc_ptr( dc );
370 /***********************************************************************
371 * SetDIBitsToDevice (GDI32.@)
373 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
374 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
375 UINT lines, LPCVOID bits, const BITMAPINFO *info,
383 if (!(dc = get_dc_ptr( hdc ))) return 0;
385 if(dc->funcs->pSetDIBitsToDevice)
388 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
389 ySrc, startscan, lines, bits,
393 FIXME("unimplemented on hdc %p\n", hdc);
397 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, BITMAP_MAGIC )))
414 /* Check if currently selected bitmap is a DIB */
415 if (bitmap->color_table)
417 if (startpos < bitmap->nb_colors)
419 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
420 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
424 GDI_ReleaseObj( dc->hBitmap );
427 if (dc->funcs->pSetDIBColorTable)
428 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
430 release_dc_ptr( dc );
435 /***********************************************************************
436 * GetDIBColorTable (GDI32.@)
438 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
443 if (!(dc = get_dc_ptr( hdc ))) return 0;
445 if (dc->funcs->pGetDIBColorTable)
446 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
449 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
452 /* Check if currently selected bitmap is a DIB */
453 if (bitmap->color_table)
455 if (startpos < bitmap->nb_colors)
457 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
458 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
462 GDI_ReleaseObj( dc->hBitmap );
465 release_dc_ptr( dc );
469 /* FIXME the following two structs should be combined with __sysPalTemplate in
470 objects/color.c - this should happen after de-X11-ing both of these
472 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
475 static const RGBQUAD EGAColorsQuads[16] = {
476 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
477 { 0x00, 0x00, 0x00, 0x00 },
478 { 0x00, 0x00, 0x80, 0x00 },
479 { 0x00, 0x80, 0x00, 0x00 },
480 { 0x00, 0x80, 0x80, 0x00 },
481 { 0x80, 0x00, 0x00, 0x00 },
482 { 0x80, 0x00, 0x80, 0x00 },
483 { 0x80, 0x80, 0x00, 0x00 },
484 { 0x80, 0x80, 0x80, 0x00 },
485 { 0xc0, 0xc0, 0xc0, 0x00 },
486 { 0x00, 0x00, 0xff, 0x00 },
487 { 0x00, 0xff, 0x00, 0x00 },
488 { 0x00, 0xff, 0xff, 0x00 },
489 { 0xff, 0x00, 0x00, 0x00 },
490 { 0xff, 0x00, 0xff, 0x00 },
491 { 0xff, 0xff, 0x00, 0x00 },
492 { 0xff, 0xff, 0xff, 0x00 }
495 static const RGBTRIPLE EGAColorsTriples[16] = {
496 /* rgbBlue, rgbGreen, rgbRed */
497 { 0x00, 0x00, 0x00 },
498 { 0x00, 0x00, 0x80 },
499 { 0x00, 0x80, 0x00 },
500 { 0x00, 0x80, 0x80 },
501 { 0x80, 0x00, 0x00 },
502 { 0x80, 0x00, 0x80 },
503 { 0x80, 0x80, 0x00 },
504 { 0x80, 0x80, 0x80 },
505 { 0xc0, 0xc0, 0xc0 },
506 { 0x00, 0x00, 0xff },
507 { 0x00, 0xff, 0x00 },
508 { 0x00, 0xff, 0xff },
509 { 0xff, 0x00, 0x00 } ,
510 { 0xff, 0x00, 0xff },
511 { 0xff, 0xff, 0x00 },
515 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
516 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
517 { 0x00, 0x00, 0x00, 0x00 },
518 { 0x00, 0x00, 0x80, 0x00 },
519 { 0x00, 0x80, 0x00, 0x00 },
520 { 0x00, 0x80, 0x80, 0x00 },
521 { 0x80, 0x00, 0x00, 0x00 },
522 { 0x80, 0x00, 0x80, 0x00 },
523 { 0x80, 0x80, 0x00, 0x00 },
524 { 0xc0, 0xc0, 0xc0, 0x00 },
525 { 0xc0, 0xdc, 0xc0, 0x00 },
526 { 0xf0, 0xca, 0xa6, 0x00 },
527 { 0xf0, 0xfb, 0xff, 0x00 },
528 { 0xa4, 0xa0, 0xa0, 0x00 },
529 { 0x80, 0x80, 0x80, 0x00 },
530 { 0x00, 0x00, 0xf0, 0x00 },
531 { 0x00, 0xff, 0x00, 0x00 },
532 { 0x00, 0xff, 0xff, 0x00 },
533 { 0xff, 0x00, 0x00, 0x00 },
534 { 0xff, 0x00, 0xff, 0x00 },
535 { 0xff, 0xff, 0x00, 0x00 },
536 { 0xff, 0xff, 0xff, 0x00 }
539 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
540 /* rgbBlue, rgbGreen, rgbRed */
541 { 0x00, 0x00, 0x00 },
542 { 0x00, 0x00, 0x80 },
543 { 0x00, 0x80, 0x00 },
544 { 0x00, 0x80, 0x80 },
545 { 0x80, 0x00, 0x00 },
546 { 0x80, 0x00, 0x80 },
547 { 0x80, 0x80, 0x00 },
548 { 0xc0, 0xc0, 0xc0 },
549 { 0xc0, 0xdc, 0xc0 },
550 { 0xf0, 0xca, 0xa6 },
551 { 0xf0, 0xfb, 0xff },
552 { 0xa4, 0xa0, 0xa0 },
553 { 0x80, 0x80, 0x80 },
554 { 0x00, 0x00, 0xf0 },
555 { 0x00, 0xff, 0x00 },
556 { 0x00, 0xff, 0xff },
557 { 0xff, 0x00, 0x00 },
558 { 0xff, 0x00, 0xff },
559 { 0xff, 0xff, 0x00 },
564 /******************************************************************************
565 * GetDIBits [GDI32.@]
567 * Retrieves bits of bitmap and copies to buffer.
570 * Success: Number of scan lines copied from bitmap
573 INT WINAPI GetDIBits(
574 HDC hdc, /* [in] Handle to device context */
575 HBITMAP hbitmap, /* [in] Handle to bitmap */
576 UINT startscan, /* [in] First scan line to set in dest bitmap */
577 UINT lines, /* [in] Number of scan lines to copy */
578 LPVOID bits, /* [out] Address of array for bitmap bits */
579 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
580 UINT coloruse) /* [in] RGB or palette index */
592 RGBTRIPLE* rgbTriples;
597 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
598 if (bitmap_type == -1)
600 ERR("Invalid bitmap format\n");
603 core_header = (bitmap_type == 0);
604 if (!(dc = get_dc_ptr( hdc )))
606 SetLastError( ERROR_INVALID_PARAMETER );
610 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
612 release_dc_ptr( dc );
616 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
617 rgbTriples = (RGBTRIPLE *) colorPtr;
618 rgbQuads = (RGBQUAD *) colorPtr;
620 /* Transfer color info */
622 if (bpp <= 8 && bpp > 0)
624 if (!core_header) info->bmiHeader.biClrUsed = 0;
626 /* If the bitmap object already has a dib section at the
627 same color depth then get the color map from it */
628 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
629 if(coloruse == DIB_RGB_COLORS) {
630 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
634 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
635 RGBTRIPLE* index = rgbTriples;
637 for (i=0; i < colors; i++, index++)
639 index->rgbtRed = bmp->color_table[i].rgbRed;
640 index->rgbtGreen = bmp->color_table[i].rgbGreen;
641 index->rgbtBlue = bmp->color_table[i].rgbBlue;
646 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
647 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
651 WORD *index = colorPtr;
652 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
657 if(bpp >= bmp->bitmap.bmBitsPixel) {
658 /* Generate the color map from the selected palette */
659 PALETTEENTRY palEntry[256];
661 memset( palEntry, 0, sizeof(palEntry) );
662 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
664 release_dc_ptr( dc );
665 GDI_ReleaseObj( hbitmap );
668 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
669 if (coloruse == DIB_RGB_COLORS) {
672 rgbTriples[i].rgbtRed = palEntry[i].peRed;
673 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
674 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
678 rgbQuads[i].rgbRed = palEntry[i].peRed;
679 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
680 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
681 rgbQuads[i].rgbReserved = 0;
684 else ((WORD *)colorPtr)[i] = (WORD)i;
691 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
692 rgbTriples[0].rgbtBlue = 0;
693 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
694 rgbTriples[1].rgbtBlue = 0xff;
698 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
699 rgbQuads[0].rgbBlue = 0;
700 rgbQuads[0].rgbReserved = 0;
701 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
702 rgbQuads[1].rgbBlue = 0xff;
703 rgbQuads[1].rgbReserved = 0;
709 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
711 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
722 memcpy(rgbTriples, DefLogPaletteTriples,
723 10 * sizeof(RGBTRIPLE));
724 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
725 10 * sizeof(RGBTRIPLE));
726 color = rgbTriples + 10;
727 for(r = 0; r <= 5; r++) /* FIXME */
728 for(g = 0; g <= 5; g++)
729 for(b = 0; b <= 5; b++) {
730 color->rgbtRed = (r * 0xff) / 5;
731 color->rgbtGreen = (g * 0xff) / 5;
732 color->rgbtBlue = (b * 0xff) / 5;
741 memcpy(rgbQuads, DefLogPaletteQuads,
742 10 * sizeof(RGBQUAD));
743 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
744 10 * sizeof(RGBQUAD));
745 color = rgbQuads + 10;
746 for(r = 0; r <= 5; r++) /* FIXME */
747 for(g = 0; g <= 5; g++)
748 for(b = 0; b <= 5; b++) {
749 color->rgbRed = (r * 0xff) / 5;
750 color->rgbGreen = (g * 0xff) / 5;
751 color->rgbBlue = (b * 0xff) / 5;
752 color->rgbReserved = 0;
764 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
765 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
767 /*FIXME: Only RGB dibs supported for now */
768 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
769 unsigned int dstwidth = width;
770 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
771 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
772 unsigned int x, y, width, widthb;
774 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
776 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
777 dstwidthb = -dstwidthb;
783 case 16: /* 16 bpp dstDIB */
785 LPWORD dstbits = (LPWORD)dbits;
786 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
788 /* FIXME: BI_BITFIELDS not supported yet */
790 switch(bmp->dib->dsBm.bmBitsPixel) {
792 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
794 widthb = min(srcwidthb, abs(dstwidthb));
795 /* FIXME: BI_BITFIELDS not supported yet */
796 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
797 memcpy(dbits, sbits, widthb);
801 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
803 LPBYTE srcbits = sbits;
805 width = min(srcwidth, dstwidth);
806 for( y = 0; y < lines; y++) {
807 for( x = 0; x < width; x++, srcbits += 3)
808 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
809 (((WORD)srcbits[1] << 2) & gmask) |
810 (((WORD)srcbits[2] << 7) & rmask);
812 dstbits = (LPWORD)(dbits+=dstwidthb);
813 srcbits = (sbits += srcwidthb);
818 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
820 LPDWORD srcbits = (LPDWORD)sbits;
823 width = min(srcwidth, dstwidth);
824 for( y = 0; y < lines; y++) {
825 for( x = 0; x < width; x++ ) {
827 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
828 ((val >> 9) & rmask));
830 dstbits = (LPWORD)(dbits+=dstwidthb);
831 srcbits = (LPDWORD)(sbits+=srcwidthb);
836 default: /* ? bit bmp -> 16 bit DIB */
837 FIXME("15/16 bit DIB %d bit bitmap\n",
838 bmp->bitmap.bmBitsPixel);
844 case 24: /* 24 bpp dstDIB */
846 LPBYTE dstbits = dbits;
848 switch(bmp->dib->dsBm.bmBitsPixel) {
850 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
852 LPWORD srcbits = (LPWORD)sbits;
855 width = min(srcwidth, dstwidth);
856 /* FIXME: BI_BITFIELDS not supported yet */
857 for( y = 0; y < lines; y++) {
858 for( x = 0; x < width; x++ ) {
860 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
861 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
862 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
864 dstbits = dbits+=dstwidthb;
865 srcbits = (LPWORD)(sbits+=srcwidthb);
870 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
872 widthb = min(srcwidthb, abs(dstwidthb));
873 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
874 memcpy(dbits, sbits, widthb);
878 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
880 LPBYTE srcbits = sbits;
882 width = min(srcwidth, dstwidth);
883 for( y = 0; y < lines; y++) {
884 for( x = 0; x < width; x++, srcbits++ ) {
885 *dstbits++ = *srcbits++;
886 *dstbits++ = *srcbits++;
887 *dstbits++ = *srcbits++;
889 dstbits = dbits+=dstwidthb;
890 srcbits = sbits+=srcwidthb;
895 default: /* ? bit bmp -> 24 bit DIB */
896 FIXME("24 bit DIB %d bit bitmap\n",
897 bmp->bitmap.bmBitsPixel);
903 case 32: /* 32 bpp dstDIB */
905 LPDWORD dstbits = (LPDWORD)dbits;
907 /* FIXME: BI_BITFIELDS not supported yet */
909 switch(bmp->dib->dsBm.bmBitsPixel) {
910 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
912 LPWORD srcbits = (LPWORD)sbits;
915 width = min(srcwidth, dstwidth);
916 /* FIXME: BI_BITFIELDS not supported yet */
917 for( y = 0; y < lines; y++) {
918 for( x = 0; x < width; x++ ) {
919 val = (DWORD)*srcbits++;
920 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
921 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
922 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
924 dstbits=(LPDWORD)(dbits+=dstwidthb);
925 srcbits=(LPWORD)(sbits+=srcwidthb);
930 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
932 LPBYTE srcbits = sbits;
934 width = min(srcwidth, dstwidth);
935 for( y = 0; y < lines; y++) {
936 for( x = 0; x < width; x++, srcbits+=3 )
937 *dstbits++ = srcbits[0] |
940 dstbits=(LPDWORD)(dbits+=dstwidthb);
941 srcbits=(sbits+=srcwidthb);
946 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
948 widthb = min(srcwidthb, abs(dstwidthb));
949 /* FIXME: BI_BITFIELDS not supported yet */
950 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
951 memcpy(dbits, sbits, widthb);
956 default: /* ? bit bmp -> 32 bit DIB */
957 FIXME("32 bit DIB %d bit bitmap\n",
958 bmp->bitmap.bmBitsPixel);
964 default: /* ? bit DIB */
965 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
969 /* Otherwise, get bits from the XImage */
972 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
975 if (bmp->funcs && bmp->funcs->pGetDIBits)
976 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
977 lines, bits, info, coloruse );
979 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
985 /* fill in struct members */
991 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
992 coreheader->bcWidth = bmp->bitmap.bmWidth;
993 coreheader->bcHeight = bmp->bitmap.bmHeight;
994 coreheader->bcPlanes = 1;
995 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
999 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
1000 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
1001 info->bmiHeader.biPlanes = 1;
1002 info->bmiHeader.biSizeImage =
1003 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
1004 bmp->bitmap.bmHeight,
1005 bmp->bitmap.bmBitsPixel );
1006 switch(bmp->bitmap.bmBitsPixel)
1009 info->bmiHeader.biBitCount = 16;
1010 info->bmiHeader.biCompression = BI_RGB;
1016 /* Add color only when bits is given, as per MSDN */
1017 ((PDWORD)info->bmiColors)[0] = 0xf800;
1018 ((PDWORD)info->bmiColors)[1] = 0x07e0;
1019 ((PDWORD)info->bmiColors)[2] = 0x001f;
1021 info->bmiHeader.biBitCount = 16;
1022 info->bmiHeader.biCompression = BI_BITFIELDS;
1026 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1027 info->bmiHeader.biCompression = BI_RGB;
1030 info->bmiHeader.biXPelsPerMeter = 0;
1031 info->bmiHeader.biYPelsPerMeter = 0;
1032 info->bmiHeader.biClrUsed = 0;
1033 info->bmiHeader.biClrImportant = 0;
1035 /* Windows 2000 doesn't touch the additional struct members if
1036 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
1038 lines = abs(bmp->bitmap.bmHeight);
1042 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1043 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1047 /* FIXME: biSizeImage should be calculated according to the selected
1048 compression algorithm if biCompression != BI_RGB */
1049 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1051 lines = abs(height);
1057 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1059 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1061 release_dc_ptr( dc );
1062 GDI_ReleaseObj( hbitmap );
1067 /***********************************************************************
1068 * CreateDIBitmap (GDI32.@)
1070 * Creates a DDB (device dependent bitmap) from a DIB.
1071 * The DDB will have the same color depth as the reference DC.
1073 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1074 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1084 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1088 TRACE("Bitmap has a negative width\n");
1092 /* Top-down DIBs have a negative height */
1093 if (height < 0) height = -height;
1095 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1096 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1099 handle = CreateBitmap( width, height, 1, 1, NULL );
1101 handle = CreateCompatibleBitmap( hdc, width, height );
1105 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1107 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
1109 if (!BITMAP_SetOwnerDC( handle, dc ))
1111 DeleteObject( handle );
1114 release_dc_ptr( dc );
1121 /***********************************************************************
1122 * CreateDIBSection (GDI.489)
1124 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1125 SEGPTR *bits16, HANDLE section, DWORD offset)
1130 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1133 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1134 if (bmp && bmp->dib && bits32)
1136 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1144 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1146 height = height >= 0 ? height : -height;
1147 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1149 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1151 /* calculate number of sel's needed for size with 64K steps */
1152 count = (size + 0xffff) / 0x10000;
1153 sel = AllocSelectorArray16(count);
1155 for (i = 0; i < count; i++)
1157 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1158 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1161 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1162 if (bits16) *bits16 = bmp->segptr_bits;
1164 if (bmp) GDI_ReleaseObj( hbitmap );
1166 return HBITMAP_16(hbitmap);
1169 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1170 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1172 RGBQUAD *colorTable;
1173 unsigned int colors;
1175 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1179 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1183 colors = info->bmiHeader.biClrUsed;
1184 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1188 ERR("called with >256 colors!\n");
1192 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1194 if(coloruse == DIB_RGB_COLORS)
1198 /* Convert RGBTRIPLEs to RGBQUADs */
1199 for (i=0; i < colors; i++)
1201 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1202 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1203 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1204 colorTable[i].rgbReserved = 0;
1209 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1214 PALETTEENTRY entries[256];
1215 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1216 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1218 for (i = 0; i < colors; i++, index++)
1220 PALETTEENTRY *entry = &entries[*index % count];
1221 colorTable[i].rgbRed = entry->peRed;
1222 colorTable[i].rgbGreen = entry->peGreen;
1223 colorTable[i].rgbBlue = entry->peBlue;
1224 colorTable[i].rgbReserved = 0;
1227 bmp->color_table = colorTable;
1228 bmp->nb_colors = colors;
1231 /***********************************************************************
1232 * CreateDIBSection (GDI32.@)
1234 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1235 VOID **bits, HANDLE section, DWORD offset)
1239 BOOL bDesktopDC = FALSE;
1245 DWORD compression, sizeImage;
1246 void *mapBits = NULL;
1248 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1249 &planes, &bpp, &compression, &sizeImage )) == -1))
1252 if (compression != BI_RGB && compression != BI_BITFIELDS)
1254 TRACE("can't create a compressed (%u) dibsection\n", compression);
1258 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1260 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1261 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1263 dib->dsBm.bmType = 0;
1264 dib->dsBm.bmWidth = width;
1265 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1266 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1267 dib->dsBm.bmPlanes = planes;
1268 dib->dsBm.bmBitsPixel = bpp;
1269 dib->dsBm.bmBits = NULL;
1271 if (!bitmap_type) /* core header */
1273 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1274 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1275 dib->dsBmih.biWidth = width;
1276 dib->dsBmih.biHeight = height;
1277 dib->dsBmih.biPlanes = planes;
1278 dib->dsBmih.biBitCount = bpp;
1279 dib->dsBmih.biCompression = compression;
1280 dib->dsBmih.biXPelsPerMeter = 0;
1281 dib->dsBmih.biYPelsPerMeter = 0;
1282 dib->dsBmih.biClrUsed = 0;
1283 dib->dsBmih.biClrImportant = 0;
1287 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1288 dib->dsBmih = bmi->bmiHeader;
1289 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1292 /* set number of entries in bmi.bmiColors table */
1294 dib->dsBmih.biClrUsed = 1 << bpp;
1296 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1298 /* set dsBitfields values */
1299 if (usage == DIB_PAL_COLORS || bpp <= 8)
1301 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1307 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1308 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1309 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1313 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1314 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1315 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1319 /* get storage location for DIB bits */
1323 SYSTEM_INFO SystemInfo;
1327 GetSystemInfo( &SystemInfo );
1328 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1329 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1330 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1331 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1336 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1337 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1339 dib->dshSection = section;
1340 dib->dsOffset = offset;
1342 if (!dib->dsBm.bmBits)
1344 HeapFree( GetProcessHeap(), 0, dib );
1348 /* If the reference hdc is null, take the desktop dc */
1351 hdc = CreateCompatibleDC(0);
1355 if (!(dc = get_dc_ptr( hdc ))) goto error;
1357 /* create Device Dependent Bitmap and add DIB pointer */
1358 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1359 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1361 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1364 bmp->funcs = dc->funcs;
1365 /* create local copy of DIB palette */
1366 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1367 GDI_ReleaseObj( ret );
1369 if (dc->funcs->pCreateDIBSection)
1371 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1373 DeleteObject( ret );
1379 release_dc_ptr( dc );
1380 if (bDesktopDC) DeleteDC( hdc );
1381 if (ret && bits) *bits = dib->dsBm.bmBits;
1385 if (bDesktopDC) DeleteDC( hdc );
1386 if (section) UnmapViewOfFile( mapBits );
1387 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1388 HeapFree( GetProcessHeap(), 0, dib );