Separated 32 bit functions to shellole.c.
[wine/multimedia.git] / objects / dib.c
blobb346629d6bcce98530b88325febc36ed2a579f45
1 /*
2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 */
8 #include "winbase.h"
9 #include "bitmap.h"
10 #include "callback.h"
11 #include "dc.h"
12 #include "debugtools.h"
13 #include "monitor.h"
14 #include "palette.h"
16 DEFAULT_DEBUG_CHANNEL(bitmap)
18 /***********************************************************************
19 * DIB_GetDIBWidthBytes
21 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
22 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
24 int DIB_GetDIBWidthBytes( int width, int depth )
26 int words;
28 switch(depth)
30 case 1: words = (width + 31) / 32; break;
31 case 4: words = (width + 7) / 8; break;
32 case 8: words = (width + 3) / 4; break;
33 case 15:
34 case 16: words = (width + 1) / 2; break;
35 case 24: words = (width * 3 + 3)/4; break;
37 default:
38 WARN("(%d): Unsupported depth\n", depth );
39 /* fall through */
40 case 32:
41 words = width;
43 return 4 * words;
46 /***********************************************************************
47 * DIB_GetDIBImageBytes
49 * Return the number of bytes used to hold the image in a DIB bitmap.
51 int DIB_GetDIBImageBytes( int width, int height, int depth )
53 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
57 /***********************************************************************
58 * DIB_BitmapInfoSize
60 * Return the size of the bitmap info structure including color table.
62 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
64 int colors;
66 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
68 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
69 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
70 return sizeof(BITMAPCOREHEADER) + colors *
71 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
73 else /* assume BITMAPINFOHEADER */
75 colors = info->bmiHeader.biClrUsed;
76 if (!colors && (info->bmiHeader.biBitCount <= 8))
77 colors = 1 << info->bmiHeader.biBitCount;
78 return sizeof(BITMAPINFOHEADER) + colors *
79 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
84 /***********************************************************************
85 * DIB_GetBitmapInfo
87 * Get the info from a bitmap header.
88 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
90 int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
91 int *height, WORD *bpp, WORD *compr )
93 if (header->biSize == sizeof(BITMAPINFOHEADER))
95 *width = header->biWidth;
96 *height = header->biHeight;
97 *bpp = header->biBitCount;
98 *compr = header->biCompression;
99 return 1;
101 if (header->biSize == sizeof(BITMAPCOREHEADER))
103 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
104 *width = core->bcWidth;
105 *height = core->bcHeight;
106 *bpp = core->bcBitCount;
107 *compr = 0;
108 return 0;
110 WARN("(%ld): wrong size for header\n", header->biSize );
111 return -1;
115 /***********************************************************************
116 * StretchDIBits16 (GDI.439)
118 INT16 WINAPI StretchDIBits16(HDC16 hdc, INT16 xDst, INT16 yDst, INT16 widthDst,
119 INT16 heightDst, INT16 xSrc, INT16 ySrc, INT16 widthSrc,
120 INT16 heightSrc, const VOID *bits,
121 const BITMAPINFO *info, UINT16 wUsage, DWORD dwRop )
123 return (INT16)StretchDIBits( hdc, xDst, yDst, widthDst, heightDst,
124 xSrc, ySrc, widthSrc, heightSrc, bits,
125 info, wUsage, dwRop );
129 /***********************************************************************
130 * StretchDIBits (GDI32.351)
132 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
133 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
134 INT heightSrc, const void *bits,
135 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
137 DC *dc = DC_GetDCPtr( hdc );
138 if(!dc) return FALSE;
140 if(dc->funcs->pStretchDIBits)
141 return dc->funcs->pStretchDIBits(dc, xDst, yDst, widthDst,
142 heightDst, xSrc, ySrc, widthSrc,
143 heightSrc, bits, info, wUsage,
144 dwRop);
145 else { /* use StretchBlt */
146 HBITMAP hBitmap, hOldBitmap;
147 HDC hdcMem;
149 hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
150 bits, info, wUsage );
151 hdcMem = CreateCompatibleDC( hdc );
152 hOldBitmap = SelectObject( hdcMem, hBitmap );
153 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
154 left (negative biHeight) */
155 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
156 hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
157 widthSrc, heightSrc, dwRop );
158 SelectObject( hdcMem, hOldBitmap );
159 DeleteDC( hdcMem );
160 DeleteObject( hBitmap );
161 return heightSrc;
166 /***********************************************************************
167 * SetDIBits16 (GDI.440)
169 INT16 WINAPI SetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
170 UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
171 UINT16 coloruse )
173 return SetDIBits( hdc, hbitmap, startscan, lines, bits, info, coloruse );
177 /******************************************************************************
178 * SetDIBits [GDI32.312] Sets pixels in a bitmap using colors from DIB
180 * PARAMS
181 * hdc [I] Handle to device context
182 * hbitmap [I] Handle to bitmap
183 * startscan [I] Starting scan line
184 * lines [I] Number of scan lines
185 * bits [I] Array of bitmap bits
186 * info [I] Address of structure with data
187 * coloruse [I] Type of color indexes to use
189 * RETURNS
190 * Success: Number of scan lines copied
191 * Failure: 0
193 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
194 UINT lines, LPCVOID bits, const BITMAPINFO *info,
195 UINT coloruse )
197 DC *dc;
198 BITMAPOBJ *bitmap;
199 INT result;
201 /* Check parameters */
202 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
203 if (!dc)
205 dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
206 if (!dc) return 0;
209 if (!(bitmap = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
211 GDI_HEAP_UNLOCK( hdc );
212 return 0;
215 result = BITMAP_Driver->pSetDIBits(bitmap, dc, startscan,
216 lines, bits, info,
217 coloruse, hbitmap);
219 GDI_HEAP_UNLOCK( hdc );
220 GDI_HEAP_UNLOCK( hbitmap );
222 return result;
226 /***********************************************************************
227 * SetDIBitsToDevice16 (GDI.443)
229 INT16 WINAPI SetDIBitsToDevice16(HDC16 hdc, INT16 xDest, INT16 yDest, INT16 cx,
230 INT16 cy, INT16 xSrc, INT16 ySrc, UINT16 startscan,
231 UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
232 UINT16 coloruse )
234 return SetDIBitsToDevice( hdc, xDest, yDest, cx, cy, xSrc, ySrc,
235 startscan, lines, bits, info, coloruse );
239 /***********************************************************************
240 * SetDIBitsToDevice (GDI32.313)
242 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
243 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
244 UINT lines, LPCVOID bits, const BITMAPINFO *info,
245 UINT coloruse )
247 INT ret;
248 DC *dc;
250 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
252 if(dc->funcs->pSetDIBitsToDevice)
253 ret = dc->funcs->pSetDIBitsToDevice( dc, xDest, yDest, cx, cy, xSrc,
254 ySrc, startscan, lines, bits,
255 info, coloruse );
256 else {
257 FIXME("unimplemented on hdc %08x\n", hdc);
258 ret = 0;
261 GDI_HEAP_UNLOCK( hdc );
262 return ret;
265 /***********************************************************************
266 * SetDIBColorTable16 (GDI.602)
268 UINT16 WINAPI SetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
269 RGBQUAD *colors )
271 return SetDIBColorTable( hdc, startpos, entries, colors );
274 /***********************************************************************
275 * SetDIBColorTable (GDI32.311)
277 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries,
278 RGBQUAD *colors )
280 DC * dc;
281 PALETTEENTRY * palEntry;
282 PALETTEOBJ * palette;
283 RGBQUAD *end;
285 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
286 if (!dc)
288 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
289 if (!dc) return 0;
292 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
294 return 0;
297 /* Transfer color info */
299 if (dc->w.bitsPerPixel <= 8) {
300 palEntry = palette->logpalette.palPalEntry + startpos;
301 if (startpos + entries > (1 << dc->w.bitsPerPixel))
302 entries = (1 << dc->w.bitsPerPixel) - startpos;
304 if (startpos + entries > palette->logpalette.palNumEntries)
305 entries = palette->logpalette.palNumEntries - startpos;
307 for (end = colors + entries; colors < end; palEntry++, colors++)
309 palEntry->peRed = colors->rgbRed;
310 palEntry->peGreen = colors->rgbGreen;
311 palEntry->peBlue = colors->rgbBlue;
313 } else {
314 entries = 0;
316 GDI_HEAP_UNLOCK( dc->w.hPalette );
317 return entries;
320 /***********************************************************************
321 * GetDIBColorTable16 (GDI.603)
323 UINT16 WINAPI GetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
324 RGBQUAD *colors )
326 return GetDIBColorTable( hdc, startpos, entries, colors );
329 /***********************************************************************
330 * GetDIBColorTable (GDI32.169)
332 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries,
333 RGBQUAD *colors )
335 DC * dc;
336 PALETTEENTRY * palEntry;
337 PALETTEOBJ * palette;
338 RGBQUAD *end;
340 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
341 if (!dc)
343 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
344 if (!dc) return 0;
347 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
349 return 0;
352 /* Transfer color info */
354 if (dc->w.bitsPerPixel <= 8) {
355 palEntry = palette->logpalette.palPalEntry + startpos;
356 if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
357 entries = (1 << dc->w.bitsPerPixel) - startpos;
359 for (end = colors + entries; colors < end; palEntry++, colors++)
361 colors->rgbRed = palEntry->peRed;
362 colors->rgbGreen = palEntry->peGreen;
363 colors->rgbBlue = palEntry->peBlue;
364 colors->rgbReserved = 0;
366 } else {
367 entries = 0;
369 GDI_HEAP_UNLOCK( dc->w.hPalette );
370 return entries;
373 /* FIXME the following two structs should be combined with __sysPalTemplate in
374 objects/color.c - this should happen after de-X11-ing both of these
375 files.
376 NB. RGBQUAD and PALETTENTRY have different orderings of red, green
377 and blue - sigh */
379 static RGBQUAD EGAColors[16] = {
380 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
381 { 0x00, 0x00, 0x00, 0x00 },
382 { 0x00, 0x00, 0x80, 0x00 },
383 { 0x00, 0x80, 0x00, 0x00 },
384 { 0x00, 0x80, 0x80, 0x00 },
385 { 0x80, 0x00, 0x00, 0x00 },
386 { 0x80, 0x00, 0x80, 0x00 },
387 { 0x80, 0x80, 0x00, 0x00 },
388 { 0x80, 0x80, 0x80, 0x00 },
389 { 0xc0, 0xc0, 0xc0, 0x00 },
390 { 0x00, 0x00, 0xff, 0x00 },
391 { 0x00, 0xff, 0x00, 0x00 },
392 { 0x00, 0xff, 0xff, 0x00 },
393 { 0xff, 0x00, 0x00, 0x00 },
394 { 0xff, 0x00, 0xff, 0x00 },
395 { 0xff, 0xff, 0x00, 0x00 },
396 { 0xff, 0xff, 0xff, 0x00 }
400 static RGBQUAD DefLogPalette[20] = { /* Copy of Default Logical Palette */
401 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
402 { 0x00, 0x00, 0x00, 0x00 },
403 { 0x00, 0x00, 0x80, 0x00 },
404 { 0x00, 0x80, 0x00, 0x00 },
405 { 0x00, 0x80, 0x80, 0x00 },
406 { 0x80, 0x00, 0x00, 0x00 },
407 { 0x80, 0x00, 0x80, 0x00 },
408 { 0x80, 0x80, 0x00, 0x00 },
409 { 0xc0, 0xc0, 0xc0, 0x00 },
410 { 0xc0, 0xdc, 0xc0, 0x00 },
411 { 0xf0, 0xca, 0xa6, 0x00 },
412 { 0xf0, 0xfb, 0xff, 0x00 },
413 { 0xa4, 0xa0, 0xa0, 0x00 },
414 { 0x80, 0x80, 0x80, 0x00 },
415 { 0x00, 0x00, 0xf0, 0x00 },
416 { 0x00, 0xff, 0x00, 0x00 },
417 { 0x00, 0xff, 0xff, 0x00 },
418 { 0xff, 0x00, 0x00, 0x00 },
419 { 0xff, 0x00, 0xff, 0x00 },
420 { 0xff, 0xff, 0x00, 0x00 },
421 { 0xff, 0xff, 0xff, 0x00 }
424 /***********************************************************************
425 * GetDIBits16 (GDI.441)
427 INT16 WINAPI GetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
428 UINT16 lines, LPVOID bits, BITMAPINFO * info,
429 UINT16 coloruse )
431 return GetDIBits( hdc, hbitmap, startscan, lines, bits, info, coloruse );
435 /******************************************************************************
436 * GetDIBits [GDI32.170] Retrieves bits of bitmap and copies to buffer
438 * RETURNS
439 * Success: Number of scan lines copied from bitmap
440 * Failure: 0
442 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
444 INT WINAPI GetDIBits(
445 HDC hdc, /* [in] Handle to device context */
446 HBITMAP hbitmap, /* [in] Handle to bitmap */
447 UINT startscan, /* [in] First scan line to set in dest bitmap */
448 UINT lines, /* [in] Number of scan lines to copy */
449 LPVOID bits, /* [out] Address of array for bitmap bits */
450 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
451 UINT coloruse) /* [in] RGB or palette index */
453 DC * dc;
454 BITMAPOBJ * bmp;
455 PALETTEENTRY * palEntry;
456 PALETTEOBJ * palette;
457 int i;
459 if (!info) return 0;
460 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
461 if (!dc)
463 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
464 if (!dc) return 0;
466 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
468 GDI_HEAP_UNLOCK( hdc );
469 return 0;
471 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
473 GDI_HEAP_UNLOCK( hdc );
474 GDI_HEAP_UNLOCK( hbitmap );
475 return 0;
478 /* Transfer color info */
480 if (info->bmiHeader.biBitCount <= 8 && info->bmiHeader.biBitCount > 0 ) {
482 info->bmiHeader.biClrUsed = 0;
484 if(info->bmiHeader.biBitCount >= bmp->bitmap.bmBitsPixel) {
485 palEntry = palette->logpalette.palPalEntry;
486 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
487 if (coloruse == DIB_RGB_COLORS) {
488 info->bmiColors[i].rgbRed = palEntry->peRed;
489 info->bmiColors[i].rgbGreen = palEntry->peGreen;
490 info->bmiColors[i].rgbBlue = palEntry->peBlue;
491 info->bmiColors[i].rgbReserved = 0;
493 else ((WORD *)info->bmiColors)[i] = (WORD)i;
495 } else {
496 switch (info->bmiHeader.biBitCount) {
497 case 1:
498 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen =
499 info->bmiColors[0].rgbBlue = 0;
500 info->bmiColors[0].rgbReserved = 0;
501 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen =
502 info->bmiColors[1].rgbBlue = 0xff;
503 info->bmiColors[1].rgbReserved = 0;
504 break;
506 case 4:
507 memcpy(info->bmiColors, EGAColors, sizeof(EGAColors));
508 break;
510 case 8:
512 INT r, g, b;
513 RGBQUAD *color;
515 memcpy(info->bmiColors, DefLogPalette,
516 10 * sizeof(RGBQUAD));
517 memcpy(info->bmiColors + 246, DefLogPalette + 10,
518 10 * sizeof(RGBQUAD));
519 color = info->bmiColors + 10;
520 for(r = 0; r <= 5; r++) /* FIXME */
521 for(g = 0; g <= 5; g++)
522 for(b = 0; b <= 5; b++) {
523 color->rgbRed = (r * 0xff) / 5;
524 color->rgbGreen = (g * 0xff) / 5;
525 color->rgbBlue = (b * 0xff) / 5;
526 color->rgbReserved = 0;
527 color++;
534 GDI_HEAP_UNLOCK( dc->w.hPalette );
536 if (bits && lines)
538 /* If the bitmap object already have a dib section that contains image data, get the bits from it*/
539 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && info->bmiHeader.biBitCount >= 15)
541 /*FIXME: Only RGB dibs supported for now */
542 int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
543 int dstwidthb = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
544 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
545 int x, y;
547 if ((info->bmiHeader.biHeight < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
549 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
550 dstwidthb = -dstwidthb;
553 switch( info->bmiHeader.biBitCount ) {
555 case 15:
556 case 16: /* 16 bpp dstDIB */
558 LPWORD dstbits = (LPWORD)dbits;
559 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
561 /* FIXME: BI_BITFIELDS not supported yet */
563 switch(bmp->dib->dsBm.bmBitsPixel) {
565 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
567 /* FIXME: BI_BITFIELDS not supported yet */
568 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
569 memcpy(dbits, sbits, srcwidthb);
571 break;
573 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
575 LPBYTE srcbits = sbits;
577 for( y = 0; y < lines; y++) {
578 for( x = 0; x < srcwidth; x++ )
579 *dstbits++ = ((*srcbits++ >> 3) & bmask) |
580 (((WORD)*srcbits++ << 2) & gmask) |
581 (((WORD)*srcbits++ << 7) & rmask);
582 dstbits = (LPWORD)(dbits+=dstwidthb);
583 srcbits = (sbits += srcwidthb);
586 break;
588 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
590 LPDWORD srcbits = (LPDWORD)sbits;
591 DWORD val;
593 for( y = 0; y < lines; y++) {
594 for( x = 0; x < srcwidth; x++ ) {
595 val = *srcbits++;
596 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
597 ((val >> 9) & rmask));
599 dstbits = (LPWORD)(dbits+=dstwidthb);
600 srcbits = (LPDWORD)(sbits+=srcwidthb);
603 break;
605 default: /* ? bit bmp -> 16 bit DIB */
606 FIXME("15/16 bit DIB %d bit bitmap\n",
607 bmp->bitmap.bmBitsPixel);
608 break;
611 break;
613 case 24: /* 24 bpp dstDIB */
615 LPBYTE dstbits = dbits;
617 switch(bmp->dib->dsBm.bmBitsPixel) {
619 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
621 LPWORD srcbits = (LPWORD)sbits;
622 WORD val;
624 /* FIXME: BI_BITFIELDS not supported yet */
625 for( y = 0; y < lines; y++) {
626 for( x = 0; x < srcwidth; x++ ) {
627 val = *srcbits++;
628 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
629 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
630 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
632 dstbits = (LPBYTE)(dbits+=dstwidthb);
633 srcbits = (LPWORD)(sbits+=srcwidthb);
636 break;
638 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
640 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
641 memcpy(dbits, sbits, srcwidthb);
643 break;
645 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
647 LPBYTE srcbits = (LPBYTE)sbits;
649 for( y = 0; y < lines; y++) {
650 for( x = 0; x < srcwidth; x++, srcbits++ ) {
651 *dstbits++ = *srcbits++;
652 *dstbits++ = *srcbits++;
653 *dstbits++ = *srcbits++;
655 dstbits=(LPBYTE)(dbits+=dstwidthb);
656 srcbits = (LPBYTE)(sbits+=srcwidthb);
659 break;
661 default: /* ? bit bmp -> 24 bit DIB */
662 FIXME("24 bit DIB %d bit bitmap\n",
663 bmp->bitmap.bmBitsPixel);
664 break;
667 break;
669 case 32: /* 32 bpp dstDIB */
671 LPDWORD dstbits = (LPDWORD)dbits;
673 /* FIXME: BI_BITFIELDS not supported yet */
675 switch(bmp->dib->dsBm.bmBitsPixel) {
676 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
678 LPWORD srcbits = (LPWORD)sbits;
679 DWORD val;
681 /* FIXME: BI_BITFIELDS not supported yet */
682 for( y = 0; y < lines; y++) {
683 for( x = 0; x < srcwidth; x++ ) {
684 val = (DWORD)*srcbits++;
685 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
686 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
687 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
689 dstbits=(LPDWORD)(dbits+=dstwidthb);
690 srcbits=(LPWORD)(sbits+=srcwidthb);
693 break;
695 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
697 LPBYTE srcbits = sbits;
699 for( y = 0; y < lines; y++) {
700 for( x = 0; x < srcwidth; x++, srcbits+=3 )
701 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
702 dstbits=(LPDWORD)(dbits+=dstwidthb);
703 srcbits=(sbits+=srcwidthb);
706 break;
708 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
710 /* FIXME: BI_BITFIELDS not supported yet */
711 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
712 memcpy(dbits, sbits, srcwidthb);
714 break;
716 default: /* ? bit bmp -> 16 bit DIB */
717 FIXME("15/16 bit DIB %d bit bitmap\n",
718 bmp->bitmap.bmBitsPixel);
719 break;
722 break;
724 default: /* ? bit DIB */
725 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
726 break;
729 /* Otherwise, get bits from the XImage */
730 else if(!BITMAP_Driver->pGetDIBits(bmp, dc, startscan, lines, bits, info, coloruse, hbitmap))
732 GDI_HEAP_UNLOCK( hdc );
733 GDI_HEAP_UNLOCK( hbitmap );
735 return FALSE;
738 else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
740 /* fill in struct members */
742 if( info->bmiHeader.biBitCount == 0)
744 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
745 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
746 info->bmiHeader.biPlanes = 1;
747 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
748 info->bmiHeader.biSizeImage =
749 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
750 bmp->bitmap.bmHeight,
751 bmp->bitmap.bmBitsPixel );
752 info->bmiHeader.biCompression = 0;
754 else
756 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
757 info->bmiHeader.biWidth,
758 info->bmiHeader.biHeight,
759 info->bmiHeader.biBitCount );
763 TRACE("biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
764 info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
765 info->bmiHeader.biHeight);
767 GDI_HEAP_UNLOCK( hdc );
768 GDI_HEAP_UNLOCK( hbitmap );
770 return lines;
774 /***********************************************************************
775 * CreateDIBitmap16 (GDI.442)
777 HBITMAP16 WINAPI CreateDIBitmap16( HDC16 hdc, const BITMAPINFOHEADER * header,
778 DWORD init, LPCVOID bits, const BITMAPINFO * data,
779 UINT16 coloruse )
781 return CreateDIBitmap( hdc, header, init, bits, data, coloruse );
785 /***********************************************************************
786 * CreateDIBitmap (GDI32.37)
788 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
789 DWORD init, LPCVOID bits, const BITMAPINFO *data,
790 UINT coloruse )
792 HBITMAP handle;
793 BOOL fColor;
794 DWORD width;
795 int height;
796 WORD bpp;
797 WORD compr;
799 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
800 if (height < 0) height = -height;
802 /* Check if we should create a monochrome or color bitmap. */
803 /* We create a monochrome bitmap only if it has exactly 2 */
804 /* colors, which are black followed by white, nothing else. */
805 /* In all other cases, we create a color bitmap. */
807 if (bpp != 1) fColor = TRUE;
808 else if ((coloruse != DIB_RGB_COLORS) ||
809 (init != CBM_INIT) || !data) fColor = FALSE;
810 else
812 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
814 RGBQUAD *rgb = data->bmiColors;
815 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
817 /* Check if the first color of the colormap is black */
818 if ((col == RGB(0,0,0)))
820 rgb++;
821 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
822 /* If the second color is white, create a monochrome bitmap */
823 fColor = (col != RGB(0xff,0xff,0xff));
825 /* Note : If the first color of the colormap is white
826 followed by black, we have to create a color bitmap.
827 If we don't the white will be displayed in black later on!*/
828 else fColor = TRUE;
830 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
832 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
833 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
834 if ((col == RGB(0,0,0)))
836 rgb++;
837 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
838 fColor = (col != RGB(0xff,0xff,0xff));
840 else fColor = TRUE;
842 else
844 WARN("(%ld): wrong size for data\n",
845 data->bmiHeader.biSize );
846 return 0;
850 /* Now create the bitmap */
852 handle = fColor ? CreateBitmap( width, height, 1, MONITOR_GetDepth(&MONITOR_PrimaryMonitor), NULL ) :
853 CreateBitmap( width, height, 1, 1, NULL );
854 if (!handle) return 0;
856 if (init == CBM_INIT)
857 SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
858 return handle;
861 /***********************************************************************
862 * CreateDIBSection16 (GDI.489)
864 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, BITMAPINFO *bmi, UINT16 usage,
865 SEGPTR *bits, HANDLE section,
866 DWORD offset)
868 HBITMAP16 hbitmap;
869 DC *dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
870 if(!dc) dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
871 if(!dc) return (HBITMAP16) NULL;
873 hbitmap = dc->funcs->pCreateDIBSection16(dc, bmi, usage, bits, section, offset);
875 GDI_HEAP_UNLOCK(hdc);
877 return hbitmap;
880 /***********************************************************************
881 * CreateDIBSection (GDI32.36)
883 HBITMAP WINAPI CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
884 LPVOID *bits, HANDLE section,
885 DWORD offset)
887 HBITMAP hbitmap;
888 DC *dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
889 if(!dc) dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
890 if(!dc) return (HBITMAP) NULL;
892 hbitmap = dc->funcs->pCreateDIBSection(dc, bmi, usage, bits, section, offset);
894 GDI_HEAP_UNLOCK(hdc);
896 return hbitmap;
899 /***********************************************************************
900 * DIB_DeleteDIBSection
902 void DIB_DeleteDIBSection( BITMAPOBJ *bmp )
904 if (bmp && bmp->dib)
906 DIBSECTION *dib = bmp->dib;
908 if (dib->dsBm.bmBits)
910 if (dib->dshSection)
911 UnmapViewOfFile(dib->dsBm.bmBits);
912 else
913 VirtualFree(dib->dsBm.bmBits, 0L, MEM_RELEASE );
916 BITMAP_Driver->pDeleteDIBSection(bmp);
918 HeapFree(GetProcessHeap(), 0, dib);
919 bmp->dib = NULL;
923 /***********************************************************************
924 * DIB_FixColorsToLoadflags
926 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
927 * are in loadflags
929 void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
931 int colors;
932 COLORREF c_W, c_S, c_F, c_L, c_C;
933 int incr,i;
934 RGBQUAD *ptr;
936 if (bmi->bmiHeader.biBitCount > 8) return;
937 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
938 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
939 else {
940 WARN("Wrong bitmap header size!\n");
941 return;
943 colors = bmi->bmiHeader.biClrUsed;
944 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
945 colors = 1 << bmi->bmiHeader.biBitCount;
946 c_W = GetSysColor(COLOR_WINDOW);
947 c_S = GetSysColor(COLOR_3DSHADOW);
948 c_F = GetSysColor(COLOR_3DFACE);
949 c_L = GetSysColor(COLOR_3DLIGHT);
950 if (loadflags & LR_LOADTRANSPARENT) {
951 switch (bmi->bmiHeader.biBitCount) {
952 case 1: pix = pix >> 7; break;
953 case 4: pix = pix >> 4; break;
954 case 8: break;
955 default:
956 WARN("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
957 return;
959 if (pix >= colors) {
960 WARN("pixel has color index greater than biClrUsed!\n");
961 return;
963 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
964 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
965 ptr->rgbBlue = GetBValue(c_W);
966 ptr->rgbGreen = GetGValue(c_W);
967 ptr->rgbRed = GetRValue(c_W);
969 if (loadflags & LR_LOADMAP3DCOLORS)
970 for (i=0; i<colors; i++) {
971 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
972 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
973 if (c_C == RGB(128, 128, 128)) {
974 ptr->rgbRed = GetRValue(c_S);
975 ptr->rgbGreen = GetGValue(c_S);
976 ptr->rgbBlue = GetBValue(c_S);
977 } else if (c_C == RGB(192, 192, 192)) {
978 ptr->rgbRed = GetRValue(c_F);
979 ptr->rgbGreen = GetGValue(c_F);
980 ptr->rgbBlue = GetBValue(c_F);
981 } else if (c_C == RGB(223, 223, 223)) {
982 ptr->rgbRed = GetRValue(c_L);
983 ptr->rgbGreen = GetGValue(c_L);
984 ptr->rgbBlue = GetBValue(c_L);
989 /***********************************************************************
990 * DIB_CreateDIBFromBitmap
991 * Allocates a packed DIB and copies the bitmap data into it.
993 HGLOBAL DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
995 BITMAPOBJ *pBmp = NULL;
996 HGLOBAL hPackedDIB = 0;
997 LPBYTE pPackedDIB = NULL;
998 LPBITMAPINFOHEADER pbmiHeader = NULL;
999 unsigned int width, height, depth, cDataSize = 0, cPackedSize = 0,
1000 OffsetBits = 0, nLinesCopied = 0;
1002 /* Get a pointer to the BITMAPOBJ structure */
1003 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
1005 /* Get the bitmap dimensions */
1006 width = pBmp->bitmap.bmWidth;
1007 height = pBmp->bitmap.bmHeight;
1008 depth = pBmp->bitmap.bmBitsPixel;
1011 * A packed DIB contains a BITMAPINFO structure followed immediately by
1012 * an optional color palette and the pixel data.
1015 /* Calculate the size of the packed DIB */
1016 cDataSize = DIB_GetDIBImageBytes( width, height, depth );
1017 cPackedSize = sizeof(BITMAPINFOHEADER)
1018 + ( (depth <= 8) ? (sizeof(RGBQUAD) * (1 << depth)) : 0 )
1019 + cDataSize;
1020 /* Get the offset to the bits */
1021 OffsetBits = cPackedSize - cDataSize;
1023 /* Allocate the packed DIB */
1024 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
1025 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
1026 cPackedSize );
1027 if ( !hPackedDIB )
1029 WARN("Could not allocate packed DIB!\n");
1030 goto END;
1033 /* A packed DIB starts with a BITMAPINFOHEADER */
1034 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
1035 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
1037 /* Init the BITMAPINFOHEADER */
1038 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
1039 pbmiHeader->biWidth = width;
1040 pbmiHeader->biHeight = height;
1041 pbmiHeader->biPlanes = 1;
1042 pbmiHeader->biBitCount = depth;
1043 pbmiHeader->biCompression = BI_RGB;
1044 pbmiHeader->biSizeImage = 0;
1045 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
1046 pbmiHeader->biClrUsed = 0;
1047 pbmiHeader->biClrImportant = 0;
1049 /* Retrieve the DIB bits from the bitmap and fill in the
1050 * DIB color table if present */
1052 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
1053 hBmp, /* Handle to bitmap */
1054 0, /* First scan line to set in dest bitmap */
1055 height, /* Number of scan lines to copy */
1056 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
1057 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
1058 0); /* RGB or palette index */
1059 GlobalUnlock(hPackedDIB);
1061 /* Cleanup if GetDIBits failed */
1062 if (nLinesCopied != height)
1064 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, height);
1065 GlobalFree(hPackedDIB);
1066 hPackedDIB = 0;
1069 END:
1070 return hPackedDIB;