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
71 #include "gdi_private.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
78 Some of the following helper functions are duplicated in
82 /***********************************************************************
83 * DIB_GetDIBWidthBytes
85 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
86 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
88 int DIB_GetDIBWidthBytes( int width, int depth )
94 case 1: words = (width + 31) / 32; break;
95 case 4: words = (width + 7) / 8; break;
96 case 8: words = (width + 3) / 4; break;
98 case 16: words = (width + 1) / 2; break;
99 case 24: words = (width * 3 + 3)/4; break;
102 WARN("(%d): Unsupported depth\n", depth );
110 /***********************************************************************
111 * DIB_GetDIBImageBytes
113 * Return the number of bytes used to hold the image in a DIB bitmap.
115 int DIB_GetDIBImageBytes( int width, int height, int depth )
117 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
121 /***********************************************************************
124 * Return the size of the bitmap info structure including color table.
126 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
130 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
132 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
133 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
134 return sizeof(BITMAPCOREHEADER) + colors *
135 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
137 else /* assume BITMAPINFOHEADER */
139 colors = info->bmiHeader.biClrUsed;
140 if (colors > 256) colors = 256;
141 if (!colors && (info->bmiHeader.biBitCount <= 8))
142 colors = 1 << info->bmiHeader.biBitCount;
143 return sizeof(BITMAPINFOHEADER) + colors *
144 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
149 /***********************************************************************
152 * Get the info from a bitmap header.
153 * Return 1 for INFOHEADER, 0 for COREHEADER,
154 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
156 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
157 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
159 if (header->biSize == sizeof(BITMAPINFOHEADER))
161 *width = header->biWidth;
162 *height = header->biHeight;
163 *planes = header->biPlanes;
164 *bpp = header->biBitCount;
165 *compr = header->biCompression;
166 *size = header->biSizeImage;
169 if (header->biSize == sizeof(BITMAPCOREHEADER))
171 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
172 *width = core->bcWidth;
173 *height = core->bcHeight;
174 *planes = core->bcPlanes;
175 *bpp = core->bcBitCount;
180 if (header->biSize == sizeof(BITMAPV4HEADER))
182 const BITMAPV4HEADER *v4hdr = (const BITMAPV4HEADER *)header;
183 *width = v4hdr->bV4Width;
184 *height = v4hdr->bV4Height;
185 *planes = v4hdr->bV4Planes;
186 *bpp = v4hdr->bV4BitCount;
187 *compr = v4hdr->bV4V4Compression;
188 *size = v4hdr->bV4SizeImage;
191 if (header->biSize == sizeof(BITMAPV5HEADER))
193 const BITMAPV5HEADER *v5hdr = (const BITMAPV5HEADER *)header;
194 *width = v5hdr->bV5Width;
195 *height = v5hdr->bV5Height;
196 *planes = v5hdr->bV5Planes;
197 *bpp = v5hdr->bV5BitCount;
198 *compr = v5hdr->bV5Compression;
199 *size = v5hdr->bV5SizeImage;
202 ERR("(%d): unknown/wrong size for header\n", header->biSize );
207 /***********************************************************************
208 * StretchDIBits (GDI32.@)
210 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
211 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
212 INT heightSrc, const void *bits,
213 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
220 dc = DC_GetDCUpdate( hdc );
221 if(!dc) return FALSE;
223 if(dc->funcs->pStretchDIBits)
225 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
226 heightDst, xSrc, ySrc, widthSrc,
227 heightSrc, bits, info, wUsage, dwRop);
228 GDI_ReleaseObj( hdc );
230 else /* use StretchBlt */
232 HBITMAP hBitmap, hOldBitmap;
233 HPALETTE hpal = NULL;
240 GDI_ReleaseObj( hdc );
242 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
244 ERR("Invalid bitmap\n");
250 ERR("Bitmap has a negative width\n");
254 hdcMem = CreateCompatibleDC( hdc );
255 hBitmap = CreateCompatibleBitmap(hdc, width, height);
256 hOldBitmap = SelectObject( hdcMem, hBitmap );
257 if(wUsage == DIB_PAL_COLORS)
259 hpal = GetCurrentObject(hdc, OBJ_PAL);
260 hpal = SelectPalette(hdcMem, hpal, FALSE);
263 if (info->bmiHeader.biCompression == BI_RLE4 ||
264 info->bmiHeader.biCompression == BI_RLE8) {
266 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
267 * contain all the rectangle described in bmiHeader, but only part of it.
268 * This mean that those undescribed pixels must be left untouched.
269 * So, we first copy on a memory bitmap the current content of the
270 * destination rectangle, blit the DIB bits on top of it - hence leaving
271 * the gaps untouched -, and blitting the rectangle back.
272 * This insure that gaps are untouched on the destination rectangle
273 * Not doing so leads to trashed images (the gaps contain what was on the
274 * memory bitmap => generally black or garbage)
275 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
276 * another speed vs correctness issue. Anyway, if speed is needed, then the
277 * pStretchDIBits function shall be implemented.
281 /* copy existing bitmap from destination dc */
282 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
283 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
287 SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
289 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
290 left (negative biHeight) */
291 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
292 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
293 widthSrc, heightSrc, dwRop );
295 SelectPalette(hdcMem, hpal, FALSE);
296 SelectObject( hdcMem, hOldBitmap );
298 DeleteObject( hBitmap );
304 /******************************************************************************
305 * SetDIBits [GDI32.@]
307 * Sets pixels in a bitmap using colors from DIB.
310 * hdc [I] Handle to device context
311 * hbitmap [I] Handle to bitmap
312 * startscan [I] Starting scan line
313 * lines [I] Number of scan lines
314 * bits [I] Array of bitmap bits
315 * info [I] Address of structure with data
316 * coloruse [I] Type of color indexes to use
319 * Success: Number of scan lines copied
322 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
323 UINT lines, LPCVOID bits, const BITMAPINFO *info,
330 if (!(dc = DC_GetDCUpdate( hdc )))
332 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
336 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
338 GDI_ReleaseObj( hdc );
342 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
344 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
345 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
346 bits, info, coloruse );
351 GDI_ReleaseObj( hbitmap );
352 GDI_ReleaseObj( hdc );
357 /***********************************************************************
358 * SetDIBitsToDevice (GDI32.@)
360 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
361 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
362 UINT lines, LPCVOID bits, const BITMAPINFO *info,
368 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
370 if(dc->funcs->pSetDIBitsToDevice)
371 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
372 ySrc, startscan, lines, bits,
375 FIXME("unimplemented on hdc %p\n", hdc);
379 GDI_ReleaseObj( hdc );
383 /***********************************************************************
384 * SetDIBColorTable (GDI32.@)
386 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
392 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
394 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
396 /* Check if currently selected bitmap is a DIB */
397 if (bitmap->color_table)
399 if (startpos < bitmap->nb_colors)
401 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
402 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
406 GDI_ReleaseObj( dc->hBitmap );
409 if (dc->funcs->pSetDIBColorTable)
410 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
412 GDI_ReleaseObj( hdc );
417 /***********************************************************************
418 * GetDIBColorTable (GDI32.@)
420 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
425 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
427 if (dc->funcs->pGetDIBColorTable)
428 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
431 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
434 /* Check if currently selected bitmap is a DIB */
435 if (bitmap->color_table)
437 if (startpos < bitmap->nb_colors)
439 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
440 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
444 GDI_ReleaseObj( dc->hBitmap );
447 GDI_ReleaseObj( hdc );
451 /* FIXME the following two structs should be combined with __sysPalTemplate in
452 objects/color.c - this should happen after de-X11-ing both of these
454 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
457 static const RGBQUAD EGAColorsQuads[16] = {
458 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
459 { 0x00, 0x00, 0x00, 0x00 },
460 { 0x00, 0x00, 0x80, 0x00 },
461 { 0x00, 0x80, 0x00, 0x00 },
462 { 0x00, 0x80, 0x80, 0x00 },
463 { 0x80, 0x00, 0x00, 0x00 },
464 { 0x80, 0x00, 0x80, 0x00 },
465 { 0x80, 0x80, 0x00, 0x00 },
466 { 0x80, 0x80, 0x80, 0x00 },
467 { 0xc0, 0xc0, 0xc0, 0x00 },
468 { 0x00, 0x00, 0xff, 0x00 },
469 { 0x00, 0xff, 0x00, 0x00 },
470 { 0x00, 0xff, 0xff, 0x00 },
471 { 0xff, 0x00, 0x00, 0x00 },
472 { 0xff, 0x00, 0xff, 0x00 },
473 { 0xff, 0xff, 0x00, 0x00 },
474 { 0xff, 0xff, 0xff, 0x00 }
477 static const RGBTRIPLE EGAColorsTriples[16] = {
478 /* rgbBlue, rgbGreen, rgbRed */
479 { 0x00, 0x00, 0x00 },
480 { 0x00, 0x00, 0x80 },
481 { 0x00, 0x80, 0x00 },
482 { 0x00, 0x80, 0x80 },
483 { 0x80, 0x00, 0x00 },
484 { 0x80, 0x00, 0x80 },
485 { 0x80, 0x80, 0x00 },
486 { 0x80, 0x80, 0x80 },
487 { 0xc0, 0xc0, 0xc0 },
488 { 0x00, 0x00, 0xff },
489 { 0x00, 0xff, 0x00 },
490 { 0x00, 0xff, 0xff },
491 { 0xff, 0x00, 0x00 } ,
492 { 0xff, 0x00, 0xff },
493 { 0xff, 0xff, 0x00 },
497 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
498 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
499 { 0x00, 0x00, 0x00, 0x00 },
500 { 0x00, 0x00, 0x80, 0x00 },
501 { 0x00, 0x80, 0x00, 0x00 },
502 { 0x00, 0x80, 0x80, 0x00 },
503 { 0x80, 0x00, 0x00, 0x00 },
504 { 0x80, 0x00, 0x80, 0x00 },
505 { 0x80, 0x80, 0x00, 0x00 },
506 { 0xc0, 0xc0, 0xc0, 0x00 },
507 { 0xc0, 0xdc, 0xc0, 0x00 },
508 { 0xf0, 0xca, 0xa6, 0x00 },
509 { 0xf0, 0xfb, 0xff, 0x00 },
510 { 0xa4, 0xa0, 0xa0, 0x00 },
511 { 0x80, 0x80, 0x80, 0x00 },
512 { 0x00, 0x00, 0xf0, 0x00 },
513 { 0x00, 0xff, 0x00, 0x00 },
514 { 0x00, 0xff, 0xff, 0x00 },
515 { 0xff, 0x00, 0x00, 0x00 },
516 { 0xff, 0x00, 0xff, 0x00 },
517 { 0xff, 0xff, 0x00, 0x00 },
518 { 0xff, 0xff, 0xff, 0x00 }
521 static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
522 /* rgbBlue, rgbGreen, rgbRed */
523 { 0x00, 0x00, 0x00 },
524 { 0x00, 0x00, 0x80 },
525 { 0x00, 0x80, 0x00 },
526 { 0x00, 0x80, 0x80 },
527 { 0x80, 0x00, 0x00 },
528 { 0x80, 0x00, 0x80 },
529 { 0x80, 0x80, 0x00 },
530 { 0xc0, 0xc0, 0xc0 },
531 { 0xc0, 0xdc, 0xc0 },
532 { 0xf0, 0xca, 0xa6 },
533 { 0xf0, 0xfb, 0xff },
534 { 0xa4, 0xa0, 0xa0 },
535 { 0x80, 0x80, 0x80 },
536 { 0x00, 0x00, 0xf0 },
537 { 0x00, 0xff, 0x00 },
538 { 0x00, 0xff, 0xff },
539 { 0xff, 0x00, 0x00 },
540 { 0xff, 0x00, 0xff },
541 { 0xff, 0xff, 0x00 },
546 /******************************************************************************
547 * GetDIBits [GDI32.@]
549 * Retrieves bits of bitmap and copies to buffer.
552 * Success: Number of scan lines copied from bitmap
555 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
557 INT WINAPI GetDIBits(
558 HDC hdc, /* [in] Handle to device context */
559 HBITMAP hbitmap, /* [in] Handle to bitmap */
560 UINT startscan, /* [in] First scan line to set in dest bitmap */
561 UINT lines, /* [in] Number of scan lines to copy */
562 LPVOID bits, /* [out] Address of array for bitmap bits */
563 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
564 UINT coloruse) /* [in] RGB or palette index */
576 RGBTRIPLE* rgbTriples;
581 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
582 if (bitmap_type == -1)
584 ERR("Invalid bitmap format\n");
587 core_header = (bitmap_type == 0);
588 if (!(dc = DC_GetDCUpdate( hdc )))
592 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
594 GDI_ReleaseObj( hdc );
598 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
599 rgbTriples = (RGBTRIPLE *) colorPtr;
600 rgbQuads = (RGBQUAD *) colorPtr;
602 /* Transfer color info */
604 if (bpp <= 8 && bpp > 0)
606 if (!core_header) info->bmiHeader.biClrUsed = 0;
608 /* If the bitmap object already has a dib section at the
609 same color depth then get the color map from it */
610 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
611 if(coloruse == DIB_RGB_COLORS) {
612 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
616 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
617 RGBTRIPLE* index = rgbTriples;
619 for (i=0; i < colors; i++, index++)
621 index->rgbtRed = bmp->color_table[i].rgbRed;
622 index->rgbtGreen = bmp->color_table[i].rgbGreen;
623 index->rgbtBlue = bmp->color_table[i].rgbBlue;
628 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
629 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
633 WORD *index = colorPtr;
634 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
639 if(bpp >= bmp->bitmap.bmBitsPixel) {
640 /* Generate the color map from the selected palette */
641 PALETTEENTRY * palEntry;
642 PALETTEOBJ * palette;
643 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
644 GDI_ReleaseObj( hdc );
645 GDI_ReleaseObj( hbitmap );
648 palEntry = palette->logpalette.palPalEntry;
649 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
650 if (coloruse == DIB_RGB_COLORS) {
653 rgbTriples[i].rgbtRed = palEntry->peRed;
654 rgbTriples[i].rgbtGreen = palEntry->peGreen;
655 rgbTriples[i].rgbtBlue = palEntry->peBlue;
659 rgbQuads[i].rgbRed = palEntry->peRed;
660 rgbQuads[i].rgbGreen = palEntry->peGreen;
661 rgbQuads[i].rgbBlue = palEntry->peBlue;
662 rgbQuads[i].rgbReserved = 0;
665 else ((WORD *)colorPtr)[i] = (WORD)i;
667 GDI_ReleaseObj( dc->hPalette );
673 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
674 rgbTriples[0].rgbtBlue = 0;
675 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
676 rgbTriples[1].rgbtBlue = 0xff;
680 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
681 rgbQuads[0].rgbBlue = 0;
682 rgbQuads[0].rgbReserved = 0;
683 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
684 rgbQuads[1].rgbBlue = 0xff;
685 rgbQuads[1].rgbReserved = 0;
691 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
693 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
704 memcpy(rgbTriples, DefLogPaletteTriples,
705 10 * sizeof(RGBTRIPLE));
706 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
707 10 * sizeof(RGBTRIPLE));
708 color = rgbTriples + 10;
709 for(r = 0; r <= 5; r++) /* FIXME */
710 for(g = 0; g <= 5; g++)
711 for(b = 0; b <= 5; b++) {
712 color->rgbtRed = (r * 0xff) / 5;
713 color->rgbtGreen = (g * 0xff) / 5;
714 color->rgbtBlue = (b * 0xff) / 5;
723 memcpy(rgbQuads, DefLogPaletteQuads,
724 10 * sizeof(RGBQUAD));
725 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
726 10 * sizeof(RGBQUAD));
727 color = rgbQuads + 10;
728 for(r = 0; r <= 5; r++) /* FIXME */
729 for(g = 0; g <= 5; g++)
730 for(b = 0; b <= 5; b++) {
731 color->rgbRed = (r * 0xff) / 5;
732 color->rgbGreen = (g * 0xff) / 5;
733 color->rgbBlue = (b * 0xff) / 5;
734 color->rgbReserved = 0;
746 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
747 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
749 /*FIXME: Only RGB dibs supported for now */
750 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
751 unsigned int dstwidth = width;
752 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
753 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
754 unsigned int x, y, width, widthb;
756 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
758 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
759 dstwidthb = -dstwidthb;
765 case 16: /* 16 bpp dstDIB */
767 LPWORD dstbits = (LPWORD)dbits;
768 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
770 /* FIXME: BI_BITFIELDS not supported yet */
772 switch(bmp->dib->dsBm.bmBitsPixel) {
774 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
776 widthb = min(srcwidthb, abs(dstwidthb));
777 /* FIXME: BI_BITFIELDS not supported yet */
778 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
779 memcpy(dbits, sbits, widthb);
783 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
785 LPBYTE srcbits = sbits;
787 width = min(srcwidth, dstwidth);
788 for( y = 0; y < lines; y++) {
789 for( x = 0; x < width; x++, srcbits += 3)
790 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
791 (((WORD)srcbits[1] << 2) & gmask) |
792 (((WORD)srcbits[2] << 7) & rmask);
794 dstbits = (LPWORD)(dbits+=dstwidthb);
795 srcbits = (sbits += srcwidthb);
800 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
802 LPDWORD srcbits = (LPDWORD)sbits;
805 width = min(srcwidth, dstwidth);
806 for( y = 0; y < lines; y++) {
807 for( x = 0; x < width; x++ ) {
809 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
810 ((val >> 9) & rmask));
812 dstbits = (LPWORD)(dbits+=dstwidthb);
813 srcbits = (LPDWORD)(sbits+=srcwidthb);
818 default: /* ? bit bmp -> 16 bit DIB */
819 FIXME("15/16 bit DIB %d bit bitmap\n",
820 bmp->bitmap.bmBitsPixel);
826 case 24: /* 24 bpp dstDIB */
828 LPBYTE dstbits = dbits;
830 switch(bmp->dib->dsBm.bmBitsPixel) {
832 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
834 LPWORD srcbits = (LPWORD)sbits;
837 width = min(srcwidth, dstwidth);
838 /* FIXME: BI_BITFIELDS not supported yet */
839 for( y = 0; y < lines; y++) {
840 for( x = 0; x < width; x++ ) {
842 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
843 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
844 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
846 dstbits = (LPBYTE)(dbits+=dstwidthb);
847 srcbits = (LPWORD)(sbits+=srcwidthb);
852 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
854 widthb = min(srcwidthb, abs(dstwidthb));
855 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
856 memcpy(dbits, sbits, widthb);
860 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
862 LPBYTE srcbits = (LPBYTE)sbits;
864 width = min(srcwidth, dstwidth);
865 for( y = 0; y < lines; y++) {
866 for( x = 0; x < width; x++, srcbits++ ) {
867 *dstbits++ = *srcbits++;
868 *dstbits++ = *srcbits++;
869 *dstbits++ = *srcbits++;
871 dstbits=(LPBYTE)(dbits+=dstwidthb);
872 srcbits = (LPBYTE)(sbits+=srcwidthb);
877 default: /* ? bit bmp -> 24 bit DIB */
878 FIXME("24 bit DIB %d bit bitmap\n",
879 bmp->bitmap.bmBitsPixel);
885 case 32: /* 32 bpp dstDIB */
887 LPDWORD dstbits = (LPDWORD)dbits;
889 /* FIXME: BI_BITFIELDS not supported yet */
891 switch(bmp->dib->dsBm.bmBitsPixel) {
892 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
894 LPWORD srcbits = (LPWORD)sbits;
897 width = min(srcwidth, dstwidth);
898 /* FIXME: BI_BITFIELDS not supported yet */
899 for( y = 0; y < lines; y++) {
900 for( x = 0; x < width; x++ ) {
901 val = (DWORD)*srcbits++;
902 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
903 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
904 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
906 dstbits=(LPDWORD)(dbits+=dstwidthb);
907 srcbits=(LPWORD)(sbits+=srcwidthb);
912 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
914 LPBYTE srcbits = sbits;
916 width = min(srcwidth, dstwidth);
917 for( y = 0; y < lines; y++) {
918 for( x = 0; x < width; x++, srcbits+=3 )
919 *dstbits++ = srcbits[0] |
922 dstbits=(LPDWORD)(dbits+=dstwidthb);
923 srcbits=(sbits+=srcwidthb);
928 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
930 widthb = min(srcwidthb, abs(dstwidthb));
931 /* FIXME: BI_BITFIELDS not supported yet */
932 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
933 memcpy(dbits, sbits, widthb);
938 default: /* ? bit bmp -> 32 bit DIB */
939 FIXME("32 bit DIB %d bit bitmap\n",
940 bmp->bitmap.bmBitsPixel);
946 default: /* ? bit DIB */
947 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
951 /* Otherwise, get bits from the XImage */
954 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
957 if (bmp->funcs && bmp->funcs->pGetDIBits)
958 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
959 lines, bits, info, coloruse );
961 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
967 /* fill in struct members */
973 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
974 coreheader->bcWidth = bmp->bitmap.bmWidth;
975 coreheader->bcHeight = bmp->bitmap.bmHeight;
976 coreheader->bcPlanes = 1;
977 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
981 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
982 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
983 info->bmiHeader.biPlanes = 1;
984 info->bmiHeader.biSizeImage =
985 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
986 bmp->bitmap.bmHeight,
987 bmp->bitmap.bmBitsPixel );
988 switch(bmp->bitmap.bmBitsPixel)
991 info->bmiHeader.biBitCount = 16;
992 info->bmiHeader.biCompression = BI_RGB;
996 info->bmiHeader.biBitCount = 16;
997 info->bmiHeader.biCompression = BI_BITFIELDS;
998 ((PDWORD)info->bmiColors)[0] = 0xf800;
999 ((PDWORD)info->bmiColors)[1] = 0x07e0;
1000 ((PDWORD)info->bmiColors)[2] = 0x001f;
1004 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
1005 info->bmiHeader.biCompression = BI_RGB;
1008 info->bmiHeader.biXPelsPerMeter = 0;
1009 info->bmiHeader.biYPelsPerMeter = 0;
1010 info->bmiHeader.biClrUsed = 0;
1011 info->bmiHeader.biClrImportant = 0;
1013 /* Windows 2000 doesn't touch the additional struct members if
1014 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
1016 lines = abs(bmp->bitmap.bmHeight);
1020 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1021 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1025 /* FIXME: biSizeImage should be calculated according to the selected
1026 compression algorithm if biCompression != BI_RGB */
1027 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1029 lines = abs(height);
1035 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
1037 TRACE("biWidth = %d, biHeight = %d\n", width, height);
1039 GDI_ReleaseObj( hdc );
1040 GDI_ReleaseObj( hbitmap );
1045 /***********************************************************************
1046 * CreateDIBitmap (GDI32.@)
1048 * Creates a DDB (device dependent bitmap) from a DIB.
1049 * The DDB will have the same color depth as the reference DC.
1051 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1052 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1062 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1066 TRACE("Bitmap has a negative width\n");
1070 /* Top-down DIBs have a negative height */
1071 if (height < 0) height = -height;
1073 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1074 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1077 handle = CreateBitmap( width, height, 1, 1, NULL );
1079 handle = CreateCompatibleBitmap( hdc, width, height );
1083 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1085 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1087 if (!BITMAP_SetOwnerDC( handle, dc ))
1089 DeleteObject( handle );
1092 GDI_ReleaseObj( hdc );
1099 /***********************************************************************
1100 * CreateDIBSection (GDI.489)
1102 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1103 SEGPTR *bits16, HANDLE section, DWORD offset)
1108 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1111 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1112 if (bmp && bmp->dib && bits32)
1114 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1122 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1124 height = height >= 0 ? height : -height;
1125 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1127 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1129 /* calculate number of sel's needed for size with 64K steps */
1130 count = (size + 0xffff) / 0x10000;
1131 sel = AllocSelectorArray16(count);
1133 for (i = 0; i < count; i++)
1135 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1136 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1139 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1140 if (bits16) *bits16 = bmp->segptr_bits;
1142 if (bmp) GDI_ReleaseObj( hbitmap );
1144 return HBITMAP_16(hbitmap);
1147 /* Copy/synthetize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
1148 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1150 RGBQUAD *colorTable;
1151 unsigned int colors;
1153 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1157 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1161 colors = info->bmiHeader.biClrUsed;
1162 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1166 ERR("called with >256 colors!\n");
1170 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1172 if(coloruse == DIB_RGB_COLORS)
1176 /* Convert RGBTRIPLEs to RGBQUADs */
1177 for (i=0; i < colors; i++)
1179 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1180 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1181 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1182 colorTable[i].rgbReserved = 0;
1187 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1192 PALETTEOBJ *palette;
1193 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
1195 if ((palette = GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
1197 UINT entries = palette->logpalette.palNumEntries;
1198 for (i = 0; i < colors; i++, index++)
1200 PALETTEENTRY *entry = &palette->logpalette.palPalEntry[*index % entries];
1201 colorTable[i].rgbRed = entry->peRed;
1202 colorTable[i].rgbGreen = entry->peGreen;
1203 colorTable[i].rgbBlue = entry->peBlue;
1204 colorTable[i].rgbReserved = 0;
1206 GDI_ReleaseObj( dc->hPalette );
1209 bmp->color_table = colorTable;
1210 bmp->nb_colors = colors;
1213 /***********************************************************************
1214 * CreateDIBSection (GDI32.@)
1216 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1217 VOID **bits, HANDLE section, DWORD offset)
1221 BOOL bDesktopDC = FALSE;
1227 DWORD compression, sizeImage;
1228 void *mapBits = NULL;
1230 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1231 &planes, &bpp, &compression, &sizeImage )) == -1))
1234 if (compression != BI_RGB && compression != BI_BITFIELDS)
1236 TRACE("can't create a compressed (%u) dibsection\n", compression);
1240 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1242 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
1243 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1245 dib->dsBm.bmType = 0;
1246 dib->dsBm.bmWidth = width;
1247 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1248 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
1249 dib->dsBm.bmPlanes = planes;
1250 dib->dsBm.bmBitsPixel = bpp;
1251 dib->dsBm.bmBits = NULL;
1253 if (!bitmap_type) /* core header */
1255 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1256 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1257 dib->dsBmih.biWidth = width;
1258 dib->dsBmih.biHeight = height;
1259 dib->dsBmih.biPlanes = planes;
1260 dib->dsBmih.biBitCount = bpp;
1261 dib->dsBmih.biCompression = compression;
1262 dib->dsBmih.biXPelsPerMeter = 0;
1263 dib->dsBmih.biYPelsPerMeter = 0;
1264 dib->dsBmih.biClrUsed = 0;
1265 dib->dsBmih.biClrImportant = 0;
1269 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1270 dib->dsBmih = bmi->bmiHeader;
1271 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1274 /* set number of entries in bmi.bmiColors table */
1276 dib->dsBmih.biClrUsed = 1 << bpp;
1278 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1280 /* set dsBitfields values */
1281 if (usage == DIB_PAL_COLORS || bpp <= 8)
1283 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1289 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1290 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1291 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1295 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1296 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1297 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1301 /* get storage location for DIB bits */
1305 SYSTEM_INFO SystemInfo;
1309 GetSystemInfo( &SystemInfo );
1310 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1311 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1312 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1313 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1318 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1319 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1321 dib->dshSection = section;
1322 dib->dsOffset = offset;
1324 if (!dib->dsBm.bmBits)
1326 HeapFree( GetProcessHeap(), 0, dib );
1330 /* If the reference hdc is null, take the desktop dc */
1333 hdc = CreateCompatibleDC(0);
1337 if (!(dc = DC_GetDCPtr( hdc ))) goto error;
1339 /* create Device Dependent Bitmap and add DIB pointer */
1340 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1341 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1343 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1346 bmp->funcs = dc->funcs;
1347 /* create local copy of DIB palette */
1348 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
1349 GDI_ReleaseObj( ret );
1351 if (dc->funcs->pCreateDIBSection)
1353 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1355 DeleteObject( ret );
1361 GDI_ReleaseObj(hdc);
1362 if (bDesktopDC) DeleteDC( hdc );
1363 if (ret && bits) *bits = dib->dsBm.bmBits;
1367 if (bDesktopDC) DeleteDC( hdc );
1368 if (section) UnmapViewOfFile( mapBits );
1369 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1370 HeapFree( GetProcessHeap(), 0, dib );