Release 960818
[wine/multimedia.git] / objects / dib.c
blob8d2907d619d7798fb615cd8aa69060c19a2e92dd
1 /*
2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <X11/Xlib.h>
10 #include <X11/Xutil.h>
11 #include "dc.h"
12 #include "bitmap.h"
13 #include "callback.h"
14 #include "palette.h"
15 #include "stddebug.h"
16 #include "color.h"
17 #include "debug.h"
18 #include "xmalloc.h"
20 extern void CLIPPING_UpdateGCRegion(DC* );
22 /***********************************************************************
23 * DIB_GetImageWidthBytes
25 * Return the width of an X image in bytes
27 int DIB_GetImageWidthBytes( int width, int depth )
29 int words;
31 switch(depth)
33 case 1: words = (width + 31) / 32; break;
34 case 4: words = (width + 7) / 8; break;
35 case 8: words = (width + 3) / 4; break;
36 case 15:
37 case 16: words = (width + 1) / 2; break;
38 case 24: words = width; break;
39 default:
40 fprintf(stderr, "DIB: unsupported depth %d.\n", depth );
41 exit(1);
43 return 4 * words;
47 /***********************************************************************
48 * DIB_BitmapInfoSize
50 * Return the size of the bitmap info structure.
52 int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
54 int colors;
56 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
58 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
59 colors = (core->bcBitCount != 24) ? 1 << core->bcBitCount : 0;
60 return sizeof(BITMAPCOREHEADER) + colors *
61 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
63 else /* assume BITMAPINFOHEADER */
65 colors = info->bmiHeader.biClrUsed;
66 if (!colors && (info->bmiHeader.biBitCount != 24))
67 colors = 1 << info->bmiHeader.biBitCount;
68 return sizeof(BITMAPINFOHEADER) + colors *
69 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
74 /***********************************************************************
75 * DIB_DIBmpToImage
77 * Create an XImage pointing to the bitmap data.
79 static XImage *DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
81 extern void _XInitImageFuncPtrs( XImage* );
82 XImage * image;
84 image = XCreateImage(display, DefaultVisualOfScreen( screen ),
85 bmp->biBitCount, ZPixmap, 0, bmpData,
86 bmp->biWidth, bmp->biHeight, 32,
87 DIB_GetImageWidthBytes(bmp->biWidth,bmp->biBitCount));
88 if (!image) return 0;
89 image->byte_order = MSBFirst;
90 image->bitmap_bit_order = MSBFirst;
91 image->bitmap_unit = 16;
92 _XInitImageFuncPtrs(image);
93 return image;
97 /***********************************************************************
98 * DIB_GetBitmapInfo
100 * Get the info from a bitmap header.
101 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
103 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
104 DWORD *height, WORD *bpp )
106 if (header->biSize == sizeof(BITMAPINFOHEADER))
108 *width = header->biWidth;
109 *height = header->biHeight;
110 *bpp = header->biBitCount;
111 return 1;
113 if (header->biSize == sizeof(BITMAPCOREHEADER))
115 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
116 *width = core->bcWidth;
117 *height = core->bcHeight;
118 *bpp = core->bcBitCount;
119 return 0;
121 fprintf( stderr, "DIB_GetBitmapInfo: wrong size (%ld) for header\n",
122 header->biSize );
123 return -1;
127 /***********************************************************************
128 * DIB_BuildColorMap
130 * Build the color map from the bitmap palette. Should not be called
131 * for a 24-bit deep bitmap.
133 static int *DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
134 BITMAPINFO *info )
136 int i, colors;
137 BOOL isInfo;
138 WORD *colorPtr;
139 int *colorMapping;
141 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
143 colors = info->bmiHeader.biClrUsed;
144 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
145 colorPtr = (WORD *)info->bmiColors;
147 else /* assume BITMAPCOREINFO */
149 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
150 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
152 if (!(colorMapping = (int *)malloc( colors * sizeof(int) ))) return NULL;
154 if (coloruse == DIB_RGB_COLORS)
156 if (isInfo)
158 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
160 if (depth == 1) /* Monochrome */
161 for (i = 0; i < colors; i++, rgb++)
162 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
163 rgb->rgbBlue > 255*3/2);
164 else
165 for (i = 0; i < colors; i++, rgb++)
166 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbRed,
167 rgb->rgbGreen,
168 rgb->rgbBlue));
170 else
172 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
174 if (depth == 1) /* Monochrome */
175 for (i = 0; i < colors; i++, rgb++)
176 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
177 rgb->rgbtBlue > 255*3/2);
178 else
179 for (i = 0; i < colors; i++, rgb++)
180 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbtRed,
181 rgb->rgbtGreen,
182 rgb->rgbtBlue));
185 else /* DIB_PAL_COLORS */
187 for (i = 0; i < colors; i++, colorPtr++)
188 colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
190 return colorMapping;
194 /***********************************************************************
195 * DIB_SetImageBits_1
197 * SetDIBits for a 1-bit deep DIB.
199 static void DIB_SetImageBits_1( WORD lines, BYTE *bits, WORD width,
200 int *colors, XImage *bmpImage )
202 WORD i, x;
203 BYTE pad, pix;
205 if (!(width & 31)) pad = 0;
206 else pad = ((32 - (width & 31)) + 7) / 8;
208 while (lines--)
210 for (i = width/8, x = 0; (i > 0); i--)
212 pix = *bits++;
213 XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
214 XPutPixel( bmpImage, x++, lines, colors[(pix >> 6) & 1] );
215 XPutPixel( bmpImage, x++, lines, colors[(pix >> 5) & 1] );
216 XPutPixel( bmpImage, x++, lines, colors[(pix >> 4) & 1] );
217 XPutPixel( bmpImage, x++, lines, colors[(pix >> 3) & 1] );
218 XPutPixel( bmpImage, x++, lines, colors[(pix >> 2) & 1] );
219 XPutPixel( bmpImage, x++, lines, colors[(pix >> 1) & 1] );
220 XPutPixel( bmpImage, x++, lines, colors[pix & 1] );
222 pix = *bits;
223 switch(width & 7)
225 case 7: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
226 case 6: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
227 case 5: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
228 case 4: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
229 case 3: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
230 case 2: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
231 case 1: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
233 bits += pad;
238 /***********************************************************************
239 * DIB_SetImageBits_4
241 * SetDIBits for a 4-bit deep DIB.
243 static void DIB_SetImageBits_4( WORD lines, BYTE *bits, WORD width,
244 int *colors, XImage *bmpImage )
246 WORD i, x;
247 BYTE pad;
249 if (!(width & 7)) pad = 0;
250 else pad = ((8 - (width & 7)) + 1) / 2;
252 while (lines--)
254 for (i = width/2, x = 0; i > 0; i--)
256 BYTE pix = *bits++;
257 XPutPixel( bmpImage, x++, lines, colors[pix >> 4] );
258 XPutPixel( bmpImage, x++, lines, colors[pix & 0x0f] );
260 if (width & 1) XPutPixel( bmpImage, x, lines, colors[*bits >> 4] );
261 bits += pad;
265 #define check_xy(x,y) \
266 if (x > width) { \
267 x = 0; \
268 if (lines) \
269 lines--; \
272 /***********************************************************************
273 * DIB_SetImageBits_RLE4
275 * SetDIBits for a 4-bit deep compressed DIB.
277 static void DIB_SetImageBits_RLE4( WORD lines, BYTE *bits, WORD width,
278 int *colors, XImage *bmpImage )
280 int x = 0, c, length;
281 BYTE *begin = bits;
283 lines--;
284 while ((short)lines >= 0)
286 length = *bits++;
287 if (length) { /* encoded */
288 c = *bits++;
289 while (length--) {
290 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
291 check_xy(x, y);
292 if (length) {
293 length--;
294 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
295 check_xy(x, y);
298 } else {
299 length = *bits++;
300 switch (length) {
301 case 0: /* eol */
302 x = 0;
303 lines--;
304 continue;
306 case 1: /* eopicture */
307 return;
309 case 2: /* delta */
310 x += *bits++;
311 lines -= *bits++;
312 continue;
314 default: /* absolute */
315 while (length--) {
316 c = *bits++;
317 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
318 check_xy(x, y);
319 if (length) {
320 length--;
321 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
322 check_xy(x, y);
325 if ((bits - begin) & 1)
326 bits++;
332 /***********************************************************************
333 * DIB_SetImageBits_8
335 * SetDIBits for an 8-bit deep DIB.
337 static void DIB_SetImageBits_8( WORD lines, BYTE *bits, WORD width,
338 int *colors, XImage *bmpImage )
340 WORD x;
341 BYTE pad = (4 - (width & 3)) & 3;
343 while (lines--)
345 for (x = 0; x < width; x++)
346 XPutPixel( bmpImage, x, lines, colors[*bits++] );
347 bits += pad;
351 /***********************************************************************
352 * DIB_SetImageBits_RLE8
354 * SetDIBits for an 8-bit deep compressed DIB.
356 * This function rewritten 941113 by James Youngman. WINE blew out when I
357 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
359 * This was because the algorithm assumed that all RLE8 bitmaps end with the
360 * 'End of bitmap' escape code. This code is very much laxer in what it
361 * allows to end the expansion. Possibly too lax. See the note by
362 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
363 * bitmap should end with RleEnd, but on the other hand, software exists
364 * that produces ones that don't and Windows 3.1 doesn't complain a bit
365 * about it.
367 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
368 * James A. Youngman <mbcstjy@afs.man.ac.uk>
369 * [JAY]
372 enum Rle8_EscapeCodes
375 * Apologies for polluting your file's namespace...
377 RleEol = 0, /* End of line */
378 RleEnd = 1, /* End of bitmap */
379 RleDelta = 2 /* Delta */
382 static void DIB_SetImageBits_RLE8(WORD lines,
383 BYTE *bits,
384 WORD width,
385 int *colors,
386 XImage *bmpImage)
388 int x; /* X-positon on each line. Increases. */
389 int line; /* Line #. Starts at lines-1, decreases */
390 BYTE *pIn = bits; /* Pointer to current position in bits */
391 BYTE length; /* The length pf a run */
392 BYTE color_index; /* index into colors[] as read from bits */
393 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
394 WORD color; /* value of colour[color_index] */
396 if (lines == 0) /* Let's hope this doesn't happen. */
397 return;
400 * Note that the bitmap data is stored by Windows starting at the
401 * bottom line of the bitmap and going upwards. Within each line,
402 * the data is stored left-to-right. That's the reason why line
403 * goes from lines-1 to 0. [JAY]
406 x = 0;
407 line = lines-1;
410 length = *pIn++;
413 * If the length byte is not zero (which is the escape value),
414 * We have a run of length pixels all the same colour. The colour
415 * index is stored next.
417 * If the length byte is zero, we need to read the next byte to
418 * know what to do. [JAY]
420 if (length != 0)
423 * [Run-Length] Encoded mode
425 color_index = (*pIn++); /* Get the colour index. */
426 color = colors[color_index];
428 while(length--)
429 XPutPixel(bmpImage, x++, line, color);
431 else
434 * Escape codes (may be an absolute sequence though)
436 escape_code = (*pIn++);
437 switch(escape_code)
439 case RleEol: /* =0, end of line */
441 x = 0;
442 line--;
443 break;
446 case RleEnd: /* =1, end of bitmap */
449 * Not all RLE8 bitmaps end with this
450 * code. For example, Paint Shop Pro
451 * produces some that don't. That's (I think)
452 * what caused the previous implementation to
453 * fail. [JAY]
455 line=-1; /* Cause exit from do loop. */
456 break;
459 case RleDelta: /* =2, a delta */
462 * Note that deltaing to line 0
463 * will cause an exit from the loop,
464 * which may not be what is intended.
465 * The fact that there is a delta in the bits
466 * almost certainly implies that there is data
467 * to follow. You may feel that we should
468 * jump to the top of the loop to avoid exiting
469 * in this case.
471 * TODO: Decide what to do here in that case. [JAY]
473 x += (*pIn++);
474 line -= (*pIn++);
475 if (line == 0)
477 dprintf_bitmap(stddeb,
478 "DIB_SetImageBits_RLE8(): "
479 "Delta to last line of bitmap "
480 "(wrongly?) causes loop exit\n");
482 break;
485 default: /* >2, switch to absolute mode */
488 * Absolute Mode
490 length = escape_code;
491 while(length--)
493 color_index = (*pIn++);
494 XPutPixel(bmpImage, x++, line,
495 colors[color_index]);
499 * If you think for a moment you'll realise that the
500 * only time we could ever possibly read an odd
501 * number of bytes is when there is a 0x00 (escape),
502 * a value >0x02 (absolute mode) and then an odd-
503 * length run. Therefore this is the only place we
504 * need to worry about it. Everywhere else the
505 * bytes are always read in pairs. [JAY]
507 if (escape_code & 1)
508 pIn++; /* Throw away the pad byte. */
509 break;
511 } /* switch (escape_code) : Escape sequence */
512 } /* process either an encoded sequence or an escape sequence */
514 /* We expect to come here more than once per line. */
515 } while (line >= 0); /* Do this until the bitmap is filled */
518 * Everybody comes here at the end.
519 * Check how we exited the loop and print a message if it's a bit odd.
520 * [JAY]
522 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
524 dprintf_bitmap(stddeb, "DIB_SetImageBits_RLE8(): End-of-bitmap "
525 "without (strictly) proper escape code. Last two "
526 "bytes were: %02X %02X.\n",
527 (int)*(pIn-2),
528 (int)*(pIn-1));
533 /***********************************************************************
534 * DIB_SetImageBits_24
536 * SetDIBits for a 24-bit deep DIB.
538 static void DIB_SetImageBits_24( WORD lines, BYTE *bits, WORD width,
539 DC *dc, XImage *bmpImage )
541 WORD x;
542 BYTE pad = (4 - ((width*3) & 3)) & 3;
544 /* "bits" order is reversed for some reason */
546 while (lines--)
548 for (x = 0; x < width; x++, bits += 3)
549 XPutPixel( bmpImage, x, lines,
550 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])) );
552 bits += pad;
557 /***********************************************************************
558 * DIB_SetImageBits
560 * Transfer the bits to an X image.
561 * Helper function for SetDIBits() and SetDIBitsToDevice().
563 static int DIB_SetImageBits( DC *dc, WORD lines, WORD depth, LPSTR bits,
564 DWORD infoWidth, WORD infoBpp,
565 BITMAPINFO *info, WORD coloruse,
566 Drawable drawable, GC gc, int xSrc, int ySrc,
567 int xDest, int yDest, int width, int height )
569 int *colorMapping;
570 XImage *bmpImage;
571 DWORD compression = 0;
573 if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
574 compression = info->bmiHeader.biCompression;
576 /* Build the color mapping table */
578 if (infoBpp == 24) colorMapping = NULL;
579 else
580 if (!(colorMapping = DIB_BuildColorMap( dc, coloruse, depth, info )))
581 return 0;
583 if( dc->w.flags & DC_DIRTY ) CLIPPING_UpdateGCRegion(dc);
585 /* Transfer the pixels */
586 XCREATEIMAGE(bmpImage, infoWidth, lines, depth );
588 switch(infoBpp)
590 case 1:
591 DIB_SetImageBits_1( lines, bits, infoWidth,
592 colorMapping, bmpImage );
593 break;
594 case 4:
595 if (compression) DIB_SetImageBits_RLE4( lines, bits, infoWidth,
596 colorMapping, bmpImage );
597 else DIB_SetImageBits_4( lines, bits, infoWidth,
598 colorMapping, bmpImage );
599 break;
600 case 8:
601 if (compression) DIB_SetImageBits_RLE8( lines, bits, infoWidth,
602 colorMapping, bmpImage );
603 else DIB_SetImageBits_8( lines, bits, infoWidth,
604 colorMapping, bmpImage );
605 break;
606 case 24:
607 DIB_SetImageBits_24( lines, bits, infoWidth, dc, bmpImage );
608 break;
609 default:
610 fprintf( stderr, "Invalid depth %d for SetDIBits!\n", infoBpp );
611 break;
613 if (colorMapping) free(colorMapping);
614 XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
615 xDest, yDest, width, height );
616 XDestroyImage( bmpImage );
617 return lines;
621 /***********************************************************************
622 * StretchDIBits (GDI.439)
624 int StretchDIBits( HDC hdc,
625 WORD xDest, WORD yDest, WORD wDestWidth, WORD wDestHeight,
626 WORD xSrc, WORD ySrc, WORD wSrcWidth, WORD wSrcHeight,
627 LPSTR bits, LPBITMAPINFO info, WORD wUsage, DWORD dwRop )
629 HBITMAP hBitmap, hOldBitmap;
630 HDC hdcMem;
632 hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
633 bits, info, wUsage );
634 hdcMem = CreateCompatibleDC( hdc );
635 hOldBitmap = SelectObject( hdcMem, hBitmap );
636 StretchBlt( hdc, xDest, yDest, wDestWidth, wDestHeight,
637 hdcMem, xSrc, ySrc, wSrcWidth, wSrcHeight, dwRop );
638 SelectObject( hdcMem, hOldBitmap );
639 DeleteDC( hdcMem );
640 DeleteObject( hBitmap );
641 return wSrcHeight;
645 /***********************************************************************
646 * SetDIBits (GDI.440) (GDI32.312)
648 INT16 SetDIBits( HDC32 hdc, HBITMAP32 hbitmap, UINT32 startscan, UINT32 lines,
649 LPCVOID bits, const BITMAPINFO *info, UINT32 coloruse )
651 DC * dc;
652 BITMAPOBJ * bmp;
653 DWORD width, height;
654 WORD bpp;
656 /* Check parameters */
658 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
659 if (!dc)
661 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
662 if (!dc) return 0;
664 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
665 return 0;
666 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
667 return 0;
668 if (!lines || (startscan >= (WORD)height)) return 0;
669 if (startscan + lines > height) lines = height - startscan;
671 return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 16,
672 dc, lines, bmp->bitmap.bmBitsPixel,
673 bits, width, bpp, info,
674 coloruse, bmp->pixmap, BITMAP_GC(bmp), 0, 0, 0,
675 startscan, bmp->bitmap.bmWidth, lines );
679 /***********************************************************************
680 * SetDIBitsToDevice (GDI.443) (GDI32.313)
682 INT16 SetDIBitsToDevice( HDC32 hdc, INT32 xDest, INT32 yDest, DWORD cx,
683 DWORD cy, INT32 xSrc, INT32 ySrc, UINT32 startscan,
684 UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
685 UINT32 coloruse )
687 DC * dc;
688 DWORD width, height;
689 WORD bpp;
691 /* Check parameters */
693 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
694 if (!dc)
696 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
697 if (!dc) return 0;
699 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
700 return 0;
701 if (!lines || (startscan >= height)) return 0;
702 if (startscan + lines > height) lines = height - startscan;
703 if (ySrc < startscan) ySrc = startscan;
704 else if (ySrc >= startscan + lines) return 0;
705 if (xSrc >= width) return 0;
706 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
707 if (xSrc + cx >= width) cx = width - xSrc;
708 if (!cx || !cy) return 0;
710 DC_SetupGCForText( dc ); /* To have the correct colors */
711 XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
712 return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 16,
713 dc, lines, dc->w.bitsPerPixel, bits, width,
714 bpp, info, coloruse,
715 dc->u.x.drawable, dc->u.x.gc,
716 xSrc, ySrc - startscan,
717 dc->w.DCOrgX + XLPTODP( dc, xDest ),
718 dc->w.DCOrgY + YLPTODP( dc, yDest ),
719 cx, cy );
724 /***********************************************************************
725 * GetDIBits (GDI.441)
727 int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
728 LPSTR bits, BITMAPINFO * info, WORD coloruse )
730 DC * dc;
731 BITMAPOBJ * bmp;
732 PALETTEENTRY * palEntry;
733 PALETTEOBJ * palette;
734 XImage * bmpImage, * dibImage;
735 int i, x, y;
737 if (!lines) return 0;
738 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
739 if (!dc)
741 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
742 if (!dc) return 0;
744 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
745 return 0;
746 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
747 return 0;
749 /* Transfer color info */
751 palEntry = palette->logpalette.palPalEntry;
752 for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
754 if (coloruse == DIB_RGB_COLORS)
756 info->bmiColors[i].rgbRed = palEntry->peRed;
757 info->bmiColors[i].rgbGreen = palEntry->peGreen;
758 info->bmiColors[i].rgbBlue = palEntry->peBlue;
759 info->bmiColors[i].rgbReserved = 0;
761 else ((WORD *)info->bmiColors)[i] = (WORD)i;
764 /* Transfer the pixels (very slow...) */
766 if (bits)
768 bmpImage = (XImage *)CallTo32_LargeStack( (int (*)())XGetImage, 8,
769 display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
770 bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
771 dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
773 for (y = 0; y < lines; y++)
775 for (x = 0; x < info->bmiHeader.biWidth; x++)
777 XPutPixel( dibImage, x, y,
778 XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
783 dibImage->data = NULL;
784 XDestroyImage( dibImage );
785 XDestroyImage( bmpImage );
787 info->bmiHeader.biCompression = 0;
788 return lines;
792 /***********************************************************************
793 * CreateDIBitmap (GDI.442)
795 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
796 LPVOID bits, BITMAPINFO * data, UINT coloruse )
798 HBITMAP handle;
799 BOOL fColor;
800 DWORD width, height;
801 WORD bpp;
803 if (DIB_GetBitmapInfo( header, &width, &height, &bpp ) == -1) return 0;
805 /* Check if we should create a monochrome or color bitmap. */
806 /* We create a monochrome bitmap only if it has exactly 2 */
807 /* colors, which are either black or white, nothing else. */
808 /* In all other cases, we create a color bitmap. */
810 if (bpp != 1) fColor = TRUE;
811 else if ((coloruse != DIB_RGB_COLORS) ||
812 (init != CBM_INIT) || !data) fColor = FALSE;
813 else
815 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
817 RGBQUAD *rgb = data->bmiColors;
818 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
819 if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
821 rgb++;
822 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
823 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
825 else fColor = TRUE;
827 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
829 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
830 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
831 if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
833 rgb++;
834 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
835 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
837 else fColor = TRUE;
839 else
841 fprintf( stderr, "CreateDIBitmap: wrong size (%ld) for data\n",
842 data->bmiHeader.biSize );
843 return 0;
847 /* Now create the bitmap */
849 handle = fColor ? CreateCompatibleBitmap( hdc, width, height ) :
850 CreateBitmap( width, height, 1, 1, NULL );
851 if (!handle) return 0;
853 if (init == CBM_INIT)
854 SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
855 return handle;