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);
76 /***********************************************************************
79 * Return the size of the bitmap info structure including color table.
81 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
83 unsigned int colors, size, masks = 0;
85 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
87 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
88 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
89 return sizeof(BITMAPCOREHEADER) + colors *
90 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
92 else /* assume BITMAPINFOHEADER */
94 colors = info->bmiHeader.biClrUsed;
95 if (colors > 256) colors = 256;
96 if (!colors && (info->bmiHeader.biBitCount <= 8))
97 colors = 1 << info->bmiHeader.biBitCount;
98 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
99 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
100 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
105 /***********************************************************************
108 * Get the info from a bitmap header.
109 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
111 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
112 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
114 if (header->biSize == sizeof(BITMAPCOREHEADER))
116 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
117 *width = core->bcWidth;
118 *height = core->bcHeight;
119 *planes = core->bcPlanes;
120 *bpp = core->bcBitCount;
125 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
127 *width = header->biWidth;
128 *height = header->biHeight;
129 *planes = header->biPlanes;
130 *bpp = header->biBitCount;
131 *compr = header->biCompression;
132 *size = header->biSizeImage;
135 ERR("(%d): unknown/wrong size for header\n", header->biSize );
139 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
140 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
141 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
142 const BITMAPINFO *info, UINT coloruse, DWORD rop )
144 DC *dc = get_nulldrv_dc( dev );
152 /* make sure we have a real implementation for StretchBlt and SetDIBits */
153 if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pSetDIBits ) == dev)
156 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
159 if (width < 0) return 0;
161 if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
162 info->bmiHeader.biCompression == BI_RGB)
164 /* Windows appears to have a fast case optimization
165 * that uses the wrong origin for top-down DIBs */
166 if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
168 if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
171 hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
172 if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
173 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
174 bm.bmBitsPixel == bpp && bm.bmPlanes == planes)
177 return SetDIBits( dev->hdc, hBitmap, 0, height, bits, info, coloruse );
182 hdcMem = CreateCompatibleDC( dev->hdc );
183 hBitmap = CreateCompatibleBitmap( dev->hdc, width, height );
184 SelectObject( hdcMem, hBitmap );
185 if (coloruse == DIB_PAL_COLORS)
186 SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
188 if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
190 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
191 * contain all the rectangle described in bmiHeader, but only part of it.
192 * This mean that those undescribed pixels must be left untouched.
193 * So, we first copy on a memory bitmap the current content of the
194 * destination rectangle, blit the DIB bits on top of it - hence leaving
195 * the gaps untouched -, and blitting the rectangle back.
196 * This insure that gaps are untouched on the destination rectangle
198 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
199 dev->hdc, xDst, yDst, widthDst, heightDst, rop );
201 ret = SetDIBits( hdcMem, hBitmap, 0, height, bits, info, coloruse );
202 if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
203 hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
205 DeleteObject( hBitmap );
209 /***********************************************************************
210 * StretchDIBits (GDI32.@)
212 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
213 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
214 const BITMAPINFO *info, UINT coloruse, DWORD rop )
219 if (!bits || !info) return 0;
221 if ((dc = get_dc_ptr( hdc )))
223 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
225 ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
226 xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
227 release_dc_ptr( dc );
233 /******************************************************************************
234 * SetDIBits [GDI32.@]
236 * Sets pixels in a bitmap using colors from DIB.
239 * hdc [I] Handle to device context
240 * hbitmap [I] Handle to bitmap
241 * startscan [I] Starting scan line
242 * lines [I] Number of scan lines
243 * bits [I] Array of bitmap bits
244 * info [I] Address of structure with data
245 * coloruse [I] Type of color indexes to use
248 * Success: Number of scan lines copied
251 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
252 UINT lines, LPCVOID bits, const BITMAPINFO *info,
255 DC *dc = get_dc_ptr( hdc );
256 BOOL delete_hdc = FALSE;
261 if (coloruse == DIB_RGB_COLORS && !dc)
263 hdc = CreateCompatibleDC(0);
264 dc = get_dc_ptr( hdc );
272 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
274 release_dc_ptr( dc );
275 if (delete_hdc) DeleteDC(hdc);
279 physdev = GET_DC_PHYSDEV( dc, pSetDIBits );
280 if (BITMAP_SetOwnerDC( hbitmap, physdev ))
281 result = physdev->funcs->pSetDIBits( physdev, hbitmap, startscan, lines, bits, info, coloruse );
283 GDI_ReleaseObj( hbitmap );
284 release_dc_ptr( dc );
285 if (delete_hdc) DeleteDC(hdc);
290 /***********************************************************************
291 * SetDIBitsToDevice (GDI32.@)
293 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
294 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
295 UINT lines, LPCVOID bits, const BITMAPINFO *info,
303 if ((dc = get_dc_ptr( hdc )))
305 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
307 ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
308 ySrc, startscan, lines, bits, info, coloruse );
309 release_dc_ptr( dc );
314 /***********************************************************************
315 * SetDIBColorTable (GDI32.@)
317 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
323 if (!(dc = get_dc_ptr( hdc ))) return 0;
325 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
327 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
329 /* Check if currently selected bitmap is a DIB */
330 if (bitmap->color_table)
332 if (startpos < bitmap->nb_colors)
334 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
335 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
339 GDI_ReleaseObj( dc->hBitmap );
340 physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
342 release_dc_ptr( dc );
347 /***********************************************************************
348 * GetDIBColorTable (GDI32.@)
350 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
356 if (!(dc = get_dc_ptr( hdc ))) return 0;
358 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
360 /* Check if currently selected bitmap is a DIB */
361 if (bitmap->color_table)
363 if (startpos < bitmap->nb_colors)
365 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
366 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
370 GDI_ReleaseObj( dc->hBitmap );
372 release_dc_ptr( dc );
376 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
377 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
378 { 0x00, 0x00, 0x00, 0x00 },
379 { 0x00, 0x00, 0x80, 0x00 },
380 { 0x00, 0x80, 0x00, 0x00 },
381 { 0x00, 0x80, 0x80, 0x00 },
382 { 0x80, 0x00, 0x00, 0x00 },
383 { 0x80, 0x00, 0x80, 0x00 },
384 { 0x80, 0x80, 0x00, 0x00 },
385 { 0xc0, 0xc0, 0xc0, 0x00 },
386 { 0xc0, 0xdc, 0xc0, 0x00 },
387 { 0xf0, 0xca, 0xa6, 0x00 },
388 { 0xf0, 0xfb, 0xff, 0x00 },
389 { 0xa4, 0xa0, 0xa0, 0x00 },
390 { 0x80, 0x80, 0x80, 0x00 },
391 { 0x00, 0x00, 0xff, 0x00 },
392 { 0x00, 0xff, 0x00, 0x00 },
393 { 0x00, 0xff, 0xff, 0x00 },
394 { 0xff, 0x00, 0x00, 0x00 },
395 { 0xff, 0x00, 0xff, 0x00 },
396 { 0xff, 0xff, 0x00, 0x00 },
397 { 0xff, 0xff, 0xff, 0x00 }
400 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
401 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
402 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
404 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
406 BITMAPINFOHEADER header;
408 header.biSize = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
409 header.biWidth = bmp->bitmap.bmWidth;
410 header.biHeight = bmp->bitmap.bmHeight;
415 header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
416 switch (bmp->dib->dsBm.bmBitsPixel)
420 header.biCompression = BI_BITFIELDS;
423 header.biCompression = BI_RGB;
429 header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
430 header.biBitCount = bmp->bitmap.bmBitsPixel;
433 header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
434 header.biXPelsPerMeter = 0;
435 header.biYPelsPerMeter = 0;
436 header.biClrUsed = 0;
437 header.biClrImportant = 0;
439 if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
441 BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
443 coreheader->bcWidth = header.biWidth;
444 coreheader->bcHeight = header.biHeight;
445 coreheader->bcPlanes = header.biPlanes;
446 coreheader->bcBitCount = header.biBitCount;
449 info->bmiHeader = header;
451 return abs(bmp->bitmap.bmHeight);
454 /************************************************************************
457 * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
459 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
461 unsigned int colors = src->bmiHeader.biBitCount > 8 ? 0 : 1 << src->bmiHeader.biBitCount;
462 RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
464 assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
466 if (src->bmiHeader.biClrUsed) colors = src->bmiHeader.biClrUsed;
468 if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
470 BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
471 if (coloruse == DIB_PAL_COLORS)
472 memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
476 for (i = 0; i < colors; i++)
478 core->bmciColors[i].rgbtRed = src_colors[i].rgbRed;
479 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
480 core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue;
486 dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed;
487 dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
489 if (src->bmiHeader.biCompression == BI_BITFIELDS)
490 /* bitfields are always at bmiColors even in larger structures */
491 memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
494 void *colorptr = (char *)dst + dst->bmiHeader.biSize;
497 if (coloruse == DIB_PAL_COLORS)
498 size = colors * sizeof(WORD);
500 size = colors * sizeof(RGBQUAD);
501 memcpy( colorptr, src_colors, size );
506 static void fill_default_color_table( BITMAPINFO *info )
510 switch (info->bmiHeader.biBitCount)
513 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
514 info->bmiColors[0].rgbReserved = 0;
515 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
516 info->bmiColors[1].rgbReserved = 0;
520 /* The EGA palette is the first and last 8 colours of the default palette
521 with the innermost pair swapped */
522 memcpy(info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
523 memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
524 memcpy(info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
525 memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
529 memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
530 memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
531 for (i = 10; i < 246; i++)
533 info->bmiColors[i].rgbRed = (i & 0x07) << 5;
534 info->bmiColors[i].rgbGreen = (i & 0x38) << 2;
535 info->bmiColors[i].rgbBlue = i & 0xc0;
536 info->bmiColors[i].rgbReserved = 0;
541 ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
545 /******************************************************************************
546 * GetDIBits [GDI32.@]
548 * Retrieves bits of bitmap and copies to buffer.
551 * Success: Number of scan lines copied from bitmap
554 INT WINAPI GetDIBits(
555 HDC hdc, /* [in] Handle to device context */
556 HBITMAP hbitmap, /* [in] Handle to bitmap */
557 UINT startscan, /* [in] First scan line to set in dest bitmap */
558 UINT lines, /* [in] Number of scan lines to copy */
559 LPVOID bits, /* [out] Address of array for bitmap bits */
560 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
561 UINT coloruse) /* [in] RGB or palette index */
571 char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
572 BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
573 unsigned int colors = 0;
577 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
578 if (bitmap_type == -1)
580 ERR("Invalid bitmap format\n");
583 if (!(dc = get_dc_ptr( hdc )))
585 SetLastError( ERROR_INVALID_PARAMETER );
589 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
591 release_dc_ptr( dc );
596 if (bpp == 0) /* query bitmap info only */
598 lines = fill_query_info( info, bmp );
602 /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
603 own copy and transfer the colour info back at the end */
605 dst_info->bmiHeader.biSize = sizeof(dst_info->bmiHeader);
606 dst_info->bmiHeader.biWidth = width;
607 dst_info->bmiHeader.biHeight = height;
608 dst_info->bmiHeader.biPlanes = planes;
609 dst_info->bmiHeader.biBitCount = bpp;
610 dst_info->bmiHeader.biCompression = compr;
611 dst_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
612 dst_info->bmiHeader.biXPelsPerMeter = 0;
613 dst_info->bmiHeader.biYPelsPerMeter = 0;
614 dst_info->bmiHeader.biClrUsed = 0;
615 dst_info->bmiHeader.biClrImportant = 0;
625 /* If the bitmap object is a dib section at the
626 same color depth then get the color map from it */
627 if (bmp->dib && bpp == bmp->dib->dsBm.bmBitsPixel && coloruse == DIB_RGB_COLORS)
629 colors = min( colors, bmp->nb_colors );
630 if (colors != 1 << bpp) dst_info->bmiHeader.biClrUsed = colors;
631 memcpy( dst_info->bmiColors, bmp->color_table, colors * sizeof(RGBQUAD) );
634 /* For color DDBs in native depth (mono DDBs always have a black/white palette):
635 Generate the color map from the selected palette. In the DIB_PAL_COLORS
636 case we'll fix up the indices after the format conversion. */
637 else if ( (bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) || coloruse == DIB_PAL_COLORS )
639 PALETTEENTRY palEntry[256];
641 memset( palEntry, 0, sizeof(palEntry) );
642 if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
648 for (i = 0; i < colors; i++)
650 dst_info->bmiColors[i].rgbRed = palEntry[i].peRed;
651 dst_info->bmiColors[i].rgbGreen = palEntry[i].peGreen;
652 dst_info->bmiColors[i].rgbBlue = palEntry[i].peBlue;
653 dst_info->bmiColors[i].rgbReserved = 0;
657 fill_default_color_table( dst_info );
662 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
663 memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
667 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
671 if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
672 memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
674 memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
677 memcpy( dst_info->bmiColors, bit_fields_565, sizeof(bit_fields_565) );
683 if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
685 if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
686 memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
688 memcpy( dst_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
696 char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
697 BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
698 struct gdi_image_bits src_bits;
699 struct bitblt_coords src;
702 /* FIXME: will need updating once the dib driver has pGetImage. */
703 physdev = GET_DC_PHYSDEV( dc, pGetImage );
705 if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
707 src.visrect.left = 0;
708 src.visrect.right = min( width, bmp->bitmap.bmWidth );
710 if (startscan >= bmp->bitmap.bmHeight) /* constrain lines to within src bitmap */
713 lines = min( lines, bmp->bitmap.bmHeight - startscan );
714 lines = min( lines, abs(height) ); /* and constrain to within dest bitmap */
716 if (lines == 0) goto done;
718 src.visrect.bottom = bmp->bitmap.bmHeight - startscan;
719 src.visrect.top = src.visrect.bottom - lines;
720 src.x = src.visrect.left;
721 src.y = src.visrect.top;
722 src.width = src.visrect.right - src.visrect.left;
723 src.height = src.visrect.bottom - src.visrect.top;
725 err = physdev->funcs->pGetImage( physdev, hbitmap, src_info, &src_bits, &src );
733 if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
736 memcpy( src_info->bmiColors, bmp->color_table, bmp->nb_colors * sizeof(RGBQUAD) );
738 fill_default_color_table( src_info );
741 if(dst_info->bmiHeader.biHeight > 0)
742 dst_info->bmiHeader.biHeight = lines;
744 dst_info->bmiHeader.biHeight = -lines;
746 convert_bitmapinfo( src_info, src_bits.ptr, &src.visrect, dst_info, bits );
747 if (src_bits.free) src_bits.free( &src_bits );
749 else lines = abs(height);
751 if (coloruse == DIB_PAL_COLORS)
753 WORD *index = (WORD *)dst_info->bmiColors;
754 for (i = 0; i < colors; i++, index++)
758 copy_color_info( info, dst_info, coloruse );
761 release_dc_ptr( dc );
762 GDI_ReleaseObj( hbitmap );
767 /***********************************************************************
768 * CreateDIBitmap (GDI32.@)
770 * Creates a DDB (device dependent bitmap) from a DIB.
771 * The DDB will have the same color depth as the reference DC.
773 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
774 DWORD init, LPCVOID bits, const BITMAPINFO *data,
783 if (!header) return 0;
785 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
789 TRACE("Bitmap has a negative width\n");
793 /* Top-down DIBs have a negative height */
794 if (height < 0) height = -height;
796 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
797 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
800 handle = CreateBitmap( width, height, 1, 1, NULL );
802 handle = CreateCompatibleBitmap( hdc, width, height );
808 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
810 DeleteObject( handle );
819 /* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
820 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
823 unsigned int colors, i;
824 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
828 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
832 colors = info->bmiHeader.biClrUsed;
833 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
837 ERR("called with >256 colors!\n");
841 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
843 if(coloruse == DIB_RGB_COLORS)
847 /* Convert RGBTRIPLEs to RGBQUADs */
848 for (i=0; i < colors; i++)
850 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
851 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
852 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
853 colorTable[i].rgbReserved = 0;
858 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
863 PALETTEENTRY entries[256];
864 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
865 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
867 for (i = 0; i < colors; i++, index++)
869 PALETTEENTRY *entry = &entries[*index % count];
870 colorTable[i].rgbRed = entry->peRed;
871 colorTable[i].rgbGreen = entry->peGreen;
872 colorTable[i].rgbBlue = entry->peBlue;
873 colorTable[i].rgbReserved = 0;
876 bmp->color_table = colorTable;
877 bmp->nb_colors = colors;
880 /***********************************************************************
881 * CreateDIBSection (GDI32.@)
883 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
884 VOID **bits, HANDLE section, DWORD offset)
888 BOOL bDesktopDC = FALSE;
894 DWORD compression, sizeImage;
895 void *mapBits = NULL;
898 if(bits) *bits = NULL;
902 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
903 &planes, &bpp, &compression, &sizeImage )) == -1))
910 if (compression == BI_BITFIELDS) break;
916 if (compression == BI_RGB) break;
919 WARN( "invalid %u bpp compression %u\n", bpp, compression );
923 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
925 TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
926 width, height, planes, bpp, compression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
927 sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
929 dib->dsBm.bmType = 0;
930 dib->dsBm.bmWidth = width;
931 dib->dsBm.bmHeight = height >= 0 ? height : -height;
932 dib->dsBm.bmWidthBytes = get_dib_stride( width, bpp );
933 dib->dsBm.bmPlanes = planes;
934 dib->dsBm.bmBitsPixel = bpp;
935 dib->dsBm.bmBits = NULL;
937 if (!bitmap_type) /* core header */
939 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
940 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
941 dib->dsBmih.biWidth = width;
942 dib->dsBmih.biHeight = height;
943 dib->dsBmih.biPlanes = planes;
944 dib->dsBmih.biBitCount = bpp;
945 dib->dsBmih.biCompression = compression;
946 dib->dsBmih.biXPelsPerMeter = 0;
947 dib->dsBmih.biYPelsPerMeter = 0;
948 dib->dsBmih.biClrUsed = 0;
949 dib->dsBmih.biClrImportant = 0;
953 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
954 dib->dsBmih = bmi->bmiHeader;
955 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
958 /* set number of entries in bmi.bmiColors table */
960 dib->dsBmih.biClrUsed = 1 << bpp;
962 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
964 /* set dsBitfields values */
965 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
967 if((bpp == 15 || bpp == 16) && compression == BI_RGB)
969 /* In this case Windows changes biCompression to BI_BITFIELDS,
970 however for now we won't do this, as there are a lot
971 of places where BI_BITFIELDS is currently unsupported. */
973 /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
974 dib->dsBitfields[0] = 0x7c00;
975 dib->dsBitfields[1] = 0x03e0;
976 dib->dsBitfields[2] = 0x001f;
978 else if(compression == BI_BITFIELDS)
980 dib->dsBitfields[0] = *(const DWORD *)bmi->bmiColors;
981 dib->dsBitfields[1] = *((const DWORD *)bmi->bmiColors + 1);
982 dib->dsBitfields[2] = *((const DWORD *)bmi->bmiColors + 2);
985 /* get storage location for DIB bits */
989 SYSTEM_INFO SystemInfo;
993 GetSystemInfo( &SystemInfo );
994 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
995 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
996 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
997 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1002 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1003 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1005 dib->dshSection = section;
1006 dib->dsOffset = offset;
1008 if (!dib->dsBm.bmBits)
1010 HeapFree( GetProcessHeap(), 0, dib );
1014 /* If the reference hdc is null, take the desktop dc */
1017 hdc = CreateCompatibleDC(0);
1021 if (!(dc = get_dc_ptr( hdc ))) goto error;
1023 /* create Device Dependent Bitmap and add DIB pointer */
1024 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1025 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1027 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1029 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1031 bmp->funcs = physdev->funcs;
1032 /* create local copy of DIB palette */
1033 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1034 GDI_ReleaseObj( ret );
1036 if (!physdev->funcs->pCreateDIBSection( physdev, ret, bmi, usage ))
1038 DeleteObject( ret );
1043 release_dc_ptr( dc );
1044 if (bDesktopDC) DeleteDC( hdc );
1045 if (ret && bits) *bits = dib->dsBm.bmBits;
1049 if (bDesktopDC) DeleteDC( hdc );
1050 if (section) UnmapViewOfFile( mapBits );
1051 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1052 HeapFree( GetProcessHeap(), 0, dib );