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 *bpp, DWORD *compr )
155 if (header->biSize == sizeof(BITMAPINFOHEADER))
157 *width = header->biWidth;
158 *height = header->biHeight;
159 *bpp = header->biBitCount;
160 *compr = header->biCompression;
163 if (header->biSize == sizeof(BITMAPCOREHEADER))
165 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
166 *width = core->bcWidth;
167 *height = core->bcHeight;
168 *bpp = core->bcBitCount;
172 if (header->biSize == sizeof(BITMAPV4HEADER))
174 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
175 *width = v4hdr->bV4Width;
176 *height = v4hdr->bV4Height;
177 *bpp = v4hdr->bV4BitCount;
178 *compr = v4hdr->bV4V4Compression;
181 if (header->biSize == sizeof(BITMAPV5HEADER))
183 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
184 *width = v5hdr->bV5Width;
185 *height = v5hdr->bV5Height;
186 *bpp = v5hdr->bV5BitCount;
187 *compr = v5hdr->bV5Compression;
190 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
195 /***********************************************************************
196 * StretchDIBits (GDI32.@)
198 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
199 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
200 INT heightSrc, const void *bits,
201 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
208 dc = DC_GetDCUpdate( hdc );
209 if(!dc) return FALSE;
211 if(dc->funcs->pStretchDIBits)
213 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
214 heightDst, xSrc, ySrc, widthSrc,
215 heightSrc, bits, info, wUsage, dwRop);
216 GDI_ReleaseObj( hdc );
218 else /* use StretchBlt */
220 HBITMAP hBitmap, hOldBitmap;
221 HPALETTE hpal = NULL;
228 if (DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr ) == -1)
230 ERR("Invalid bitmap\n");
236 ERR("Bitmap has a negative width\n");
240 GDI_ReleaseObj( hdc );
241 hdcMem = CreateCompatibleDC( hdc );
242 hBitmap = CreateCompatibleBitmap(hdc, width, height);
243 hOldBitmap = SelectObject( hdcMem, hBitmap );
244 if(wUsage == DIB_PAL_COLORS)
246 hpal = GetCurrentObject(hdc, OBJ_PAL);
247 hpal = SelectPalette(hdcMem, hpal, FALSE);
250 if (info->bmiHeader.biCompression == BI_RLE4 ||
251 info->bmiHeader.biCompression == BI_RLE8) {
253 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
254 * contain all the rectangle described in bmiHeader, but only part of it.
255 * This mean that those undescribed pixels must be left untouched.
256 * So, we first copy on a memory bitmap the current content of the
257 * destination rectangle, blit the DIB bits on top of it - hence leaving
258 * the gaps untouched -, and blitting the rectangle back.
259 * This insure that gaps are untouched on the destination rectangle
260 * Not doing so leads to trashed images (the gaps contain what was on the
261 * memory bitmap => generally black or garbage)
262 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
263 * another speed vs correctness issue. Anyway, if speed is needed, then the
264 * pStretchDIBits function shall be implemented.
268 /* copy existing bitmap from destination dc */
269 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
270 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
274 SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
276 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
277 left (negative biHeight) */
278 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
279 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
280 widthSrc, heightSrc, dwRop );
282 SelectPalette(hdcMem, hpal, FALSE);
283 SelectObject( hdcMem, hOldBitmap );
285 DeleteObject( hBitmap );
291 /******************************************************************************
292 * SetDIBits [GDI32.@]
294 * Sets pixels in a bitmap using colors from DIB.
297 * hdc [I] Handle to device context
298 * hbitmap [I] Handle to bitmap
299 * startscan [I] Starting scan line
300 * lines [I] Number of scan lines
301 * bits [I] Array of bitmap bits
302 * info [I] Address of structure with data
303 * coloruse [I] Type of color indexes to use
306 * Success: Number of scan lines copied
309 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
310 UINT lines, LPCVOID bits, const BITMAPINFO *info,
317 if (!(dc = DC_GetDCUpdate( hdc )))
319 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
323 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
325 GDI_ReleaseObj( hdc );
329 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
331 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
332 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
333 bits, info, coloruse );
338 GDI_ReleaseObj( hbitmap );
339 GDI_ReleaseObj( hdc );
344 /***********************************************************************
345 * SetDIBitsToDevice (GDI32.@)
347 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
348 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
349 UINT lines, LPCVOID bits, const BITMAPINFO *info,
355 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
357 if(dc->funcs->pSetDIBitsToDevice)
358 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
359 ySrc, startscan, lines, bits,
362 FIXME("unimplemented on hdc %p\n", hdc);
366 GDI_ReleaseObj( hdc );
370 /***********************************************************************
371 * SetDIBColorTable (GDI32.@)
373 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
378 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
380 if (dc->funcs->pSetDIBColorTable)
381 result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
383 GDI_ReleaseObj( hdc );
388 /***********************************************************************
389 * GetDIBColorTable (GDI32.@)
391 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
396 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
398 if (dc->funcs->pGetDIBColorTable)
399 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
401 GDI_ReleaseObj( hdc );
405 /* FIXME the following two structs should be combined with __sysPalTemplate in
406 objects/color.c - this should happen after de-X11-ing both of these
408 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
411 static RGBQUAD EGAColorsQuads[16] = {
412 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
413 { 0x00, 0x00, 0x00, 0x00 },
414 { 0x00, 0x00, 0x80, 0x00 },
415 { 0x00, 0x80, 0x00, 0x00 },
416 { 0x00, 0x80, 0x80, 0x00 },
417 { 0x80, 0x00, 0x00, 0x00 },
418 { 0x80, 0x00, 0x80, 0x00 },
419 { 0x80, 0x80, 0x00, 0x00 },
420 { 0x80, 0x80, 0x80, 0x00 },
421 { 0xc0, 0xc0, 0xc0, 0x00 },
422 { 0x00, 0x00, 0xff, 0x00 },
423 { 0x00, 0xff, 0x00, 0x00 },
424 { 0x00, 0xff, 0xff, 0x00 },
425 { 0xff, 0x00, 0x00, 0x00 },
426 { 0xff, 0x00, 0xff, 0x00 },
427 { 0xff, 0xff, 0x00, 0x00 },
428 { 0xff, 0xff, 0xff, 0x00 }
431 static RGBTRIPLE EGAColorsTriples[16] = {
432 /* rgbBlue, rgbGreen, rgbRed */
433 { 0x00, 0x00, 0x00 },
434 { 0x00, 0x00, 0x80 },
435 { 0x00, 0x80, 0x00 },
436 { 0x00, 0x80, 0x80 },
437 { 0x80, 0x00, 0x00 },
438 { 0x80, 0x00, 0x80 },
439 { 0x80, 0x80, 0x00 },
440 { 0x80, 0x80, 0x80 },
441 { 0xc0, 0xc0, 0xc0 },
442 { 0x00, 0x00, 0xff },
443 { 0x00, 0xff, 0x00 },
444 { 0x00, 0xff, 0xff },
445 { 0xff, 0x00, 0x00 } ,
446 { 0xff, 0x00, 0xff },
447 { 0xff, 0xff, 0x00 },
451 static RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
452 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
453 { 0x00, 0x00, 0x00, 0x00 },
454 { 0x00, 0x00, 0x80, 0x00 },
455 { 0x00, 0x80, 0x00, 0x00 },
456 { 0x00, 0x80, 0x80, 0x00 },
457 { 0x80, 0x00, 0x00, 0x00 },
458 { 0x80, 0x00, 0x80, 0x00 },
459 { 0x80, 0x80, 0x00, 0x00 },
460 { 0xc0, 0xc0, 0xc0, 0x00 },
461 { 0xc0, 0xdc, 0xc0, 0x00 },
462 { 0xf0, 0xca, 0xa6, 0x00 },
463 { 0xf0, 0xfb, 0xff, 0x00 },
464 { 0xa4, 0xa0, 0xa0, 0x00 },
465 { 0x80, 0x80, 0x80, 0x00 },
466 { 0x00, 0x00, 0xf0, 0x00 },
467 { 0x00, 0xff, 0x00, 0x00 },
468 { 0x00, 0xff, 0xff, 0x00 },
469 { 0xff, 0x00, 0x00, 0x00 },
470 { 0xff, 0x00, 0xff, 0x00 },
471 { 0xff, 0xff, 0x00, 0x00 },
472 { 0xff, 0xff, 0xff, 0x00 }
475 static RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
476 /* rgbBlue, rgbGreen, rgbRed */
477 { 0x00, 0x00, 0x00 },
478 { 0x00, 0x00, 0x80 },
479 { 0x00, 0x80, 0x00 },
480 { 0x00, 0x80, 0x80 },
481 { 0x80, 0x00, 0x00 },
482 { 0x80, 0x00, 0x80 },
483 { 0x80, 0x80, 0x00 },
484 { 0xc0, 0xc0, 0xc0 },
485 { 0xc0, 0xdc, 0xc0 },
486 { 0xf0, 0xca, 0xa6 },
487 { 0xf0, 0xfb, 0xff },
488 { 0xa4, 0xa0, 0xa0 },
489 { 0x80, 0x80, 0x80 },
490 { 0x00, 0x00, 0xf0 },
491 { 0x00, 0xff, 0x00 },
492 { 0x00, 0xff, 0xff },
493 { 0xff, 0x00, 0x00 },
494 { 0xff, 0x00, 0xff },
495 { 0xff, 0xff, 0x00 },
500 /******************************************************************************
501 * GetDIBits [GDI32.@]
503 * Retrieves bits of bitmap and copies to buffer.
506 * Success: Number of scan lines copied from bitmap
509 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
511 INT WINAPI GetDIBits(
512 HDC hdc, /* [in] Handle to device context */
513 HBITMAP hbitmap, /* [in] Handle to bitmap */
514 UINT startscan, /* [in] First scan line to set in dest bitmap */
515 UINT lines, /* [in] Number of scan lines to copy */
516 LPVOID bits, /* [out] Address of array for bitmap bits */
517 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
518 UINT coloruse) /* [in] RGB or palette index */
531 RGBTRIPLE* rgbTriples;
536 bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr);
537 if (bitmap_type == -1)
539 ERR("Invalid bitmap format\n");
542 core_header = (bitmap_type == 0);
543 memdc = CreateCompatibleDC(hdc);
544 if (!(dc = DC_GetDCUpdate( hdc )))
549 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
551 GDI_ReleaseObj( hdc );
556 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
557 rgbTriples = (RGBTRIPLE *) colorPtr;
558 rgbQuads = (RGBQUAD *) colorPtr;
560 /* Transfer color info */
562 if (bpp <= 8 && bpp > 0)
564 if (!core_header) info->bmiHeader.biClrUsed = 0;
566 /* If the bitmap object already has a dib section at the
567 same color depth then get the color map from it */
568 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
569 if(coloruse == DIB_RGB_COLORS) {
570 HBITMAP oldbm = SelectObject(memdc, hbitmap);
571 unsigned int colors = 1 << bpp;
575 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
576 RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
580 RGBTRIPLE* index = rgbTriples;
581 GetDIBColorTable(memdc, 0, colors, buffer);
583 for (i=0; i < colors; i++, index++)
585 index->rgbtRed = buffer[i].rgbRed;
586 index->rgbtGreen = buffer[i].rgbGreen;
587 index->rgbtBlue = buffer[i].rgbBlue;
590 HeapFree(GetProcessHeap(), 0, buffer);
595 GetDIBColorTable(memdc, 0, colors, colorPtr);
597 SelectObject(memdc, oldbm);
600 WORD *index = colorPtr;
601 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
606 if(bpp >= bmp->bitmap.bmBitsPixel) {
607 /* Generate the color map from the selected palette */
608 PALETTEENTRY * palEntry;
609 PALETTEOBJ * palette;
610 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
611 GDI_ReleaseObj( hdc );
612 GDI_ReleaseObj( hbitmap );
616 palEntry = palette->logpalette.palPalEntry;
617 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
618 if (coloruse == DIB_RGB_COLORS) {
621 rgbTriples[i].rgbtRed = palEntry->peRed;
622 rgbTriples[i].rgbtGreen = palEntry->peGreen;
623 rgbTriples[i].rgbtBlue = palEntry->peBlue;
627 rgbQuads[i].rgbRed = palEntry->peRed;
628 rgbQuads[i].rgbGreen = palEntry->peGreen;
629 rgbQuads[i].rgbBlue = palEntry->peBlue;
630 rgbQuads[i].rgbReserved = 0;
633 else ((WORD *)colorPtr)[i] = (WORD)i;
635 GDI_ReleaseObj( dc->hPalette );
641 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
642 rgbTriples[0].rgbtBlue = 0;
643 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
644 rgbTriples[1].rgbtBlue = 0xff;
648 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
649 rgbQuads[0].rgbBlue = 0;
650 rgbQuads[0].rgbReserved = 0;
651 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
652 rgbQuads[1].rgbBlue = 0xff;
653 rgbQuads[1].rgbReserved = 0;
659 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
661 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
672 memcpy(rgbTriples, DefLogPaletteTriples,
673 10 * sizeof(RGBTRIPLE));
674 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
675 10 * sizeof(RGBTRIPLE));
676 color = rgbTriples + 10;
677 for(r = 0; r <= 5; r++) /* FIXME */
678 for(g = 0; g <= 5; g++)
679 for(b = 0; b <= 5; b++) {
680 color->rgbtRed = (r * 0xff) / 5;
681 color->rgbtGreen = (g * 0xff) / 5;
682 color->rgbtBlue = (b * 0xff) / 5;
691 memcpy(rgbQuads, DefLogPaletteQuads,
692 10 * sizeof(RGBQUAD));
693 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
694 10 * sizeof(RGBQUAD));
695 color = rgbQuads + 10;
696 for(r = 0; r <= 5; r++) /* FIXME */
697 for(g = 0; g <= 5; g++)
698 for(b = 0; b <= 5; b++) {
699 color->rgbRed = (r * 0xff) / 5;
700 color->rgbGreen = (g * 0xff) / 5;
701 color->rgbBlue = (b * 0xff) / 5;
702 color->rgbReserved = 0;
714 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
715 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
717 /*FIXME: Only RGB dibs supported for now */
718 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
719 unsigned int dstwidth = width;
720 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
721 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
722 unsigned int x, y, width, widthb;
724 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
726 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
727 dstwidthb = -dstwidthb;
733 case 16: /* 16 bpp dstDIB */
735 LPWORD dstbits = (LPWORD)dbits;
736 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
738 /* FIXME: BI_BITFIELDS not supported yet */
740 switch(bmp->dib->dsBm.bmBitsPixel) {
742 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
744 widthb = min(srcwidthb, abs(dstwidthb));
745 /* FIXME: BI_BITFIELDS not supported yet */
746 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
747 memcpy(dbits, sbits, widthb);
751 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
753 LPBYTE srcbits = sbits;
755 width = min(srcwidth, dstwidth);
756 for( y = 0; y < lines; y++) {
757 for( x = 0; x < width; x++, srcbits += 3)
758 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
759 (((WORD)srcbits[1] << 2) & gmask) |
760 (((WORD)srcbits[2] << 7) & rmask);
762 dstbits = (LPWORD)(dbits+=dstwidthb);
763 srcbits = (sbits += srcwidthb);
768 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
770 LPDWORD srcbits = (LPDWORD)sbits;
773 width = min(srcwidth, dstwidth);
774 for( y = 0; y < lines; y++) {
775 for( x = 0; x < width; x++ ) {
777 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
778 ((val >> 9) & rmask));
780 dstbits = (LPWORD)(dbits+=dstwidthb);
781 srcbits = (LPDWORD)(sbits+=srcwidthb);
786 default: /* ? bit bmp -> 16 bit DIB */
787 FIXME("15/16 bit DIB %d bit bitmap\n",
788 bmp->bitmap.bmBitsPixel);
794 case 24: /* 24 bpp dstDIB */
796 LPBYTE dstbits = dbits;
798 switch(bmp->dib->dsBm.bmBitsPixel) {
800 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
802 LPWORD srcbits = (LPWORD)sbits;
805 width = min(srcwidth, dstwidth);
806 /* FIXME: BI_BITFIELDS not supported yet */
807 for( y = 0; y < lines; y++) {
808 for( x = 0; x < width; x++ ) {
810 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
811 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
812 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
814 dstbits = (LPBYTE)(dbits+=dstwidthb);
815 srcbits = (LPWORD)(sbits+=srcwidthb);
820 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
822 widthb = min(srcwidthb, abs(dstwidthb));
823 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
824 memcpy(dbits, sbits, widthb);
828 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
830 LPBYTE srcbits = (LPBYTE)sbits;
832 width = min(srcwidth, dstwidth);
833 for( y = 0; y < lines; y++) {
834 for( x = 0; x < width; x++, srcbits++ ) {
835 *dstbits++ = *srcbits++;
836 *dstbits++ = *srcbits++;
837 *dstbits++ = *srcbits++;
839 dstbits=(LPBYTE)(dbits+=dstwidthb);
840 srcbits = (LPBYTE)(sbits+=srcwidthb);
845 default: /* ? bit bmp -> 24 bit DIB */
846 FIXME("24 bit DIB %d bit bitmap\n",
847 bmp->bitmap.bmBitsPixel);
853 case 32: /* 32 bpp dstDIB */
855 LPDWORD dstbits = (LPDWORD)dbits;
857 /* FIXME: BI_BITFIELDS not supported yet */
859 switch(bmp->dib->dsBm.bmBitsPixel) {
860 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
862 LPWORD srcbits = (LPWORD)sbits;
865 width = min(srcwidth, dstwidth);
866 /* FIXME: BI_BITFIELDS not supported yet */
867 for( y = 0; y < lines; y++) {
868 for( x = 0; x < width; x++ ) {
869 val = (DWORD)*srcbits++;
870 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
871 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
872 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
874 dstbits=(LPDWORD)(dbits+=dstwidthb);
875 srcbits=(LPWORD)(sbits+=srcwidthb);
880 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
882 LPBYTE srcbits = sbits;
884 width = min(srcwidth, dstwidth);
885 for( y = 0; y < lines; y++) {
886 for( x = 0; x < width; x++, srcbits+=3 )
887 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
888 dstbits=(LPDWORD)(dbits+=dstwidthb);
889 srcbits=(sbits+=srcwidthb);
894 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
896 widthb = min(srcwidthb, abs(dstwidthb));
897 /* FIXME: BI_BITFIELDS not supported yet */
898 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
899 memcpy(dbits, sbits, widthb);
904 default: /* ? bit bmp -> 32 bit DIB */
905 FIXME("32 bit DIB %d bit bitmap\n",
906 bmp->bitmap.bmBitsPixel);
912 default: /* ? bit DIB */
913 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
917 /* Otherwise, get bits from the XImage */
920 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
923 if (bmp->funcs && bmp->funcs->pGetDIBits)
924 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
925 lines, bits, info, coloruse );
927 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
933 /* fill in struct members */
939 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
940 coreheader->bcWidth = bmp->bitmap.bmWidth;
941 coreheader->bcHeight = bmp->bitmap.bmHeight;
942 coreheader->bcPlanes = 1;
943 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
947 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
948 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
949 info->bmiHeader.biPlanes = 1;
950 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
951 info->bmiHeader.biSizeImage =
952 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
953 bmp->bitmap.bmHeight,
954 bmp->bitmap.bmBitsPixel );
955 info->bmiHeader.biCompression = 0;
957 lines = abs(bmp->bitmap.bmHeight);
963 TRACE("biSizeImage = %ld, ", info->bmiHeader.biSizeImage);
965 TRACE("biWidth = %ld, biHeight = %ld\n", width, height);
967 GDI_ReleaseObj( hdc );
968 GDI_ReleaseObj( hbitmap );
974 /***********************************************************************
975 * CreateDIBitmap (GDI32.@)
977 * Creates a DDB (device dependent bitmap) from a DIB.
978 * The DDB will have the same color depth as the reference DC.
980 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
981 DWORD init, LPCVOID bits, const BITMAPINFO *data,
991 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
995 TRACE("Bitmap has a negative width\n");
999 /* Top-down DIBs have a negative height */
1000 if (height < 0) height = -height;
1002 TRACE("hdc=%p, header=%p, init=%lu, bits=%p, data=%p, coloruse=%u (bitmap: width=%ld, height=%ld, bpp=%u, compr=%lu)\n",
1003 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1006 handle = CreateBitmap( width, height, 1, 1, NULL );
1008 handle = CreateCompatibleBitmap( hdc, width, height );
1012 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1014 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1016 if (!BITMAP_SetOwnerDC( handle, dc ))
1018 DeleteObject( handle );
1021 GDI_ReleaseObj( hdc );
1028 /***********************************************************************
1029 * CreateDIBSection (GDI.489)
1031 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1032 SEGPTR *bits16, HANDLE section, DWORD offset)
1037 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1040 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1041 if (bmp && bmp->dib && bits32)
1043 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1053 core_header = (DIB_GetBitmapInfo(bi, &width, &height, &bpp, &compr) == 0);
1055 height = height >= 0 ? height : -height;
1056 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1060 size = width_bytes * height;
1064 size = (bi->biSizeImage && compr != BI_RGB) ?
1065 bi->biSizeImage : width_bytes * height;
1068 /* calculate number of sel's needed for size with 64K steps */
1069 count = (size + 0xffff) / 0x10000;
1070 sel = AllocSelectorArray16(count);
1072 for (i = 0; i < count; i++)
1074 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1075 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1078 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1079 if (bits16) *bits16 = bmp->segptr_bits;
1081 if (bmp) GDI_ReleaseObj( hbitmap );
1083 return HBITMAP_16(hbitmap);
1086 /***********************************************************************
1087 * DIB_CreateDIBSection
1089 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
1090 VOID **bits, HANDLE section,
1091 DWORD offset, DWORD ovr_pitch)
1093 HBITMAP hbitmap = 0;
1095 BOOL bDesktopDC = FALSE;
1097 /* If the reference hdc is null, take the desktop dc */
1100 hdc = CreateCompatibleDC(0);
1104 if ((dc = DC_GetDCPtr( hdc )))
1106 if(dc->funcs->pCreateDIBSection)
1107 hbitmap = dc->funcs->pCreateDIBSection(dc->physDev, bmi, usage, bits, section, offset, ovr_pitch);
1108 GDI_ReleaseObj(hdc);
1117 /***********************************************************************
1118 * CreateDIBSection (GDI32.@)
1120 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1121 VOID **bits, HANDLE section,
1124 return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);