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 );
181 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
182 INT CDECL nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
183 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
184 const BITMAPINFO *info, UINT coloruse, DWORD rop )
186 DC *dc = get_nulldrv_dc( dev );
194 /* make sure we have a real implementation for StretchBlt and SetDIBits */
195 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pSetDIBits ) == dev)
198 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
201 if (width < 0) return 0;
203 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
204 info->bmiHeader.biCompression == BI_RGB)
206 /* Windows appears to have a fast case optimization
207 * that uses the wrong origin for top-down DIBs */
208 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
210 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
213 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
214 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
215 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
216 bm.bmBitsPixel == bpp && bm.bmPlanes == planes)
219 return SetDIBits( dev->hdc, hBitmap, 0, height, bits, info, coloruse );
224 hdcMem = CreateCompatibleDC( dev->hdc );
225 hBitmap = CreateCompatibleBitmap( dev->hdc, width, height );
226 SelectObject( hdcMem, hBitmap );
227 if (coloruse == DIB_PAL_COLORS)
228 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
230 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
232 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
233 * contain all the rectangle described in bmiHeader, but only part of it.
234 * This mean that those undescribed pixels must be left untouched.
235 * So, we first copy on a memory bitmap the current content of the
236 * destination rectangle, blit the DIB bits on top of it - hence leaving
237 * the gaps untouched -, and blitting the rectangle back.
238 * This insure that gaps are untouched on the destination rectangle
240 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
241 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
243 ret = SetDIBits( hdcMem, hBitmap, 0, height, bits, info, coloruse );
244 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
245 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
247 DeleteObject( hBitmap );
251 /***********************************************************************
252 * StretchDIBits (GDI32.@)
254 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
255 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
256 const BITMAPINFO *info, UINT coloruse, DWORD rop )
261 if (!bits || !info) return 0;
263 if ((dc = get_dc_ptr( hdc )))
265 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
267 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
268 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
269 release_dc_ptr( dc );
275 /******************************************************************************
276 * SetDIBits [GDI32.@]
278 * Sets pixels in a bitmap using colors from DIB.
281 * hdc [I] Handle to device context
282 * hbitmap [I] Handle to bitmap
283 * startscan [I] Starting scan line
284 * lines [I] Number of scan lines
285 * bits [I] Array of bitmap bits
286 * info [I] Address of structure with data
287 * coloruse [I] Type of color indexes to use
290 * Success: Number of scan lines copied
293 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
294 UINT lines, LPCVOID bits, const BITMAPINFO *info,
297 DC *dc = get_dc_ptr( hdc );
298 BOOL delete_hdc = FALSE;
303 if (coloruse == DIB_RGB_COLORS && !dc)
305 hdc = CreateCompatibleDC(0);
306 dc = get_dc_ptr( hdc );
314 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
316 release_dc_ptr( dc );
317 if (delete_hdc) DeleteDC(hdc);
321 physdev = GET_DC_PHYSDEV( dc, pSetDIBits );
322 if (BITMAP_SetOwnerDC( hbitmap, physdev ))
323 result = physdev->funcs->pSetDIBits( physdev, hbitmap, startscan, lines, bits, info, coloruse );
325 GDI_ReleaseObj( hbitmap );
326 release_dc_ptr( dc );
327 if (delete_hdc) DeleteDC(hdc);
332 /***********************************************************************
333 * SetDIBitsToDevice (GDI32.@)
335 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
336 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
337 UINT lines, LPCVOID bits, const BITMAPINFO *info,
345 if ((dc = get_dc_ptr( hdc )))
347 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
349 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
350 ySrc, startscan, lines, bits, info, coloruse );
351 release_dc_ptr( dc );
356 /***********************************************************************
357 * SetDIBColorTable (GDI32.@)
359 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
365 if (!(dc = get_dc_ptr( hdc ))) return 0;
367 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
369 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
371 /* Check if currently selected bitmap is a DIB */
372 if (bitmap->color_table)
374 if (startpos < bitmap->nb_colors)
376 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
377 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
381 GDI_ReleaseObj( dc->hBitmap );
382 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
384 release_dc_ptr( dc );
389 /***********************************************************************
390 * GetDIBColorTable (GDI32.@)
392 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
398 if (!(dc = get_dc_ptr( hdc ))) return 0;
400 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
402 /* Check if currently selected bitmap is a DIB */
403 if (bitmap->color_table)
405 if (startpos < bitmap->nb_colors)
407 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
408 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
412 GDI_ReleaseObj( dc->hBitmap );
414 release_dc_ptr( dc );
418 /* FIXME the following two structs should be combined with __sysPalTemplate in
419 objects/color.c - this should happen after de-X11-ing both of these
421 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
424 static const RGBQUAD EGAColorsQuads[16] = {
425 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
426 { 0x00, 0x00, 0x00, 0x00 },
427 { 0x00, 0x00, 0x80, 0x00 },
428 { 0x00, 0x80, 0x00, 0x00 },
429 { 0x00, 0x80, 0x80, 0x00 },
430 { 0x80, 0x00, 0x00, 0x00 },
431 { 0x80, 0x00, 0x80, 0x00 },
432 { 0x80, 0x80, 0x00, 0x00 },
433 { 0x80, 0x80, 0x80, 0x00 },
434 { 0xc0, 0xc0, 0xc0, 0x00 },
435 { 0x00, 0x00, 0xff, 0x00 },
436 { 0x00, 0xff, 0x00, 0x00 },
437 { 0x00, 0xff, 0xff, 0x00 },
438 { 0xff, 0x00, 0x00, 0x00 },
439 { 0xff, 0x00, 0xff, 0x00 },
440 { 0xff, 0xff, 0x00, 0x00 },
441 { 0xff, 0xff, 0xff, 0x00 }
444 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
445 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
446 { 0x00, 0x00, 0x00, 0x00 },
447 { 0x00, 0x00, 0x80, 0x00 },
448 { 0x00, 0x80, 0x00, 0x00 },
449 { 0x00, 0x80, 0x80, 0x00 },
450 { 0x80, 0x00, 0x00, 0x00 },
451 { 0x80, 0x00, 0x80, 0x00 },
452 { 0x80, 0x80, 0x00, 0x00 },
453 { 0xc0, 0xc0, 0xc0, 0x00 },
454 { 0xc0, 0xdc, 0xc0, 0x00 },
455 { 0xf0, 0xca, 0xa6, 0x00 },
456 { 0xf0, 0xfb, 0xff, 0x00 },
457 { 0xa4, 0xa0, 0xa0, 0x00 },
458 { 0x80, 0x80, 0x80, 0x00 },
459 { 0x00, 0x00, 0xff, 0x00 },
460 { 0x00, 0xff, 0x00, 0x00 },
461 { 0x00, 0xff, 0xff, 0x00 },
462 { 0xff, 0x00, 0x00, 0x00 },
463 { 0xff, 0x00, 0xff, 0x00 },
464 { 0xff, 0xff, 0x00, 0x00 },
465 { 0xff, 0xff, 0xff, 0x00 }
468 /******************************************************************************
469 * GetDIBits [GDI32.@]
471 * Retrieves bits of bitmap and copies to buffer.
474 * Success: Number of scan lines copied from bitmap
477 INT WINAPI GetDIBits(
478 HDC hdc, /* [in] Handle to device context */
479 HBITMAP hbitmap, /* [in] Handle to bitmap */
480 UINT startscan, /* [in] First scan line to set in dest bitmap */
481 UINT lines, /* [in] Number of scan lines to copy */
482 LPVOID bits, /* [out] Address of array for bitmap bits */
483 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
484 UINT coloruse) /* [in] RGB or palette index */
496 RGBQUAD quad_buf[256];
497 RGBQUAD* rgbQuads = quad_buf;
501 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
502 if (bitmap_type == -1)
504 ERR("Invalid bitmap format\n");
507 core_header = (bitmap_type == 0);
508 if (!(dc = get_dc_ptr( hdc )))
510 SetLastError( ERROR_INVALID_PARAMETER );
514 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
516 release_dc_ptr( dc );
520 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
521 if(!core_header) rgbQuads = colorPtr;
523 /* Transfer color info */
527 case 0: /* query bitmap info only */
530 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
531 coreheader->bcWidth = bmp->bitmap.bmWidth;
532 coreheader->bcHeight = bmp->bitmap.bmHeight;
533 coreheader->bcPlanes = 1;
534 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
538 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
539 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
540 info->bmiHeader.biPlanes = 1;
541 info->bmiHeader.biSizeImage =
542 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
543 bmp->bitmap.bmHeight,
544 bmp->bitmap.bmBitsPixel );
547 info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
548 switch (bmp->dib->dsBm.bmBitsPixel)
552 info->bmiHeader.biCompression = BI_BITFIELDS;
555 info->bmiHeader.biCompression = BI_RGB;
561 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
562 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
564 info->bmiHeader.biXPelsPerMeter = 0;
565 info->bmiHeader.biYPelsPerMeter = 0;
566 info->bmiHeader.biClrUsed = 0;
567 info->bmiHeader.biClrImportant = 0;
569 /* Windows 2000 doesn't touch the additional struct members if
570 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
572 lines = abs(bmp->bitmap.bmHeight);
579 unsigned int colors = 1 << bpp;
581 if (!core_header) info->bmiHeader.biClrUsed = 0;
583 if (coloruse == DIB_PAL_COLORS)
585 WORD *index = colorPtr;
586 for (i = 0; i < colors; i++, index++)
592 /* If the bitmap object already has a dib section at the
593 same color depth then get the color map from it */
595 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp)
597 colors = min( colors, bmp->nb_colors );
599 if (!core_header && colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
601 memcpy(rgbQuads, bmp->color_table, colors * sizeof(RGBQUAD));
604 /* For color DDBs in native depth (mono DDBs always have a black/white palette):
605 Generate the color map from the selected palette */
607 else if (bpp > 1 && bpp == bmp->bitmap.bmBitsPixel)
609 PALETTEENTRY palEntry[256];
611 memset( palEntry, 0, sizeof(palEntry) );
612 if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
614 release_dc_ptr( dc );
615 GDI_ReleaseObj( hbitmap );
618 for (i = 0; i < colors; i++)
620 rgbQuads[i].rgbRed = palEntry[i].peRed;
621 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
622 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
623 rgbQuads[i].rgbReserved = 0;
631 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
632 rgbQuads[0].rgbReserved = 0;
633 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
634 rgbQuads[1].rgbReserved = 0;
638 memcpy(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
642 memcpy(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
643 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
644 for (i = 10; i < 246; i++)
646 rgbQuads[i].rgbRed = (i & 0x07) << 5;
647 rgbQuads[i].rgbGreen = (i & 0x38) << 2;
648 rgbQuads[i].rgbBlue = i & 0xc0;
649 rgbQuads[i].rgbReserved = 0;
656 RGBTRIPLE *triple = (RGBTRIPLE *)colorPtr;
657 for (i = 0; i < colors; i++)
659 triple[i].rgbtRed = rgbQuads[i].rgbRed;
660 triple[i].rgbtGreen = rgbQuads[i].rgbGreen;
661 triple[i].rgbtBlue = rgbQuads[i].rgbBlue;
669 if (info->bmiHeader.biCompression == BI_BITFIELDS)
671 ((PDWORD)info->bmiColors)[0] = 0x7c00;
672 ((PDWORD)info->bmiColors)[1] = 0x03e0;
673 ((PDWORD)info->bmiColors)[2] = 0x001f;
678 if (info->bmiHeader.biCompression == BI_BITFIELDS)
682 if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS)
683 memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
686 ((PDWORD)info->bmiColors)[0] = 0x7c00;
687 ((PDWORD)info->bmiColors)[1] = 0x03e0;
688 ((PDWORD)info->bmiColors)[2] = 0x001f;
693 ((PDWORD)info->bmiColors)[0] = 0xf800;
694 ((PDWORD)info->bmiColors)[1] = 0x07e0;
695 ((PDWORD)info->bmiColors)[2] = 0x001f;
702 if (info->bmiHeader.biCompression == BI_BITFIELDS)
704 if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS)
705 memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
708 ((PDWORD)info->bmiColors)[0] = 0xff0000;
709 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
710 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
718 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
719 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
721 /*FIXME: Only RGB dibs supported for now */
722 unsigned int srcwidth = bmp->dib->dsBm.bmWidth;
723 int srcwidthb = bmp->dib->dsBm.bmWidthBytes;
724 unsigned int dstwidth = width;
725 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
726 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
727 unsigned int x, y, width, widthb;
730 * If copying from a top-down source bitmap, move the source
731 * pointer to the end of the source bitmap and negate the width
732 * so that we copy the bits upside-down.
734 if (bmp->dib->dsBmih.biHeight < 0)
736 sbits += (srcwidthb * (int)(abs(bmp->dib->dsBmih.biHeight) - 2 * startscan - 1));
737 srcwidthb = -srcwidthb;
739 /*Same for the destination.*/
742 dbits = (LPBYTE)bits + (dstwidthb * (lines - 1));
743 dstwidthb = -dstwidthb;
748 case 16: /* 16 bpp dstDIB */
750 LPWORD dstbits = (LPWORD)dbits;
751 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
753 /* FIXME: BI_BITFIELDS not supported yet */
755 switch(bmp->dib->dsBm.bmBitsPixel) {
757 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
759 widthb = min(abs(srcwidthb), abs(dstwidthb));
760 /* FIXME: BI_BITFIELDS not supported yet */
761 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
762 memcpy(dbits, sbits, widthb);
766 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
768 LPBYTE srcbits = sbits;
770 width = min(srcwidth, dstwidth);
771 for( y = 0; y < lines; y++) {
772 for( x = 0; x < width; x++, srcbits += 3)
773 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
774 (((WORD)srcbits[1] << 2) & gmask) |
775 (((WORD)srcbits[2] << 7) & rmask);
777 dstbits = (LPWORD)(dbits+=dstwidthb);
778 srcbits = (sbits += srcwidthb);
783 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
785 LPDWORD srcbits = (LPDWORD)sbits;
788 width = min(srcwidth, dstwidth);
789 for( y = 0; y < lines; y++) {
790 for( x = 0; x < width; x++ ) {
792 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
793 ((val >> 9) & rmask));
795 dstbits = (LPWORD)(dbits+=dstwidthb);
796 srcbits = (LPDWORD)(sbits+=srcwidthb);
801 default: /* ? bit bmp -> 16 bit DIB */
802 FIXME("15/16 bit DIB %d bit bitmap\n",
803 bmp->bitmap.bmBitsPixel);
809 case 24: /* 24 bpp dstDIB */
811 LPBYTE dstbits = dbits;
813 switch(bmp->dib->dsBm.bmBitsPixel) {
815 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
817 LPWORD srcbits = (LPWORD)sbits;
820 width = min(srcwidth, dstwidth);
821 /* FIXME: BI_BITFIELDS not supported yet */
822 for( y = 0; y < lines; y++) {
823 for( x = 0; x < width; x++ ) {
825 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
826 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
827 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
829 dstbits = dbits+=dstwidthb;
830 srcbits = (LPWORD)(sbits+=srcwidthb);
835 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
837 widthb = min(abs(srcwidthb), abs(dstwidthb));
838 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
839 memcpy(dbits, sbits, widthb);
843 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
845 LPBYTE srcbits = sbits;
847 width = min(srcwidth, dstwidth);
848 for( y = 0; y < lines; y++) {
849 for( x = 0; x < width; x++, srcbits++ ) {
850 *dstbits++ = *srcbits++;
851 *dstbits++ = *srcbits++;
852 *dstbits++ = *srcbits++;
854 dstbits = dbits+=dstwidthb;
855 srcbits = sbits+=srcwidthb;
860 default: /* ? bit bmp -> 24 bit DIB */
861 FIXME("24 bit DIB %d bit bitmap\n",
862 bmp->bitmap.bmBitsPixel);
868 case 32: /* 32 bpp dstDIB */
870 LPDWORD dstbits = (LPDWORD)dbits;
872 /* FIXME: BI_BITFIELDS not supported yet */
874 switch(bmp->dib->dsBm.bmBitsPixel) {
875 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
877 LPWORD srcbits = (LPWORD)sbits;
880 width = min(srcwidth, dstwidth);
881 /* FIXME: BI_BITFIELDS not supported yet */
882 for( y = 0; y < lines; y++) {
883 for( x = 0; x < width; x++ ) {
884 val = (DWORD)*srcbits++;
885 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
886 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
887 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
889 dstbits=(LPDWORD)(dbits+=dstwidthb);
890 srcbits=(LPWORD)(sbits+=srcwidthb);
895 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
897 LPBYTE srcbits = sbits;
899 width = min(srcwidth, dstwidth);
900 for( y = 0; y < lines; y++) {
901 for( x = 0; x < width; x++, srcbits+=3 )
902 *dstbits++ = srcbits[0] |
905 dstbits=(LPDWORD)(dbits+=dstwidthb);
906 srcbits=(sbits+=srcwidthb);
911 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
913 widthb = min(abs(srcwidthb), abs(dstwidthb));
914 /* FIXME: BI_BITFIELDS not supported yet */
915 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
916 memcpy(dbits, sbits, widthb);
921 default: /* ? bit bmp -> 32 bit DIB */
922 FIXME("32 bit DIB %d bit bitmap\n",
923 bmp->bitmap.bmBitsPixel);
929 default: /* ? bit DIB */
930 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
934 /* Otherwise, get bits from the XImage */
937 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDIBits );
938 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
939 else lines = physdev->funcs->pGetDIBits( physdev, hbitmap, startscan,
940 lines, bits, info, coloruse );
943 else lines = abs(height);
945 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
946 if bits == NULL and bpp != 0, only biSizeImage and the color table are
950 /* FIXME: biSizeImage should be calculated according to the selected
951 compression algorithm if biCompression != BI_RGB */
952 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
953 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
955 TRACE("biWidth = %d, biHeight = %d\n", width, height);
958 release_dc_ptr( dc );
959 GDI_ReleaseObj( hbitmap );
964 /***********************************************************************
965 * CreateDIBitmap (GDI32.@)
967 * Creates a DDB (device dependent bitmap) from a DIB.
968 * The DDB will have the same color depth as the reference DC.
970 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
971 DWORD init, LPCVOID bits, const BITMAPINFO *data,
980 if (!header) return 0;
982 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
986 TRACE("Bitmap has a negative width\n");
990 /* Top-down DIBs have a negative height */
991 if (height < 0) height = -height;
993 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
994 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
997 handle = CreateBitmap( width, height, 1, 1, NULL );
999 handle = CreateCompatibleBitmap( hdc, width, height );
1003 if (init & CBM_INIT)
1005 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1007 DeleteObject( handle );
1016 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1017 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1019 RGBQUAD *colorTable;
1020 unsigned int colors, i;
1021 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1025 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1029 colors = info->bmiHeader.biClrUsed;
1030 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1034 ERR("called with >256 colors!\n");
1038 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1040 if(coloruse == DIB_RGB_COLORS)
1044 /* Convert RGBTRIPLEs to RGBQUADs */
1045 for (i=0; i < colors; i++)
1047 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1048 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1049 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1050 colorTable[i].rgbReserved = 0;
1055 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1060 PALETTEENTRY entries[256];
1061 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1062 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1064 for (i = 0; i < colors; i++, index++)
1066 PALETTEENTRY *entry = &entries[*index % count];
1067 colorTable[i].rgbRed = entry->peRed;
1068 colorTable[i].rgbGreen = entry->peGreen;
1069 colorTable[i].rgbBlue = entry->peBlue;
1070 colorTable[i].rgbReserved = 0;
1073 bmp->color_table = colorTable;
1074 bmp->nb_colors = colors;
1077 /***********************************************************************
1078 * CreateDIBSection (GDI32.@)
1080 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1081 VOID **bits, HANDLE section, DWORD offset)
1085 BOOL bDesktopDC = FALSE;
1091 DWORD compression, sizeImage;
1092 void *mapBits = NULL;
1095 if(bits) *bits = NULL;
1099 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1100 &planes, &bpp, &compression, &sizeImage )) == -1))
1107 if (compression == BI_BITFIELDS) break;
1113 if (compression == BI_RGB) break;
1116 WARN( "invalid %u bpp compression %u\n", bpp, compression );
1120 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1122 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1123 width, height, planes, bpp, compression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1124 sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1126 dib->dsBm.bmType = 0;
1127 dib->dsBm.bmWidth = width;
1128 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1129 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1130 dib->dsBm.bmPlanes = planes;
1131 dib->dsBm.bmBitsPixel = bpp;
1132 dib->dsBm.bmBits = NULL;
1134 if (!bitmap_type) /* core header */
1136 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1137 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1138 dib->dsBmih.biWidth = width;
1139 dib->dsBmih.biHeight = height;
1140 dib->dsBmih.biPlanes = planes;
1141 dib->dsBmih.biBitCount = bpp;
1142 dib->dsBmih.biCompression = compression;
1143 dib->dsBmih.biXPelsPerMeter = 0;
1144 dib->dsBmih.biYPelsPerMeter = 0;
1145 dib->dsBmih.biClrUsed = 0;
1146 dib->dsBmih.biClrImportant = 0;
1150 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1151 dib->dsBmih = bmi->bmiHeader;
1152 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1155 /* set number of entries in bmi.bmiColors table */
1157 dib->dsBmih.biClrUsed = 1 << bpp;
1159 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1161 /* set dsBitfields values */
1162 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1164 if((bpp == 15 || bpp == 16) && compression == BI_RGB)
1166 /* In this case Windows changes biCompression to BI_BITFIELDS,
1167 however for now we won't do this, as there are a lot
1168 of places where BI_BITFIELDS is currently unsupported. */
1170 /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
1171 dib->dsBitfields[0] = 0x7c00;
1172 dib->dsBitfields[1] = 0x03e0;
1173 dib->dsBitfields[2] = 0x001f;
1175 else if(compression == BI_BITFIELDS)
1177 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
1178 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
1179 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
1182 /* get storage location for DIB bits */
1186 SYSTEM_INFO SystemInfo;
1190 GetSystemInfo( &SystemInfo );
1191 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1192 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1193 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1194 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1199 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1200 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1202 dib->dshSection = section;
1203 dib->dsOffset = offset;
1205 if (!dib->dsBm.bmBits)
1207 HeapFree( GetProcessHeap(), 0, dib );
1211 /* If the reference hdc is null, take the desktop dc */
1214 hdc = CreateCompatibleDC(0);
1218 if (!(dc = get_dc_ptr( hdc ))) goto error;
1220 /* create Device Dependent Bitmap and add DIB pointer */
1221 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1222 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1224 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1226 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1228 bmp->funcs = physdev->funcs;
1229 /* create local copy of DIB palette */
1230 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1231 GDI_ReleaseObj( ret );
1233 if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1235 DeleteObject( ret );
1240 release_dc_ptr( dc );
1241 if (bDesktopDC) DeleteDC( hdc );
1242 if (ret && bits) *bits = dib->dsBm.bmBits;
1246 if (bDesktopDC) DeleteDC( hdc );
1247 if (section) UnmapViewOfFile( mapBits );
1248 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1249 HeapFree( GetProcessHeap(), 0, dib );