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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
47 * You should never access the color table using the bmiColors member,
48 because the passed structure may have one of the extended headers
49 mentioned above. Use this to calculate the location:
52 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
56 Search for "Bitmap Structures" in MSDN
67 #include "gdi_private.h"
68 #include "wine/debug.h"
70 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
74 Some of the following helper functions are duplicated in
78 /***********************************************************************
79 * DIB_GetDIBWidthBytes
81 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
82 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
84 int DIB_GetDIBWidthBytes( int width, int depth )
90 case 1: words = (width + 31) / 32; break;
91 case 4: words = (width + 7) / 8; break;
92 case 8: words = (width + 3) / 4; break;
94 case 16: words = (width + 1) / 2; break;
95 case 24: words = (width * 3 + 3)/4; break;
98 WARN("(%d): Unsupported depth\n", depth );
106 /***********************************************************************
107 * DIB_GetDIBImageBytes
109 * Return the number of bytes used to hold the image in a DIB bitmap.
111 int DIB_GetDIBImageBytes( int width, int height, int depth )
113 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
117 /***********************************************************************
120 * Return the size of the bitmap info structure including color table.
122 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
126 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
128 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
129 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
130 return sizeof(BITMAPCOREHEADER) + colors *
131 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
133 else /* assume BITMAPINFOHEADER */
135 colors = info->bmiHeader.biClrUsed;
136 if (colors > 256) colors = 256;
137 if (!colors && (info->bmiHeader.biBitCount <= 8))
138 colors = 1 << info->bmiHeader.biBitCount;
139 return sizeof(BITMAPINFOHEADER) + colors *
140 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
145 /***********************************************************************
148 * Get the info from a bitmap header.
149 * Return 1 for INFOHEADER, 0 for COREHEADER,
150 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
152 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
153 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
155 if (header->biSize == sizeof(BITMAPINFOHEADER))
157 *width = header->biWidth;
158 *height = header->biHeight;
159 *planes = header->biPlanes;
160 *bpp = header->biBitCount;
161 *compr = header->biCompression;
162 *size = header->biSizeImage;
165 if (header->biSize == sizeof(BITMAPCOREHEADER))
167 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
168 *width = core->bcWidth;
169 *height = core->bcHeight;
170 *planes = core->bcPlanes;
171 *bpp = core->bcBitCount;
176 if (header->biSize == sizeof(BITMAPV4HEADER))
178 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
179 *width = v4hdr->bV4Width;
180 *height = v4hdr->bV4Height;
181 *planes = v4hdr->bV4Planes;
182 *bpp = v4hdr->bV4BitCount;
183 *compr = v4hdr->bV4V4Compression;
184 *size = v4hdr->bV4SizeImage;
187 if (header->biSize == sizeof(BITMAPV5HEADER))
189 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
190 *width = v5hdr->bV5Width;
191 *height = v5hdr->bV5Height;
192 *planes = v5hdr->bV5Planes;
193 *bpp = v5hdr->bV5BitCount;
194 *compr = v5hdr->bV5Compression;
195 *size = v5hdr->bV5SizeImage;
198 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
203 /***********************************************************************
204 * StretchDIBits (GDI32.@)
206 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
207 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
208 INT heightSrc, const void *bits,
209 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
216 dc = DC_GetDCUpdate( hdc );
217 if(!dc) return FALSE;
219 if(dc->funcs->pStretchDIBits)
221 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
222 heightDst, xSrc, ySrc, widthSrc,
223 heightSrc, bits, info, wUsage, dwRop);
224 GDI_ReleaseObj( hdc );
226 else /* use StretchBlt */
228 HBITMAP hBitmap, hOldBitmap;
229 HPALETTE hpal = NULL;
236 GDI_ReleaseObj( hdc );
238 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
240 ERR("Invalid bitmap\n");
246 ERR("Bitmap has a negative width\n");
250 hdcMem = CreateCompatibleDC( hdc );
251 hBitmap = CreateCompatibleBitmap(hdc, width, height);
252 hOldBitmap = SelectObject( hdcMem, hBitmap );
253 if(wUsage == DIB_PAL_COLORS)
255 hpal = GetCurrentObject(hdc, OBJ_PAL);
256 hpal = SelectPalette(hdcMem, hpal, FALSE);
259 if (info->bmiHeader.biCompression == BI_RLE4 ||
260 info->bmiHeader.biCompression == BI_RLE8) {
262 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
263 * contain all the rectangle described in bmiHeader, but only part of it.
264 * This mean that those undescribed pixels must be left untouched.
265 * So, we first copy on a memory bitmap the current content of the
266 * destination rectangle, blit the DIB bits on top of it - hence leaving
267 * the gaps untouched -, and blitting the rectangle back.
268 * This insure that gaps are untouched on the destination rectangle
269 * Not doing so leads to trashed images (the gaps contain what was on the
270 * memory bitmap => generally black or garbage)
271 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
272 * another speed vs correctness issue. Anyway, if speed is needed, then the
273 * pStretchDIBits function shall be implemented.
277 /* copy existing bitmap from destination dc */
278 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
279 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
283 SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
285 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
286 left (negative biHeight) */
287 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
288 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
289 widthSrc, heightSrc, dwRop );
291 SelectPalette(hdcMem, hpal, FALSE);
292 SelectObject( hdcMem, hOldBitmap );
294 DeleteObject( hBitmap );
300 /******************************************************************************
301 * SetDIBits [GDI32.@]
303 * Sets pixels in a bitmap using colors from DIB.
306 * hdc [I] Handle to device context
307 * hbitmap [I] Handle to bitmap
308 * startscan [I] Starting scan line
309 * lines [I] Number of scan lines
310 * bits [I] Array of bitmap bits
311 * info [I] Address of structure with data
312 * coloruse [I] Type of color indexes to use
315 * Success: Number of scan lines copied
318 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
319 UINT lines, LPCVOID bits, const BITMAPINFO *info,
326 if (!(dc = DC_GetDCUpdate( hdc )))
328 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
332 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
334 GDI_ReleaseObj( hdc );
338 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
340 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
341 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
342 bits, info, coloruse );
347 GDI_ReleaseObj( hbitmap );
348 GDI_ReleaseObj( hdc );
353 /***********************************************************************
354 * SetDIBitsToDevice (GDI32.@)
356 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
357 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
358 UINT lines, LPCVOID bits, const BITMAPINFO *info,
364 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
366 if(dc->funcs->pSetDIBitsToDevice)
367 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
368 ySrc, startscan, lines, bits,
371 FIXME("unimplemented on hdc %p\n", hdc);
375 GDI_ReleaseObj( hdc );
379 /***********************************************************************
380 * SetDIBColorTable (GDI32.@)
382 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
387 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
389 if (dc->funcs->pSetDIBColorTable)
390 result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
392 GDI_ReleaseObj( hdc );
397 /***********************************************************************
398 * GetDIBColorTable (GDI32.@)
400 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
405 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
407 if (dc->funcs->pGetDIBColorTable)
408 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
410 GDI_ReleaseObj( hdc );
414 /* FIXME the following two structs should be combined with __sysPalTemplate in
415 objects/color.c - this should happen after de-X11-ing both of these
417 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
420 static RGBQUAD EGAColorsQuads[16] = {
421 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
422 { 0x00, 0x00, 0x00, 0x00 },
423 { 0x00, 0x00, 0x80, 0x00 },
424 { 0x00, 0x80, 0x00, 0x00 },
425 { 0x00, 0x80, 0x80, 0x00 },
426 { 0x80, 0x00, 0x00, 0x00 },
427 { 0x80, 0x00, 0x80, 0x00 },
428 { 0x80, 0x80, 0x00, 0x00 },
429 { 0x80, 0x80, 0x80, 0x00 },
430 { 0xc0, 0xc0, 0xc0, 0x00 },
431 { 0x00, 0x00, 0xff, 0x00 },
432 { 0x00, 0xff, 0x00, 0x00 },
433 { 0x00, 0xff, 0xff, 0x00 },
434 { 0xff, 0x00, 0x00, 0x00 },
435 { 0xff, 0x00, 0xff, 0x00 },
436 { 0xff, 0xff, 0x00, 0x00 },
437 { 0xff, 0xff, 0xff, 0x00 }
440 static RGBTRIPLE EGAColorsTriples[16] = {
441 /* rgbBlue, rgbGreen, rgbRed */
442 { 0x00, 0x00, 0x00 },
443 { 0x00, 0x00, 0x80 },
444 { 0x00, 0x80, 0x00 },
445 { 0x00, 0x80, 0x80 },
446 { 0x80, 0x00, 0x00 },
447 { 0x80, 0x00, 0x80 },
448 { 0x80, 0x80, 0x00 },
449 { 0x80, 0x80, 0x80 },
450 { 0xc0, 0xc0, 0xc0 },
451 { 0x00, 0x00, 0xff },
452 { 0x00, 0xff, 0x00 },
453 { 0x00, 0xff, 0xff },
454 { 0xff, 0x00, 0x00 } ,
455 { 0xff, 0x00, 0xff },
456 { 0xff, 0xff, 0x00 },
460 static RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
461 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
462 { 0x00, 0x00, 0x00, 0x00 },
463 { 0x00, 0x00, 0x80, 0x00 },
464 { 0x00, 0x80, 0x00, 0x00 },
465 { 0x00, 0x80, 0x80, 0x00 },
466 { 0x80, 0x00, 0x00, 0x00 },
467 { 0x80, 0x00, 0x80, 0x00 },
468 { 0x80, 0x80, 0x00, 0x00 },
469 { 0xc0, 0xc0, 0xc0, 0x00 },
470 { 0xc0, 0xdc, 0xc0, 0x00 },
471 { 0xf0, 0xca, 0xa6, 0x00 },
472 { 0xf0, 0xfb, 0xff, 0x00 },
473 { 0xa4, 0xa0, 0xa0, 0x00 },
474 { 0x80, 0x80, 0x80, 0x00 },
475 { 0x00, 0x00, 0xf0, 0x00 },
476 { 0x00, 0xff, 0x00, 0x00 },
477 { 0x00, 0xff, 0xff, 0x00 },
478 { 0xff, 0x00, 0x00, 0x00 },
479 { 0xff, 0x00, 0xff, 0x00 },
480 { 0xff, 0xff, 0x00, 0x00 },
481 { 0xff, 0xff, 0xff, 0x00 }
484 static RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
485 /* rgbBlue, rgbGreen, rgbRed */
486 { 0x00, 0x00, 0x00 },
487 { 0x00, 0x00, 0x80 },
488 { 0x00, 0x80, 0x00 },
489 { 0x00, 0x80, 0x80 },
490 { 0x80, 0x00, 0x00 },
491 { 0x80, 0x00, 0x80 },
492 { 0x80, 0x80, 0x00 },
493 { 0xc0, 0xc0, 0xc0 },
494 { 0xc0, 0xdc, 0xc0 },
495 { 0xf0, 0xca, 0xa6 },
496 { 0xf0, 0xfb, 0xff },
497 { 0xa4, 0xa0, 0xa0 },
498 { 0x80, 0x80, 0x80 },
499 { 0x00, 0x00, 0xf0 },
500 { 0x00, 0xff, 0x00 },
501 { 0x00, 0xff, 0xff },
502 { 0xff, 0x00, 0x00 },
503 { 0xff, 0x00, 0xff },
504 { 0xff, 0xff, 0x00 },
509 /******************************************************************************
510 * GetDIBits [GDI32.@]
512 * Retrieves bits of bitmap and copies to buffer.
515 * Success: Number of scan lines copied from bitmap
518 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
520 INT WINAPI GetDIBits(
521 HDC hdc, /* [in] Handle to device context */
522 HBITMAP hbitmap, /* [in] Handle to bitmap */
523 UINT startscan, /* [in] First scan line to set in dest bitmap */
524 UINT lines, /* [in] Number of scan lines to copy */
525 LPVOID bits, /* [out] Address of array for bitmap bits */
526 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
527 UINT coloruse) /* [in] RGB or palette index */
540 RGBTRIPLE* rgbTriples;
545 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
546 if (bitmap_type == -1)
548 ERR("Invalid bitmap format\n");
551 core_header = (bitmap_type == 0);
552 memdc = CreateCompatibleDC(hdc);
553 if (!(dc = DC_GetDCUpdate( hdc )))
558 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
560 GDI_ReleaseObj( hdc );
565 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
566 rgbTriples = (RGBTRIPLE *) colorPtr;
567 rgbQuads = (RGBQUAD *) colorPtr;
569 /* Transfer color info */
571 if (bpp <= 8 && bpp > 0)
573 if (!core_header) info->bmiHeader.biClrUsed = 0;
575 /* If the bitmap object already has a dib section at the
576 same color depth then get the color map from it */
577 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
578 if(coloruse == DIB_RGB_COLORS) {
579 HBITMAP oldbm = SelectObject(memdc, hbitmap);
580 unsigned int colors = 1 << bpp;
584 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
585 RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
589 RGBTRIPLE* index = rgbTriples;
590 GetDIBColorTable(memdc, 0, colors, buffer);
592 for (i=0; i < colors; i++, index++)
594 index->rgbtRed = buffer[i].rgbRed;
595 index->rgbtGreen = buffer[i].rgbGreen;
596 index->rgbtBlue = buffer[i].rgbBlue;
599 HeapFree(GetProcessHeap(), 0, buffer);
604 GetDIBColorTable(memdc, 0, colors, colorPtr);
606 SelectObject(memdc, oldbm);
609 WORD *index = colorPtr;
610 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
615 if(bpp >= bmp->bitmap.bmBitsPixel) {
616 /* Generate the color map from the selected palette */
617 PALETTEENTRY * palEntry;
618 PALETTEOBJ * palette;
619 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
620 GDI_ReleaseObj( hdc );
621 GDI_ReleaseObj( hbitmap );
625 palEntry = palette->logpalette.palPalEntry;
626 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
627 if (coloruse == DIB_RGB_COLORS) {
630 rgbTriples[i].rgbtRed = palEntry->peRed;
631 rgbTriples[i].rgbtGreen = palEntry->peGreen;
632 rgbTriples[i].rgbtBlue = palEntry->peBlue;
636 rgbQuads[i].rgbRed = palEntry->peRed;
637 rgbQuads[i].rgbGreen = palEntry->peGreen;
638 rgbQuads[i].rgbBlue = palEntry->peBlue;
639 rgbQuads[i].rgbReserved = 0;
642 else ((WORD *)colorPtr)[i] = (WORD)i;
644 GDI_ReleaseObj( dc->hPalette );
650 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
651 rgbTriples[0].rgbtBlue = 0;
652 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
653 rgbTriples[1].rgbtBlue = 0xff;
657 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
658 rgbQuads[0].rgbBlue = 0;
659 rgbQuads[0].rgbReserved = 0;
660 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
661 rgbQuads[1].rgbBlue = 0xff;
662 rgbQuads[1].rgbReserved = 0;
668 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
670 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
681 memcpy(rgbTriples, DefLogPaletteTriples,
682 10 * sizeof(RGBTRIPLE));
683 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
684 10 * sizeof(RGBTRIPLE));
685 color = rgbTriples + 10;
686 for(r = 0; r <= 5; r++) /* FIXME */
687 for(g = 0; g <= 5; g++)
688 for(b = 0; b <= 5; b++) {
689 color->rgbtRed = (r * 0xff) / 5;
690 color->rgbtGreen = (g * 0xff) / 5;
691 color->rgbtBlue = (b * 0xff) / 5;
700 memcpy(rgbQuads, DefLogPaletteQuads,
701 10 * sizeof(RGBQUAD));
702 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
703 10 * sizeof(RGBQUAD));
704 color = rgbQuads + 10;
705 for(r = 0; r <= 5; r++) /* FIXME */
706 for(g = 0; g <= 5; g++)
707 for(b = 0; b <= 5; b++) {
708 color->rgbRed = (r * 0xff) / 5;
709 color->rgbGreen = (g * 0xff) / 5;
710 color->rgbBlue = (b * 0xff) / 5;
711 color->rgbReserved = 0;
723 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
724 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
726 /*FIXME: Only RGB dibs supported for now */
727 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
728 unsigned int dstwidth = width;
729 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
730 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
731 unsigned int x, y, width, widthb;
733 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
735 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
736 dstwidthb = -dstwidthb;
742 case 16: /* 16 bpp dstDIB */
744 LPWORD dstbits = (LPWORD)dbits;
745 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
747 /* FIXME: BI_BITFIELDS not supported yet */
749 switch(bmp->dib->dsBm.bmBitsPixel) {
751 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
753 widthb = min(srcwidthb, abs(dstwidthb));
754 /* FIXME: BI_BITFIELDS not supported yet */
755 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
756 memcpy(dbits, sbits, widthb);
760 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
762 LPBYTE srcbits = sbits;
764 width = min(srcwidth, dstwidth);
765 for( y = 0; y < lines; y++) {
766 for( x = 0; x < width; x++, srcbits += 3)
767 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
768 (((WORD)srcbits[1] << 2) & gmask) |
769 (((WORD)srcbits[2] << 7) & rmask);
771 dstbits = (LPWORD)(dbits+=dstwidthb);
772 srcbits = (sbits += srcwidthb);
777 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
779 LPDWORD srcbits = (LPDWORD)sbits;
782 width = min(srcwidth, dstwidth);
783 for( y = 0; y < lines; y++) {
784 for( x = 0; x < width; x++ ) {
786 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
787 ((val >> 9) & rmask));
789 dstbits = (LPWORD)(dbits+=dstwidthb);
790 srcbits = (LPDWORD)(sbits+=srcwidthb);
795 default: /* ? bit bmp -> 16 bit DIB */
796 FIXME("15/16 bit DIB %d bit bitmap\n",
797 bmp->bitmap.bmBitsPixel);
803 case 24: /* 24 bpp dstDIB */
805 LPBYTE dstbits = dbits;
807 switch(bmp->dib->dsBm.bmBitsPixel) {
809 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
811 LPWORD srcbits = (LPWORD)sbits;
814 width = min(srcwidth, dstwidth);
815 /* FIXME: BI_BITFIELDS not supported yet */
816 for( y = 0; y < lines; y++) {
817 for( x = 0; x < width; x++ ) {
819 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
820 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
821 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
823 dstbits = (LPBYTE)(dbits+=dstwidthb);
824 srcbits = (LPWORD)(sbits+=srcwidthb);
829 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
831 widthb = min(srcwidthb, abs(dstwidthb));
832 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
833 memcpy(dbits, sbits, widthb);
837 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
839 LPBYTE srcbits = (LPBYTE)sbits;
841 width = min(srcwidth, dstwidth);
842 for( y = 0; y < lines; y++) {
843 for( x = 0; x < width; x++, srcbits++ ) {
844 *dstbits++ = *srcbits++;
845 *dstbits++ = *srcbits++;
846 *dstbits++ = *srcbits++;
848 dstbits=(LPBYTE)(dbits+=dstwidthb);
849 srcbits = (LPBYTE)(sbits+=srcwidthb);
854 default: /* ? bit bmp -> 24 bit DIB */
855 FIXME("24 bit DIB %d bit bitmap\n",
856 bmp->bitmap.bmBitsPixel);
862 case 32: /* 32 bpp dstDIB */
864 LPDWORD dstbits = (LPDWORD)dbits;
866 /* FIXME: BI_BITFIELDS not supported yet */
868 switch(bmp->dib->dsBm.bmBitsPixel) {
869 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
871 LPWORD srcbits = (LPWORD)sbits;
874 width = min(srcwidth, dstwidth);
875 /* FIXME: BI_BITFIELDS not supported yet */
876 for( y = 0; y < lines; y++) {
877 for( x = 0; x < width; x++ ) {
878 val = (DWORD)*srcbits++;
879 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
880 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
881 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
883 dstbits=(LPDWORD)(dbits+=dstwidthb);
884 srcbits=(LPWORD)(sbits+=srcwidthb);
889 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
891 LPBYTE srcbits = sbits;
893 width = min(srcwidth, dstwidth);
894 for( y = 0; y < lines; y++) {
895 for( x = 0; x < width; x++, srcbits+=3 )
896 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
897 dstbits=(LPDWORD)(dbits+=dstwidthb);
898 srcbits=(sbits+=srcwidthb);
903 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
905 widthb = min(srcwidthb, abs(dstwidthb));
906 /* FIXME: BI_BITFIELDS not supported yet */
907 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
908 memcpy(dbits, sbits, widthb);
913 default: /* ? bit bmp -> 32 bit DIB */
914 FIXME("32 bit DIB %d bit bitmap\n",
915 bmp->bitmap.bmBitsPixel);
921 default: /* ? bit DIB */
922 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
926 /* Otherwise, get bits from the XImage */
929 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
932 if (bmp->funcs && bmp->funcs->pGetDIBits)
933 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
934 lines, bits, info, coloruse );
936 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
942 /* fill in struct members */
948 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
949 coreheader->bcWidth = bmp->bitmap.bmWidth;
950 coreheader->bcHeight = bmp->bitmap.bmHeight;
951 coreheader->bcPlanes = 1;
952 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
956 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
957 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
958 info->bmiHeader.biPlanes = 1;
959 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
960 info->bmiHeader.biSizeImage =
961 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
962 bmp->bitmap.bmHeight,
963 bmp->bitmap.bmBitsPixel );
964 info->bmiHeader.biCompression = 0;
965 info->bmiHeader.biXPelsPerMeter = 0;
966 info->bmiHeader.biYPelsPerMeter = 0;
967 info->bmiHeader.biClrUsed = 0;
968 info->bmiHeader.biClrImportant = 0;
970 /* Windows 2000 doesn't touch the additional struct members if
971 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
973 lines = abs(bmp->bitmap.bmHeight);
977 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
978 if bits == NULL and bpp != 0, only biSizeImage and the color table are
982 /* FIXME: biSizeImage should be calculated according to the selected
983 compression algorithm if biCompression != BI_RGB */
984 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
992 TRACE("biSizeImage = %ld, ", info->bmiHeader.biSizeImage);
994 TRACE("biWidth = %ld, biHeight = %ld\n", width, height);
996 GDI_ReleaseObj( hdc );
997 GDI_ReleaseObj( hbitmap );
1003 /***********************************************************************
1004 * CreateDIBitmap (GDI32.@)
1006 * Creates a DDB (device dependent bitmap) from a DIB.
1007 * The DDB will have the same color depth as the reference DC.
1009 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1010 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1020 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1024 TRACE("Bitmap has a negative width\n");
1028 /* Top-down DIBs have a negative height */
1029 if (height < 0) height = -height;
1031 TRACE("hdc=%p, header=%p, init=%lu, bits=%p, data=%p, coloruse=%u (bitmap: width=%ld, height=%ld, bpp=%u, compr=%lu)\n",
1032 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1035 handle = CreateBitmap( width, height, 1, 1, NULL );
1037 handle = CreateCompatibleBitmap( hdc, width, height );
1041 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1043 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1045 if (!BITMAP_SetOwnerDC( handle, dc ))
1047 DeleteObject( handle );
1050 GDI_ReleaseObj( hdc );
1057 /***********************************************************************
1058 * CreateDIBSection (GDI.489)
1060 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1061 SEGPTR *bits16, HANDLE section, DWORD offset)
1066 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1069 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1070 if (bmp && bmp->dib && bits32)
1072 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1080 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1082 height = height >= 0 ? height : -height;
1083 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1085 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1087 /* calculate number of sel's needed for size with 64K steps */
1088 count = (size + 0xffff) / 0x10000;
1089 sel = AllocSelectorArray16(count);
1091 for (i = 0; i < count; i++)
1093 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1094 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1097 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1098 if (bits16) *bits16 = bmp->segptr_bits;
1100 if (bmp) GDI_ReleaseObj( hbitmap );
1102 return HBITMAP_16(hbitmap);
1105 /***********************************************************************
1106 * DIB_CreateDIBSection
1108 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
1109 VOID **bits, HANDLE section,
1110 DWORD offset, DWORD ovr_pitch)
1114 BOOL bDesktopDC = FALSE;
1120 DWORD compression, sizeImage;
1121 const DWORD *colorPtr;
1122 void *mapBits = NULL;
1124 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1125 &planes, &bpp, &compression, &sizeImage )) == -1))
1128 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1130 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, %s\n",
1131 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1133 dib->dsBm.bmType = 0;
1134 dib->dsBm.bmWidth = width;
1135 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1136 dib->dsBm.bmWidthBytes = ovr_pitch ? ovr_pitch : DIB_GetDIBWidthBytes(width, bpp);
1137 dib->dsBm.bmPlanes = planes;
1138 dib->dsBm.bmBitsPixel = bpp;
1139 dib->dsBm.bmBits = NULL;
1141 if (!bitmap_type) /* core header */
1143 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1144 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1145 dib->dsBmih.biWidth = width;
1146 dib->dsBmih.biHeight = height;
1147 dib->dsBmih.biPlanes = planes;
1148 dib->dsBmih.biBitCount = bpp;
1149 dib->dsBmih.biCompression = compression;
1150 dib->dsBmih.biXPelsPerMeter = 0;
1151 dib->dsBmih.biYPelsPerMeter = 0;
1152 dib->dsBmih.biClrUsed = 0;
1153 dib->dsBmih.biClrImportant = 0;
1157 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1158 dib->dsBmih = bmi->bmiHeader;
1159 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1162 /* only use sizeImage if it's valid and we're dealing with a compressed bitmap */
1163 if (sizeImage && (compression == BI_RLE4 || compression == BI_RLE8))
1164 dib->dsBmih.biSizeImage = sizeImage;
1166 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1169 /* set dsBitfields values */
1170 colorPtr = (const DWORD *)((const char *)bmi + (WORD) bmi->bmiHeader.biSize);
1171 if (usage == DIB_PAL_COLORS || bpp <= 8)
1173 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1179 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? colorPtr[0] : 0x7c00;
1180 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? colorPtr[1] : 0x03e0;
1181 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? colorPtr[2] : 0x001f;
1185 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? colorPtr[0] : 0xff0000;
1186 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? colorPtr[1] : 0x00ff00;
1187 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? colorPtr[2] : 0x0000ff;
1191 /* get storage location for DIB bits */
1195 SYSTEM_INFO SystemInfo;
1199 GetSystemInfo( &SystemInfo );
1200 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1201 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1202 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1203 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1205 else if (ovr_pitch && offset)
1206 dib->dsBm.bmBits = (LPVOID) offset;
1210 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1211 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1213 dib->dshSection = section;
1214 dib->dsOffset = offset;
1216 if (!dib->dsBm.bmBits)
1218 HeapFree( GetProcessHeap(), 0, dib );
1222 /* If the reference hdc is null, take the desktop dc */
1225 hdc = CreateCompatibleDC(0);
1229 if (!(dc = DC_GetDCPtr( hdc ))) goto error;
1231 /* create Device Dependent Bitmap and add DIB pointer */
1232 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1233 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1235 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1238 bmp->funcs = dc->funcs;
1239 GDI_ReleaseObj( ret );
1241 if (dc->funcs->pCreateDIBSection)
1243 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1245 DeleteObject( ret );
1251 GDI_ReleaseObj(hdc);
1252 if (bDesktopDC) DeleteDC( hdc );
1253 if (ret && bits) *bits = dib->dsBm.bmBits;
1257 if (bDesktopDC) DeleteDC( hdc );
1258 if (section) UnmapViewOfFile( mapBits );
1259 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1260 HeapFree( GetProcessHeap(), 0, dib );
1264 /***********************************************************************
1265 * CreateDIBSection (GDI32.@)
1267 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1268 VOID **bits, HANDLE section,
1271 return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);