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.
85 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
87 int DIB_GetDIBWidthBytes( int width, int depth )
93 case 1: words = (width + 31) / 32; break;
94 case 4: words = (width + 7) / 8; break;
95 case 8: words = (width + 3) / 4; break;
97 case 16: words = (width + 1) / 2; break;
98 case 24: words = (width * 3 + 3)/4; break;
101 WARN("(%d): Unsupported depth\n", depth );
109 /***********************************************************************
110 * DIB_GetDIBImageBytes
112 * Return the number of bytes used to hold the image in a DIB bitmap.
114 int DIB_GetDIBImageBytes( int width, int height, int depth )
116 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
120 /***********************************************************************
123 * Return the size of the bitmap info structure including color table.
125 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
129 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
131 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
132 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
133 return sizeof(BITMAPCOREHEADER) + colors *
134 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
136 else /* assume BITMAPINFOHEADER */
138 colors = info->bmiHeader.biClrUsed;
139 if (colors > 256) colors = 256;
140 if (!colors && (info->bmiHeader.biBitCount <= 8))
141 colors = 1 << info->bmiHeader.biBitCount;
142 return sizeof(BITMAPINFOHEADER) + colors *
143 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
148 /***********************************************************************
151 * Get the info from a bitmap header.
152 * Return 1 for INFOHEADER, 0 for COREHEADER,
153 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
155 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
156 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
158 if (header->biSize == sizeof(BITMAPINFOHEADER))
160 *width = header->biWidth;
161 *height = header->biHeight;
162 *planes = header->biPlanes;
163 *bpp = header->biBitCount;
164 *compr = header->biCompression;
165 *size = header->biSizeImage;
168 if (header->biSize == sizeof(BITMAPCOREHEADER))
170 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
171 *width = core->bcWidth;
172 *height = core->bcHeight;
173 *planes = core->bcPlanes;
174 *bpp = core->bcBitCount;
179 if (header->biSize == sizeof(BITMAPV4HEADER))
181 const BITMAPV4HEADER *v4hdr = (const BITMAPV4HEADER *)header;
182 *width = v4hdr->bV4Width;
183 *height = v4hdr->bV4Height;
184 *planes = v4hdr->bV4Planes;
185 *bpp = v4hdr->bV4BitCount;
186 *compr = v4hdr->bV4V4Compression;
187 *size = v4hdr->bV4SizeImage;
190 if (header->biSize == sizeof(BITMAPV5HEADER))
192 const BITMAPV5HEADER *v5hdr = (const BITMAPV5HEADER *)header;
193 *width = v5hdr->bV5Width;
194 *height = v5hdr->bV5Height;
195 *planes = v5hdr->bV5Planes;
196 *bpp = v5hdr->bV5BitCount;
197 *compr = v5hdr->bV5Compression;
198 *size = v5hdr->bV5SizeImage;
201 ERR("(%d): unknown/wrong size for header\n", header->biSize );
206 /***********************************************************************
207 * StretchDIBits (GDI32.@)
209 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
210 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
211 INT heightSrc, const void *bits,
212 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
219 dc = DC_GetDCUpdate( hdc );
220 if(!dc) return FALSE;
222 if(dc->funcs->pStretchDIBits)
224 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
225 heightDst, xSrc, ySrc, widthSrc,
226 heightSrc, bits, info, wUsage, dwRop);
227 GDI_ReleaseObj( hdc );
229 else /* use StretchBlt */
231 HBITMAP hBitmap, hOldBitmap;
232 HPALETTE hpal = NULL;
239 GDI_ReleaseObj( hdc );
241 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
243 ERR("Invalid bitmap\n");
249 ERR("Bitmap has a negative width\n");
253 hdcMem = CreateCompatibleDC( hdc );
254 hBitmap = CreateCompatibleBitmap(hdc, width, height);
255 hOldBitmap = SelectObject( hdcMem, hBitmap );
256 if(wUsage == DIB_PAL_COLORS)
258 hpal = GetCurrentObject(hdc, OBJ_PAL);
259 hpal = SelectPalette(hdcMem, hpal, FALSE);
262 if (info->bmiHeader.biCompression == BI_RLE4 ||
263 info->bmiHeader.biCompression == BI_RLE8) {
265 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
266 * contain all the rectangle described in bmiHeader, but only part of it.
267 * This mean that those undescribed pixels must be left untouched.
268 * So, we first copy on a memory bitmap the current content of the
269 * destination rectangle, blit the DIB bits on top of it - hence leaving
270 * the gaps untouched -, and blitting the rectangle back.
271 * This insure that gaps are untouched on the destination rectangle
272 * Not doing so leads to trashed images (the gaps contain what was on the
273 * memory bitmap => generally black or garbage)
274 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
275 * another speed vs correctness issue. Anyway, if speed is needed, then the
276 * pStretchDIBits function shall be implemented.
280 /* copy existing bitmap from destination dc */
281 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
282 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
286 SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
288 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
289 left (negative biHeight) */
290 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
291 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
292 widthSrc, heightSrc, dwRop );
294 SelectPalette(hdcMem, hpal, FALSE);
295 SelectObject( hdcMem, hOldBitmap );
297 DeleteObject( hBitmap );
303 /******************************************************************************
304 * SetDIBits [GDI32.@]
306 * Sets pixels in a bitmap using colors from DIB.
309 * hdc [I] Handle to device context
310 * hbitmap [I] Handle to bitmap
311 * startscan [I] Starting scan line
312 * lines [I] Number of scan lines
313 * bits [I] Array of bitmap bits
314 * info [I] Address of structure with data
315 * coloruse [I] Type of color indexes to use
318 * Success: Number of scan lines copied
321 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
322 UINT lines, LPCVOID bits, const BITMAPINFO *info,
329 if (!(dc = DC_GetDCUpdate( hdc )))
331 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
335 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
337 GDI_ReleaseObj( hdc );
341 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
343 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
344 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
345 bits, info, coloruse );
350 GDI_ReleaseObj( hbitmap );
351 GDI_ReleaseObj( hdc );
356 /***********************************************************************
357 * SetDIBitsToDevice (GDI32.@)
359 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
360 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
361 UINT lines, LPCVOID bits, const BITMAPINFO *info,
367 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
369 if(dc->funcs->pSetDIBitsToDevice)
370 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
371 ySrc, startscan, lines, bits,
374 FIXME("unimplemented on hdc %p\n", hdc);
378 GDI_ReleaseObj( hdc );
382 /***********************************************************************
383 * SetDIBColorTable (GDI32.@)
385 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
391 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
393 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
395 /* Check if currently selected bitmap is a DIB */
396 if (bitmap->color_table)
398 if (startpos < bitmap->nb_colors)
400 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
401 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
405 GDI_ReleaseObj( dc->hBitmap );
408 if (dc->funcs->pSetDIBColorTable)
409 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
411 GDI_ReleaseObj( hdc );
416 /***********************************************************************
417 * GetDIBColorTable (GDI32.@)
419 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
424 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
426 if (dc->funcs->pGetDIBColorTable)
427 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
430 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
433 /* Check if currently selected bitmap is a DIB */
434 if (bitmap->color_table)
436 if (startpos < bitmap->nb_colors)
438 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
439 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
443 GDI_ReleaseObj( dc->hBitmap );
446 GDI_ReleaseObj( hdc );
450 /* FIXME the following two structs should be combined with __sysPalTemplate in
451 objects/color.c - this should happen after de-X11-ing both of these
453 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
456 static const RGBQUAD EGAColorsQuads[16] = {
457 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
458 { 0x00, 0x00, 0x00, 0x00 },
459 { 0x00, 0x00, 0x80, 0x00 },
460 { 0x00, 0x80, 0x00, 0x00 },
461 { 0x00, 0x80, 0x80, 0x00 },
462 { 0x80, 0x00, 0x00, 0x00 },
463 { 0x80, 0x00, 0x80, 0x00 },
464 { 0x80, 0x80, 0x00, 0x00 },
465 { 0x80, 0x80, 0x80, 0x00 },
466 { 0xc0, 0xc0, 0xc0, 0x00 },
467 { 0x00, 0x00, 0xff, 0x00 },
468 { 0x00, 0xff, 0x00, 0x00 },
469 { 0x00, 0xff, 0xff, 0x00 },
470 { 0xff, 0x00, 0x00, 0x00 },
471 { 0xff, 0x00, 0xff, 0x00 },
472 { 0xff, 0xff, 0x00, 0x00 },
473 { 0xff, 0xff, 0xff, 0x00 }
476 static const RGBTRIPLE EGAColorsTriples[16] = {
477 /* rgbBlue, rgbGreen, rgbRed */
478 { 0x00, 0x00, 0x00 },
479 { 0x00, 0x00, 0x80 },
480 { 0x00, 0x80, 0x00 },
481 { 0x00, 0x80, 0x80 },
482 { 0x80, 0x00, 0x00 },
483 { 0x80, 0x00, 0x80 },
484 { 0x80, 0x80, 0x00 },
485 { 0x80, 0x80, 0x80 },
486 { 0xc0, 0xc0, 0xc0 },
487 { 0x00, 0x00, 0xff },
488 { 0x00, 0xff, 0x00 },
489 { 0x00, 0xff, 0xff },
490 { 0xff, 0x00, 0x00 } ,
491 { 0xff, 0x00, 0xff },
492 { 0xff, 0xff, 0x00 },
496 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
497 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
498 { 0x00, 0x00, 0x00, 0x00 },
499 { 0x00, 0x00, 0x80, 0x00 },
500 { 0x00, 0x80, 0x00, 0x00 },
501 { 0x00, 0x80, 0x80, 0x00 },
502 { 0x80, 0x00, 0x00, 0x00 },
503 { 0x80, 0x00, 0x80, 0x00 },
504 { 0x80, 0x80, 0x00, 0x00 },
505 { 0xc0, 0xc0, 0xc0, 0x00 },
506 { 0xc0, 0xdc, 0xc0, 0x00 },
507 { 0xf0, 0xca, 0xa6, 0x00 },
508 { 0xf0, 0xfb, 0xff, 0x00 },
509 { 0xa4, 0xa0, 0xa0, 0x00 },
510 { 0x80, 0x80, 0x80, 0x00 },
511 { 0x00, 0x00, 0xf0, 0x00 },
512 { 0x00, 0xff, 0x00, 0x00 },
513 { 0x00, 0xff, 0xff, 0x00 },
514 { 0xff, 0x00, 0x00, 0x00 },
515 { 0xff, 0x00, 0xff, 0x00 },
516 { 0xff, 0xff, 0x00, 0x00 },
517 { 0xff, 0xff, 0xff, 0x00 }
520 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
521 /* rgbBlue, rgbGreen, rgbRed */
522 { 0x00, 0x00, 0x00 },
523 { 0x00, 0x00, 0x80 },
524 { 0x00, 0x80, 0x00 },
525 { 0x00, 0x80, 0x80 },
526 { 0x80, 0x00, 0x00 },
527 { 0x80, 0x00, 0x80 },
528 { 0x80, 0x80, 0x00 },
529 { 0xc0, 0xc0, 0xc0 },
530 { 0xc0, 0xdc, 0xc0 },
531 { 0xf0, 0xca, 0xa6 },
532 { 0xf0, 0xfb, 0xff },
533 { 0xa4, 0xa0, 0xa0 },
534 { 0x80, 0x80, 0x80 },
535 { 0x00, 0x00, 0xf0 },
536 { 0x00, 0xff, 0x00 },
537 { 0x00, 0xff, 0xff },
538 { 0xff, 0x00, 0x00 },
539 { 0xff, 0x00, 0xff },
540 { 0xff, 0xff, 0x00 },
545 /******************************************************************************
546 * GetDIBits [GDI32.@]
548 * Retrieves bits of bitmap and copies to buffer.
551 * Success: Number of scan lines copied from bitmap
554 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
556 INT WINAPI GetDIBits(
557 HDC hdc, /* [in] Handle to device context */
558 HBITMAP hbitmap, /* [in] Handle to bitmap */
559 UINT startscan, /* [in] First scan line to set in dest bitmap */
560 UINT lines, /* [in] Number of scan lines to copy */
561 LPVOID bits, /* [out] Address of array for bitmap bits */
562 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
563 UINT coloruse) /* [in] RGB or palette index */
575 RGBTRIPLE* rgbTriples;
580 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
581 if (bitmap_type == -1)
583 ERR("Invalid bitmap format\n");
586 core_header = (bitmap_type == 0);
587 if (!(dc = DC_GetDCUpdate( hdc )))
591 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
593 GDI_ReleaseObj( hdc );
597 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
598 rgbTriples = (RGBTRIPLE *) colorPtr;
599 rgbQuads = (RGBQUAD *) colorPtr;
601 /* Transfer color info */
603 if (bpp <= 8 && bpp > 0)
605 if (!core_header) info->bmiHeader.biClrUsed = 0;
607 /* If the bitmap object already has a dib section at the
608 same color depth then get the color map from it */
609 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
610 if(coloruse == DIB_RGB_COLORS) {
611 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
615 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
616 RGBTRIPLE* index = rgbTriples;
618 for (i=0; i < colors; i++, index++)
620 index->rgbtRed = bmp->color_table[i].rgbRed;
621 index->rgbtGreen = bmp->color_table[i].rgbGreen;
622 index->rgbtBlue = bmp->color_table[i].rgbBlue;
627 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
628 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
632 WORD *index = colorPtr;
633 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
638 if(bpp >= bmp->bitmap.bmBitsPixel) {
639 /* Generate the color map from the selected palette */
640 PALETTEENTRY palEntry[256];
642 memset( palEntry, 0, sizeof(palEntry) );
643 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
645 GDI_ReleaseObj( hdc );
646 GDI_ReleaseObj( hbitmap );
649 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
650 if (coloruse == DIB_RGB_COLORS) {
653 rgbTriples[i].rgbtRed = palEntry[i].peRed;
654 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
655 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
659 rgbQuads[i].rgbRed = palEntry[i].peRed;
660 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
661 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
662 rgbQuads[i].rgbReserved = 0;
665 else ((WORD *)colorPtr)[i] = (WORD)i;
672 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
673 rgbTriples[0].rgbtBlue = 0;
674 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
675 rgbTriples[1].rgbtBlue = 0xff;
679 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
680 rgbQuads[0].rgbBlue = 0;
681 rgbQuads[0].rgbReserved = 0;
682 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
683 rgbQuads[1].rgbBlue = 0xff;
684 rgbQuads[1].rgbReserved = 0;
690 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
692 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
703 memcpy(rgbTriples, DefLogPaletteTriples,
704 10 * sizeof(RGBTRIPLE));
705 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
706 10 * sizeof(RGBTRIPLE));
707 color = rgbTriples + 10;
708 for(r = 0; r <= 5; r++) /* FIXME */
709 for(g = 0; g <= 5; g++)
710 for(b = 0; b <= 5; b++) {
711 color->rgbtRed = (r * 0xff) / 5;
712 color->rgbtGreen = (g * 0xff) / 5;
713 color->rgbtBlue = (b * 0xff) / 5;
722 memcpy(rgbQuads, DefLogPaletteQuads,
723 10 * sizeof(RGBQUAD));
724 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
725 10 * sizeof(RGBQUAD));
726 color = rgbQuads + 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->rgbRed = (r * 0xff) / 5;
731 color->rgbGreen = (g * 0xff) / 5;
732 color->rgbBlue = (b * 0xff) / 5;
733 color->rgbReserved = 0;
745 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
746 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
748 /*FIXME: Only RGB dibs supported for now */
749 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
750 unsigned int dstwidth = width;
751 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
752 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
753 unsigned int x, y, width, widthb;
755 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
757 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
758 dstwidthb = -dstwidthb;
764 case 16: /* 16 bpp dstDIB */
766 LPWORD dstbits = (LPWORD)dbits;
767 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
769 /* FIXME: BI_BITFIELDS not supported yet */
771 switch(bmp->dib->dsBm.bmBitsPixel) {
773 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
775 widthb = min(srcwidthb, abs(dstwidthb));
776 /* FIXME: BI_BITFIELDS not supported yet */
777 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
778 memcpy(dbits, sbits, widthb);
782 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
784 LPBYTE srcbits = sbits;
786 width = min(srcwidth, dstwidth);
787 for( y = 0; y < lines; y++) {
788 for( x = 0; x < width; x++, srcbits += 3)
789 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
790 (((WORD)srcbits[1] << 2) & gmask) |
791 (((WORD)srcbits[2] << 7) & rmask);
793 dstbits = (LPWORD)(dbits+=dstwidthb);
794 srcbits = (sbits += srcwidthb);
799 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
801 LPDWORD srcbits = (LPDWORD)sbits;
804 width = min(srcwidth, dstwidth);
805 for( y = 0; y < lines; y++) {
806 for( x = 0; x < width; x++ ) {
808 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
809 ((val >> 9) & rmask));
811 dstbits = (LPWORD)(dbits+=dstwidthb);
812 srcbits = (LPDWORD)(sbits+=srcwidthb);
817 default: /* ? bit bmp -> 16 bit DIB */
818 FIXME("15/16 bit DIB %d bit bitmap\n",
819 bmp->bitmap.bmBitsPixel);
825 case 24: /* 24 bpp dstDIB */
827 LPBYTE dstbits = dbits;
829 switch(bmp->dib->dsBm.bmBitsPixel) {
831 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
833 LPWORD srcbits = (LPWORD)sbits;
836 width = min(srcwidth, dstwidth);
837 /* FIXME: BI_BITFIELDS not supported yet */
838 for( y = 0; y < lines; y++) {
839 for( x = 0; x < width; x++ ) {
841 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
842 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
843 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
845 dstbits = (LPBYTE)(dbits+=dstwidthb);
846 srcbits = (LPWORD)(sbits+=srcwidthb);
851 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
853 widthb = min(srcwidthb, abs(dstwidthb));
854 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
855 memcpy(dbits, sbits, widthb);
859 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
861 LPBYTE srcbits = (LPBYTE)sbits;
863 width = min(srcwidth, dstwidth);
864 for( y = 0; y < lines; y++) {
865 for( x = 0; x < width; x++, srcbits++ ) {
866 *dstbits++ = *srcbits++;
867 *dstbits++ = *srcbits++;
868 *dstbits++ = *srcbits++;
870 dstbits=(LPBYTE)(dbits+=dstwidthb);
871 srcbits = (LPBYTE)(sbits+=srcwidthb);
876 default: /* ? bit bmp -> 24 bit DIB */
877 FIXME("24 bit DIB %d bit bitmap\n",
878 bmp->bitmap.bmBitsPixel);
884 case 32: /* 32 bpp dstDIB */
886 LPDWORD dstbits = (LPDWORD)dbits;
888 /* FIXME: BI_BITFIELDS not supported yet */
890 switch(bmp->dib->dsBm.bmBitsPixel) {
891 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
893 LPWORD srcbits = (LPWORD)sbits;
896 width = min(srcwidth, dstwidth);
897 /* FIXME: BI_BITFIELDS not supported yet */
898 for( y = 0; y < lines; y++) {
899 for( x = 0; x < width; x++ ) {
900 val = (DWORD)*srcbits++;
901 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
902 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
903 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
905 dstbits=(LPDWORD)(dbits+=dstwidthb);
906 srcbits=(LPWORD)(sbits+=srcwidthb);
911 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
913 LPBYTE srcbits = sbits;
915 width = min(srcwidth, dstwidth);
916 for( y = 0; y < lines; y++) {
917 for( x = 0; x < width; x++, srcbits+=3 )
918 *dstbits++ = srcbits[0] |
921 dstbits=(LPDWORD)(dbits+=dstwidthb);
922 srcbits=(sbits+=srcwidthb);
927 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
929 widthb = min(srcwidthb, abs(dstwidthb));
930 /* FIXME: BI_BITFIELDS not supported yet */
931 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
932 memcpy(dbits, sbits, widthb);
937 default: /* ? bit bmp -> 32 bit DIB */
938 FIXME("32 bit DIB %d bit bitmap\n",
939 bmp->bitmap.bmBitsPixel);
945 default: /* ? bit DIB */
946 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
950 /* Otherwise, get bits from the XImage */
953 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
956 if (bmp->funcs && bmp->funcs->pGetDIBits)
957 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
958 lines, bits, info, coloruse );
960 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
966 /* fill in struct members */
972 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
973 coreheader->bcWidth = bmp->bitmap.bmWidth;
974 coreheader->bcHeight = bmp->bitmap.bmHeight;
975 coreheader->bcPlanes = 1;
976 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
980 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
981 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
982 info->bmiHeader.biPlanes = 1;
983 info->bmiHeader.biSizeImage =
984 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
985 bmp->bitmap.bmHeight,
986 bmp->bitmap.bmBitsPixel );
987 switch(bmp->bitmap.bmBitsPixel)
990 info->bmiHeader.biBitCount = 16;
991 info->bmiHeader.biCompression = BI_RGB;
995 info->bmiHeader.biBitCount = 16;
996 info->bmiHeader.biCompression = BI_BITFIELDS;
997 ((PDWORD)info->bmiColors)[0] = 0xf800;
998 ((PDWORD)info->bmiColors)[1] = 0x07e0;
999 ((PDWORD)info->bmiColors)[2] = 0x001f;
1003 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1004 info->bmiHeader.biCompression = BI_RGB;
1007 info->bmiHeader.biXPelsPerMeter = 0;
1008 info->bmiHeader.biYPelsPerMeter = 0;
1009 info->bmiHeader.biClrUsed = 0;
1010 info->bmiHeader.biClrImportant = 0;
1012 /* Windows 2000 doesn't touch the additional struct members if
1013 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
1015 lines = abs(bmp->bitmap.bmHeight);
1019 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1020 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1024 /* FIXME: biSizeImage should be calculated according to the selected
1025 compression algorithm if biCompression != BI_RGB */
1026 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1028 lines = abs(height);
1034 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1036 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1038 GDI_ReleaseObj( hdc );
1039 GDI_ReleaseObj( hbitmap );
1044 /***********************************************************************
1045 * CreateDIBitmap (GDI32.@)
1047 * Creates a DDB (device dependent bitmap) from a DIB.
1048 * The DDB will have the same color depth as the reference DC.
1050 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1051 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1061 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1065 TRACE("Bitmap has a negative width\n");
1069 /* Top-down DIBs have a negative height */
1070 if (height < 0) height = -height;
1072 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1073 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1076 handle = CreateBitmap( width, height, 1, 1, NULL );
1078 handle = CreateCompatibleBitmap( hdc, width, height );
1082 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1084 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1086 if (!BITMAP_SetOwnerDC( handle, dc ))
1088 DeleteObject( handle );
1091 GDI_ReleaseObj( hdc );
1098 /***********************************************************************
1099 * CreateDIBSection (GDI.489)
1101 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1102 SEGPTR *bits16, HANDLE section, DWORD offset)
1107 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1110 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1111 if (bmp && bmp->dib && bits32)
1113 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1121 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1123 height = height >= 0 ? height : -height;
1124 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1126 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1128 /* calculate number of sel's needed for size with 64K steps */
1129 count = (size + 0xffff) / 0x10000;
1130 sel = AllocSelectorArray16(count);
1132 for (i = 0; i < count; i++)
1134 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1135 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1138 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1139 if (bits16) *bits16 = bmp->segptr_bits;
1141 if (bmp) GDI_ReleaseObj( hbitmap );
1143 return HBITMAP_16(hbitmap);
1146 /* Copy/synthetize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1147 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1149 RGBQUAD *colorTable;
1150 unsigned int colors;
1152 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1156 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1160 colors = info->bmiHeader.biClrUsed;
1161 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1165 ERR("called with >256 colors!\n");
1169 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1171 if(coloruse == DIB_RGB_COLORS)
1175 /* Convert RGBTRIPLEs to RGBQUADs */
1176 for (i=0; i < colors; i++)
1178 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1179 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1180 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1181 colorTable[i].rgbReserved = 0;
1186 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1191 PALETTEENTRY entries[256];
1192 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1193 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1195 for (i = 0; i < colors; i++, index++)
1197 PALETTEENTRY *entry = &entries[*index % count];
1198 colorTable[i].rgbRed = entry->peRed;
1199 colorTable[i].rgbGreen = entry->peGreen;
1200 colorTable[i].rgbBlue = entry->peBlue;
1201 colorTable[i].rgbReserved = 0;
1204 bmp->color_table = colorTable;
1205 bmp->nb_colors = colors;
1208 /***********************************************************************
1209 * CreateDIBSection (GDI32.@)
1211 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1212 VOID **bits, HANDLE section, DWORD offset)
1216 BOOL bDesktopDC = FALSE;
1222 DWORD compression, sizeImage;
1223 void *mapBits = NULL;
1225 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1226 &planes, &bpp, &compression, &sizeImage )) == -1))
1229 if (compression != BI_RGB && compression != BI_BITFIELDS)
1231 TRACE("can't create a compressed (%u) dibsection\n", compression);
1235 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1237 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1238 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1240 dib->dsBm.bmType = 0;
1241 dib->dsBm.bmWidth = width;
1242 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1243 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1244 dib->dsBm.bmPlanes = planes;
1245 dib->dsBm.bmBitsPixel = bpp;
1246 dib->dsBm.bmBits = NULL;
1248 if (!bitmap_type) /* core header */
1250 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1251 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1252 dib->dsBmih.biWidth = width;
1253 dib->dsBmih.biHeight = height;
1254 dib->dsBmih.biPlanes = planes;
1255 dib->dsBmih.biBitCount = bpp;
1256 dib->dsBmih.biCompression = compression;
1257 dib->dsBmih.biXPelsPerMeter = 0;
1258 dib->dsBmih.biYPelsPerMeter = 0;
1259 dib->dsBmih.biClrUsed = 0;
1260 dib->dsBmih.biClrImportant = 0;
1264 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1265 dib->dsBmih = bmi->bmiHeader;
1266 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1269 /* set number of entries in bmi.bmiColors table */
1271 dib->dsBmih.biClrUsed = 1 << bpp;
1273 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1275 /* set dsBitfields values */
1276 if (usage == DIB_PAL_COLORS || bpp <= 8)
1278 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1284 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1285 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1286 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1290 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1291 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1292 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1296 /* get storage location for DIB bits */
1300 SYSTEM_INFO SystemInfo;
1304 GetSystemInfo( &SystemInfo );
1305 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1306 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1307 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1308 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1313 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1314 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1316 dib->dshSection = section;
1317 dib->dsOffset = offset;
1319 if (!dib->dsBm.bmBits)
1321 HeapFree( GetProcessHeap(), 0, dib );
1325 /* If the reference hdc is null, take the desktop dc */
1328 hdc = CreateCompatibleDC(0);
1332 if (!(dc = DC_GetDCPtr( hdc ))) goto error;
1334 /* create Device Dependent Bitmap and add DIB pointer */
1335 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1336 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1338 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1341 bmp->funcs = dc->funcs;
1342 /* create local copy of DIB palette */
1343 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1344 GDI_ReleaseObj( ret );
1346 if (dc->funcs->pCreateDIBSection)
1348 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1350 DeleteObject( ret );
1356 GDI_ReleaseObj(hdc);
1357 if (bDesktopDC) DeleteDC( hdc );
1358 if (ret && bits) *bits = dib->dsBm.bmBits;
1362 if (bDesktopDC) DeleteDC( hdc );
1363 if (section) UnmapViewOfFile( mapBits );
1364 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1365 HeapFree( GetProcessHeap(), 0, dib );