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 (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
319 if (!(dc = DC_GetDCUpdate( hdc )))
321 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
322 GDI_ReleaseObj( hbitmap );
326 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
328 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
329 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
330 bits, info, coloruse );
335 GDI_ReleaseObj( hdc );
336 GDI_ReleaseObj( hbitmap );
341 /***********************************************************************
342 * SetDIBitsToDevice (GDI32.@)
344 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
345 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
346 UINT lines, LPCVOID bits, const BITMAPINFO *info,
352 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
354 if(dc->funcs->pSetDIBitsToDevice)
355 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
356 ySrc, startscan, lines, bits,
359 FIXME("unimplemented on hdc %p\n", hdc);
363 GDI_ReleaseObj( hdc );
367 /***********************************************************************
368 * SetDIBColorTable (GDI32.@)
370 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
375 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
377 if (dc->funcs->pSetDIBColorTable)
378 result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
380 GDI_ReleaseObj( hdc );
385 /***********************************************************************
386 * GetDIBColorTable (GDI32.@)
388 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
393 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
395 if (dc->funcs->pGetDIBColorTable)
396 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
398 GDI_ReleaseObj( hdc );
402 /* FIXME the following two structs should be combined with __sysPalTemplate in
403 objects/color.c - this should happen after de-X11-ing both of these
405 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
408 static RGBQUAD EGAColorsQuads[16] = {
409 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
410 { 0x00, 0x00, 0x00, 0x00 },
411 { 0x00, 0x00, 0x80, 0x00 },
412 { 0x00, 0x80, 0x00, 0x00 },
413 { 0x00, 0x80, 0x80, 0x00 },
414 { 0x80, 0x00, 0x00, 0x00 },
415 { 0x80, 0x00, 0x80, 0x00 },
416 { 0x80, 0x80, 0x00, 0x00 },
417 { 0x80, 0x80, 0x80, 0x00 },
418 { 0xc0, 0xc0, 0xc0, 0x00 },
419 { 0x00, 0x00, 0xff, 0x00 },
420 { 0x00, 0xff, 0x00, 0x00 },
421 { 0x00, 0xff, 0xff, 0x00 },
422 { 0xff, 0x00, 0x00, 0x00 },
423 { 0xff, 0x00, 0xff, 0x00 },
424 { 0xff, 0xff, 0x00, 0x00 },
425 { 0xff, 0xff, 0xff, 0x00 }
428 static RGBTRIPLE EGAColorsTriples[16] = {
429 /* rgbBlue, rgbGreen, rgbRed */
430 { 0x00, 0x00, 0x00 },
431 { 0x00, 0x00, 0x80 },
432 { 0x00, 0x80, 0x00 },
433 { 0x00, 0x80, 0x80 },
434 { 0x80, 0x00, 0x00 },
435 { 0x80, 0x00, 0x80 },
436 { 0x80, 0x80, 0x00 },
437 { 0x80, 0x80, 0x80 },
438 { 0xc0, 0xc0, 0xc0 },
439 { 0x00, 0x00, 0xff },
440 { 0x00, 0xff, 0x00 },
441 { 0x00, 0xff, 0xff },
442 { 0xff, 0x00, 0x00 } ,
443 { 0xff, 0x00, 0xff },
444 { 0xff, 0xff, 0x00 },
448 static RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
449 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
450 { 0x00, 0x00, 0x00, 0x00 },
451 { 0x00, 0x00, 0x80, 0x00 },
452 { 0x00, 0x80, 0x00, 0x00 },
453 { 0x00, 0x80, 0x80, 0x00 },
454 { 0x80, 0x00, 0x00, 0x00 },
455 { 0x80, 0x00, 0x80, 0x00 },
456 { 0x80, 0x80, 0x00, 0x00 },
457 { 0xc0, 0xc0, 0xc0, 0x00 },
458 { 0xc0, 0xdc, 0xc0, 0x00 },
459 { 0xf0, 0xca, 0xa6, 0x00 },
460 { 0xf0, 0xfb, 0xff, 0x00 },
461 { 0xa4, 0xa0, 0xa0, 0x00 },
462 { 0x80, 0x80, 0x80, 0x00 },
463 { 0x00, 0x00, 0xf0, 0x00 },
464 { 0x00, 0xff, 0x00, 0x00 },
465 { 0x00, 0xff, 0xff, 0x00 },
466 { 0xff, 0x00, 0x00, 0x00 },
467 { 0xff, 0x00, 0xff, 0x00 },
468 { 0xff, 0xff, 0x00, 0x00 },
469 { 0xff, 0xff, 0xff, 0x00 }
472 static RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
473 /* rgbBlue, rgbGreen, rgbRed */
474 { 0x00, 0x00, 0x00 },
475 { 0x00, 0x00, 0x80 },
476 { 0x00, 0x80, 0x00 },
477 { 0x00, 0x80, 0x80 },
478 { 0x80, 0x00, 0x00 },
479 { 0x80, 0x00, 0x80 },
480 { 0x80, 0x80, 0x00 },
481 { 0xc0, 0xc0, 0xc0 },
482 { 0xc0, 0xdc, 0xc0 },
483 { 0xf0, 0xca, 0xa6 },
484 { 0xf0, 0xfb, 0xff },
485 { 0xa4, 0xa0, 0xa0 },
486 { 0x80, 0x80, 0x80 },
487 { 0x00, 0x00, 0xf0 },
488 { 0x00, 0xff, 0x00 },
489 { 0x00, 0xff, 0xff },
490 { 0xff, 0x00, 0x00 },
491 { 0xff, 0x00, 0xff },
492 { 0xff, 0xff, 0x00 },
497 /******************************************************************************
498 * GetDIBits [GDI32.@]
500 * Retrieves bits of bitmap and copies to buffer.
503 * Success: Number of scan lines copied from bitmap
506 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
508 INT WINAPI GetDIBits(
509 HDC hdc, /* [in] Handle to device context */
510 HBITMAP hbitmap, /* [in] Handle to bitmap */
511 UINT startscan, /* [in] First scan line to set in dest bitmap */
512 UINT lines, /* [in] Number of scan lines to copy */
513 LPVOID bits, /* [out] Address of array for bitmap bits */
514 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
515 UINT coloruse) /* [in] RGB or palette index */
528 RGBTRIPLE* rgbTriples;
533 bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr);
534 if (bitmap_type == -1)
536 ERR("Invalid bitmap format\n");
539 core_header = (bitmap_type == 0);
540 memdc = CreateCompatibleDC(hdc);
541 if (!(dc = DC_GetDCUpdate( hdc )))
546 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
548 GDI_ReleaseObj( hdc );
553 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
554 rgbTriples = (RGBTRIPLE *) colorPtr;
555 rgbQuads = (RGBQUAD *) colorPtr;
557 /* Transfer color info */
559 if (bpp <= 8 && bpp > 0)
561 if (!core_header) info->bmiHeader.biClrUsed = 0;
563 /* If the bitmap object already has a dib section at the
564 same color depth then get the color map from it */
565 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
566 if(coloruse == DIB_RGB_COLORS) {
567 HBITMAP oldbm = SelectObject(memdc, hbitmap);
568 unsigned int colors = 1 << bpp;
572 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
573 RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
577 RGBTRIPLE* index = rgbTriples;
578 GetDIBColorTable(memdc, 0, colors, buffer);
580 for (i=0; i < colors; i++, index++)
582 index->rgbtRed = buffer[i].rgbRed;
583 index->rgbtGreen = buffer[i].rgbGreen;
584 index->rgbtBlue = buffer[i].rgbBlue;
587 HeapFree(GetProcessHeap(), 0, buffer);
592 GetDIBColorTable(memdc, 0, colors, colorPtr);
594 SelectObject(memdc, oldbm);
597 WORD *index = colorPtr;
598 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
603 if(bpp >= bmp->bitmap.bmBitsPixel) {
604 /* Generate the color map from the selected palette */
605 PALETTEENTRY * palEntry;
606 PALETTEOBJ * palette;
607 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
608 GDI_ReleaseObj( hdc );
609 GDI_ReleaseObj( hbitmap );
613 palEntry = palette->logpalette.palPalEntry;
614 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
615 if (coloruse == DIB_RGB_COLORS) {
618 rgbTriples[i].rgbtRed = palEntry->peRed;
619 rgbTriples[i].rgbtGreen = palEntry->peGreen;
620 rgbTriples[i].rgbtBlue = palEntry->peBlue;
624 rgbQuads[i].rgbRed = palEntry->peRed;
625 rgbQuads[i].rgbGreen = palEntry->peGreen;
626 rgbQuads[i].rgbBlue = palEntry->peBlue;
627 rgbQuads[i].rgbReserved = 0;
630 else ((WORD *)colorPtr)[i] = (WORD)i;
632 GDI_ReleaseObj( dc->hPalette );
638 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
639 rgbTriples[0].rgbtBlue = 0;
640 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
641 rgbTriples[1].rgbtBlue = 0xff;
645 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
646 rgbQuads[0].rgbBlue = 0;
647 rgbQuads[0].rgbReserved = 0;
648 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
649 rgbQuads[1].rgbBlue = 0xff;
650 rgbQuads[1].rgbReserved = 0;
656 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
658 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
669 memcpy(rgbTriples, DefLogPaletteTriples,
670 10 * sizeof(RGBTRIPLE));
671 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
672 10 * sizeof(RGBTRIPLE));
673 color = rgbTriples + 10;
674 for(r = 0; r <= 5; r++) /* FIXME */
675 for(g = 0; g <= 5; g++)
676 for(b = 0; b <= 5; b++) {
677 color->rgbtRed = (r * 0xff) / 5;
678 color->rgbtGreen = (g * 0xff) / 5;
679 color->rgbtBlue = (b * 0xff) / 5;
688 memcpy(rgbQuads, DefLogPaletteQuads,
689 10 * sizeof(RGBQUAD));
690 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
691 10 * sizeof(RGBQUAD));
692 color = rgbQuads + 10;
693 for(r = 0; r <= 5; r++) /* FIXME */
694 for(g = 0; g <= 5; g++)
695 for(b = 0; b <= 5; b++) {
696 color->rgbRed = (r * 0xff) / 5;
697 color->rgbGreen = (g * 0xff) / 5;
698 color->rgbBlue = (b * 0xff) / 5;
699 color->rgbReserved = 0;
711 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
712 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
714 /*FIXME: Only RGB dibs supported for now */
715 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
716 unsigned int dstwidth = width;
717 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
718 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
719 unsigned int x, y, width, widthb;
721 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
723 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
724 dstwidthb = -dstwidthb;
730 case 16: /* 16 bpp dstDIB */
732 LPWORD dstbits = (LPWORD)dbits;
733 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
735 /* FIXME: BI_BITFIELDS not supported yet */
737 switch(bmp->dib->dsBm.bmBitsPixel) {
739 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
741 widthb = min(srcwidthb, abs(dstwidthb));
742 /* FIXME: BI_BITFIELDS not supported yet */
743 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
744 memcpy(dbits, sbits, widthb);
748 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
750 LPBYTE srcbits = sbits;
752 width = min(srcwidth, dstwidth);
753 for( y = 0; y < lines; y++) {
754 for( x = 0; x < width; x++, srcbits += 3)
755 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
756 (((WORD)srcbits[1] << 2) & gmask) |
757 (((WORD)srcbits[2] << 7) & rmask);
759 dstbits = (LPWORD)(dbits+=dstwidthb);
760 srcbits = (sbits += srcwidthb);
765 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
767 LPDWORD srcbits = (LPDWORD)sbits;
770 width = min(srcwidth, dstwidth);
771 for( y = 0; y < lines; y++) {
772 for( x = 0; x < width; x++ ) {
774 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
775 ((val >> 9) & rmask));
777 dstbits = (LPWORD)(dbits+=dstwidthb);
778 srcbits = (LPDWORD)(sbits+=srcwidthb);
783 default: /* ? bit bmp -> 16 bit DIB */
784 FIXME("15/16 bit DIB %d bit bitmap\n",
785 bmp->bitmap.bmBitsPixel);
791 case 24: /* 24 bpp dstDIB */
793 LPBYTE dstbits = dbits;
795 switch(bmp->dib->dsBm.bmBitsPixel) {
797 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
799 LPWORD srcbits = (LPWORD)sbits;
802 width = min(srcwidth, dstwidth);
803 /* FIXME: BI_BITFIELDS not supported yet */
804 for( y = 0; y < lines; y++) {
805 for( x = 0; x < width; x++ ) {
807 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
808 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
809 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
811 dstbits = (LPBYTE)(dbits+=dstwidthb);
812 srcbits = (LPWORD)(sbits+=srcwidthb);
817 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
819 widthb = min(srcwidthb, abs(dstwidthb));
820 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
821 memcpy(dbits, sbits, widthb);
825 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
827 LPBYTE srcbits = (LPBYTE)sbits;
829 width = min(srcwidth, dstwidth);
830 for( y = 0; y < lines; y++) {
831 for( x = 0; x < width; x++, srcbits++ ) {
832 *dstbits++ = *srcbits++;
833 *dstbits++ = *srcbits++;
834 *dstbits++ = *srcbits++;
836 dstbits=(LPBYTE)(dbits+=dstwidthb);
837 srcbits = (LPBYTE)(sbits+=srcwidthb);
842 default: /* ? bit bmp -> 24 bit DIB */
843 FIXME("24 bit DIB %d bit bitmap\n",
844 bmp->bitmap.bmBitsPixel);
850 case 32: /* 32 bpp dstDIB */
852 LPDWORD dstbits = (LPDWORD)dbits;
854 /* FIXME: BI_BITFIELDS not supported yet */
856 switch(bmp->dib->dsBm.bmBitsPixel) {
857 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
859 LPWORD srcbits = (LPWORD)sbits;
862 width = min(srcwidth, dstwidth);
863 /* FIXME: BI_BITFIELDS not supported yet */
864 for( y = 0; y < lines; y++) {
865 for( x = 0; x < width; x++ ) {
866 val = (DWORD)*srcbits++;
867 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
868 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
869 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
871 dstbits=(LPDWORD)(dbits+=dstwidthb);
872 srcbits=(LPWORD)(sbits+=srcwidthb);
877 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
879 LPBYTE srcbits = sbits;
881 width = min(srcwidth, dstwidth);
882 for( y = 0; y < lines; y++) {
883 for( x = 0; x < width; x++, srcbits+=3 )
884 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
885 dstbits=(LPDWORD)(dbits+=dstwidthb);
886 srcbits=(sbits+=srcwidthb);
891 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
893 widthb = min(srcwidthb, abs(dstwidthb));
894 /* FIXME: BI_BITFIELDS not supported yet */
895 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
896 memcpy(dbits, sbits, widthb);
901 default: /* ? bit bmp -> 32 bit DIB */
902 FIXME("32 bit DIB %d bit bitmap\n",
903 bmp->bitmap.bmBitsPixel);
909 default: /* ? bit DIB */
910 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
914 /* Otherwise, get bits from the XImage */
917 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
920 if (bmp->funcs && bmp->funcs->pGetDIBits)
921 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
922 lines, bits, info, coloruse );
924 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
930 /* fill in struct members */
936 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
937 coreheader->bcWidth = bmp->bitmap.bmWidth;
938 coreheader->bcHeight = bmp->bitmap.bmHeight;
939 coreheader->bcPlanes = 1;
940 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
944 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
945 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
946 info->bmiHeader.biPlanes = 1;
947 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
948 info->bmiHeader.biSizeImage =
949 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
950 bmp->bitmap.bmHeight,
951 bmp->bitmap.bmBitsPixel );
952 info->bmiHeader.biCompression = 0;
954 lines = abs(bmp->bitmap.bmHeight);
960 TRACE("biSizeImage = %ld, ", info->bmiHeader.biSizeImage);
962 TRACE("biWidth = %ld, biHeight = %ld\n", width, height);
964 GDI_ReleaseObj( hdc );
965 GDI_ReleaseObj( hbitmap );
971 /***********************************************************************
972 * CreateDIBitmap (GDI32.@)
974 * Creates a DDB (device dependent bitmap) from a DIB.
975 * The DDB will have the same color depth as the reference DC.
977 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
978 DWORD init, LPCVOID bits, const BITMAPINFO *data,
988 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
992 TRACE("Bitmap has a negative width\n");
996 /* Top-down DIBs have a negative height */
997 if (height < 0) height = -height;
999 TRACE("hdc=%p, header=%p, init=%lu, bits=%p, data=%p, coloruse=%u (bitmap: width=%ld, height=%ld, bpp=%u, compr=%lu)\n",
1000 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1003 handle = CreateBitmap( width, height, 1, 1, NULL );
1005 handle = CreateCompatibleBitmap( hdc, width, height );
1009 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1011 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1013 if (!BITMAP_SetOwnerDC( handle, dc ))
1015 DeleteObject( handle );
1018 GDI_ReleaseObj( hdc );
1025 /***********************************************************************
1026 * CreateDIBSection (GDI.489)
1028 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1029 SEGPTR *bits16, HANDLE section, DWORD offset)
1034 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1037 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1038 if (bmp && bmp->dib && bits32)
1040 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1050 core_header = (DIB_GetBitmapInfo(bi, &width, &height, &bpp, &compr) == 0);
1052 height = height >= 0 ? height : -height;
1053 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1057 size = width_bytes * height;
1061 size = (bi->biSizeImage && compr != BI_RGB) ?
1062 bi->biSizeImage : width_bytes * height;
1065 /* calculate number of sel's needed for size with 64K steps */
1066 count = (size + 0xffff) / 0x10000;
1067 sel = AllocSelectorArray16(count);
1069 for (i = 0; i < count; i++)
1071 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1072 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1075 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1076 if (bits16) *bits16 = bmp->segptr_bits;
1078 if (bmp) GDI_ReleaseObj( hbitmap );
1080 return HBITMAP_16(hbitmap);
1083 /***********************************************************************
1084 * DIB_CreateDIBSection
1086 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
1087 VOID **bits, HANDLE section,
1088 DWORD offset, DWORD ovr_pitch)
1090 HBITMAP hbitmap = 0;
1092 BOOL bDesktopDC = FALSE;
1094 /* If the reference hdc is null, take the desktop dc */
1097 hdc = CreateCompatibleDC(0);
1101 if ((dc = DC_GetDCPtr( hdc )))
1103 if(dc->funcs->pCreateDIBSection)
1104 hbitmap = dc->funcs->pCreateDIBSection(dc->physDev, bmi, usage, bits, section, offset, ovr_pitch);
1105 GDI_ReleaseObj(hdc);
1114 /***********************************************************************
1115 * CreateDIBSection (GDI32.@)
1117 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1118 VOID **bits, HANDLE section,
1121 return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);