Release 960728
[wine/multimedia.git] / objects / dib.c
blobef9f072aed7a2dc7e5d5f3b9a80bde11687e182a
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 "stackframe.h"
16 #include "stddebug.h"
17 #include "color.h"
18 #include "debug.h"
19 #include "xmalloc.h"
21 extern void CLIPPING_UpdateGCRegion(DC* );
23 /***********************************************************************
24 * DIB_GetImageWidthBytes
26 * Return the width of an X image in bytes
28 int DIB_GetImageWidthBytes( int width, int depth )
30 int words;
32 switch(depth)
34 case 1: words = (width + 31) / 32; break;
35 case 4: words = (width + 7) / 8; break;
36 case 8: words = (width + 3) / 4; break;
37 case 15:
38 case 16: words = (width + 1) / 2; break;
39 case 24: words = width; break;
40 default:
41 fprintf(stderr, "DIB: unsupported depth %d.\n", depth );
42 exit(1);
44 return 4 * words;
48 /***********************************************************************
49 * DIB_BitmapInfoSize
51 * Return the size of the bitmap info structure.
53 int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
55 int colors;
57 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
59 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
60 colors = (core->bcBitCount != 24) ? 1 << core->bcBitCount : 0;
61 return sizeof(BITMAPCOREHEADER) + colors *
62 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
64 else /* assume BITMAPINFOHEADER */
66 colors = info->bmiHeader.biClrUsed;
67 if (!colors && (info->bmiHeader.biBitCount != 24))
68 colors = 1 << info->bmiHeader.biBitCount;
69 return sizeof(BITMAPINFOHEADER) + colors *
70 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
75 /***********************************************************************
76 * DIB_DIBmpToImage
78 * Create an XImage pointing to the bitmap data.
80 static XImage *DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
82 extern void _XInitImageFuncPtrs( XImage* );
83 XImage * image;
85 image = XCreateImage(display, DefaultVisualOfScreen( screen ),
86 bmp->biBitCount, ZPixmap, 0, bmpData,
87 bmp->biWidth, bmp->biHeight, 32,
88 DIB_GetImageWidthBytes(bmp->biWidth,bmp->biBitCount));
89 if (!image) return 0;
90 image->byte_order = MSBFirst;
91 image->bitmap_bit_order = MSBFirst;
92 image->bitmap_unit = 16;
93 _XInitImageFuncPtrs(image);
94 return image;
98 /***********************************************************************
99 * DIB_GetBitmapInfo
101 * Get the info from a bitmap header.
102 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
104 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
105 DWORD *height, WORD *bpp )
107 if (header->biSize == sizeof(BITMAPINFOHEADER))
109 *width = header->biWidth;
110 *height = header->biHeight;
111 *bpp = header->biBitCount;
112 return 1;
114 if (header->biSize == sizeof(BITMAPCOREHEADER))
116 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
117 *width = core->bcWidth;
118 *height = core->bcHeight;
119 *bpp = core->bcBitCount;
120 return 0;
122 fprintf( stderr, "DIB_GetBitmapInfo: wrong size (%ld) for header\n",
123 header->biSize );
124 return -1;
128 /***********************************************************************
129 * DIB_BuildColorMap
131 * Build the color map from the bitmap palette. Should not be called
132 * for a 24-bit deep bitmap.
134 static int *DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
135 BITMAPINFO *info )
137 int i, colors;
138 BOOL isInfo;
139 WORD *colorPtr;
140 int *colorMapping;
142 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
144 colors = info->bmiHeader.biClrUsed;
145 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
146 colorPtr = (WORD *)info->bmiColors;
148 else /* assume BITMAPCOREINFO */
150 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
151 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
153 if (!(colorMapping = (int *)malloc( colors * sizeof(int) ))) return NULL;
155 if (coloruse == DIB_RGB_COLORS)
157 if (isInfo)
159 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
161 if (depth == 1) /* Monochrome */
162 for (i = 0; i < colors; i++, rgb++)
163 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
164 rgb->rgbBlue > 255*3/2);
165 else
166 for (i = 0; i < colors; i++, rgb++)
167 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbRed,
168 rgb->rgbGreen,
169 rgb->rgbBlue));
171 else
173 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
175 if (depth == 1) /* Monochrome */
176 for (i = 0; i < colors; i++, rgb++)
177 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
178 rgb->rgbtBlue > 255*3/2);
179 else
180 for (i = 0; i < colors; i++, rgb++)
181 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbtRed,
182 rgb->rgbtGreen,
183 rgb->rgbtBlue));
186 else /* DIB_PAL_COLORS */
188 for (i = 0; i < colors; i++, colorPtr++)
189 colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
191 return colorMapping;
195 /***********************************************************************
196 * DIB_SetImageBits_1
198 * SetDIBits for a 1-bit deep DIB.
200 static void DIB_SetImageBits_1( WORD lines, BYTE *bits, WORD width,
201 int *colors, XImage *bmpImage )
203 WORD i, x;
204 BYTE pad, pix;
206 if (!(width & 31)) pad = 0;
207 else pad = ((32 - (width & 31)) + 7) / 8;
209 while (lines--)
211 for (i = width/8, x = 0; (i > 0); i--)
213 pix = *bits++;
214 XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
215 XPutPixel( bmpImage, x++, lines, colors[(pix >> 6) & 1] );
216 XPutPixel( bmpImage, x++, lines, colors[(pix >> 5) & 1] );
217 XPutPixel( bmpImage, x++, lines, colors[(pix >> 4) & 1] );
218 XPutPixel( bmpImage, x++, lines, colors[(pix >> 3) & 1] );
219 XPutPixel( bmpImage, x++, lines, colors[(pix >> 2) & 1] );
220 XPutPixel( bmpImage, x++, lines, colors[(pix >> 1) & 1] );
221 XPutPixel( bmpImage, x++, lines, colors[pix & 1] );
223 pix = *bits;
224 switch(width & 7)
226 case 7: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
227 case 6: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
228 case 5: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
229 case 4: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
230 case 3: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
231 case 2: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
232 case 1: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
234 bits += pad;
239 /***********************************************************************
240 * DIB_SetImageBits_4
242 * SetDIBits for a 4-bit deep DIB.
244 static void DIB_SetImageBits_4( WORD lines, BYTE *bits, WORD width,
245 int *colors, XImage *bmpImage )
247 WORD i, x;
248 BYTE pad;
250 if (!(width & 7)) pad = 0;
251 else pad = ((8 - (width & 7)) + 1) / 2;
253 while (lines--)
255 for (i = width/2, x = 0; i > 0; i--)
257 BYTE pix = *bits++;
258 XPutPixel( bmpImage, x++, lines, colors[pix >> 4] );
259 XPutPixel( bmpImage, x++, lines, colors[pix & 0x0f] );
261 if (width & 1) XPutPixel( bmpImage, x, lines, colors[*bits >> 4] );
262 bits += pad;
266 #define check_xy(x,y) \
267 if (x > width) { \
268 x = 0; \
269 if (lines) \
270 lines--; \
273 /***********************************************************************
274 * DIB_SetImageBits_RLE4
276 * SetDIBits for a 4-bit deep compressed DIB.
278 static void DIB_SetImageBits_RLE4( WORD lines, BYTE *bits, WORD width,
279 int *colors, XImage *bmpImage )
281 int x = 0, c, length;
282 BYTE *begin = bits;
284 lines--;
285 while ((short)lines >= 0)
287 length = *bits++;
288 if (length) { /* encoded */
289 c = *bits++;
290 while (length--) {
291 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
292 check_xy(x, y);
293 if (length) {
294 length--;
295 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
296 check_xy(x, y);
299 } else {
300 length = *bits++;
301 switch (length) {
302 case 0: /* eol */
303 x = 0;
304 lines--;
305 continue;
307 case 1: /* eopicture */
308 return;
310 case 2: /* delta */
311 x += *bits++;
312 lines -= *bits++;
313 continue;
315 default: /* absolute */
316 while (length--) {
317 c = *bits++;
318 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
319 check_xy(x, y);
320 if (length) {
321 length--;
322 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
323 check_xy(x, y);
326 if ((bits - begin) & 1)
327 bits++;
333 /***********************************************************************
334 * DIB_SetImageBits_8
336 * SetDIBits for an 8-bit deep DIB.
338 static void DIB_SetImageBits_8( WORD lines, BYTE *bits, WORD width,
339 int *colors, XImage *bmpImage )
341 WORD x;
342 BYTE pad = (4 - (width & 3)) & 3;
344 while (lines--)
346 for (x = 0; x < width; x++)
347 XPutPixel( bmpImage, x, lines, colors[*bits++] );
348 bits += pad;
352 /***********************************************************************
353 * DIB_SetImageBits_RLE8
355 * SetDIBits for an 8-bit deep compressed DIB.
357 * This function rewritten 941113 by James Youngman. WINE blew out when I
358 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
360 * This was because the algorithm assumed that all RLE8 bitmaps end with the
361 * 'End of bitmap' escape code. This code is very much laxer in what it
362 * allows to end the expansion. Possibly too lax. See the note by
363 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
364 * bitmap should end with RleEnd, but on the other hand, software exists
365 * that produces ones that don't and Windows 3.1 doesn't complain a bit
366 * about it.
368 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
369 * James A. Youngman <mbcstjy@afs.man.ac.uk>
370 * [JAY]
373 enum Rle8_EscapeCodes
376 * Apologies for polluting your file's namespace...
378 RleEol = 0, /* End of line */
379 RleEnd = 1, /* End of bitmap */
380 RleDelta = 2 /* Delta */
383 static void DIB_SetImageBits_RLE8(WORD lines,
384 BYTE *bits,
385 WORD width,
386 int *colors,
387 XImage *bmpImage)
389 int x; /* X-positon on each line. Increases. */
390 int line; /* Line #. Starts at lines-1, decreases */
391 BYTE *pIn = bits; /* Pointer to current position in bits */
392 BYTE length; /* The length pf a run */
393 BYTE color_index; /* index into colors[] as read from bits */
394 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
395 WORD color; /* value of colour[color_index] */
397 if (lines == 0) /* Let's hope this doesn't happen. */
398 return;
401 * Note that the bitmap data is stored by Windows starting at the
402 * bottom line of the bitmap and going upwards. Within each line,
403 * the data is stored left-to-right. That's the reason why line
404 * goes from lines-1 to 0. [JAY]
407 x = 0;
408 line = lines-1;
411 length = *pIn++;
414 * If the length byte is not zero (which is the escape value),
415 * We have a run of length pixels all the same colour. The colour
416 * index is stored next.
418 * If the length byte is zero, we need to read the next byte to
419 * know what to do. [JAY]
421 if (length != 0)
424 * [Run-Length] Encoded mode
426 color_index = (*pIn++); /* Get the colour index. */
427 color = colors[color_index];
429 while(length--)
430 XPutPixel(bmpImage, x++, line, color);
432 else
435 * Escape codes (may be an absolute sequence though)
437 escape_code = (*pIn++);
438 switch(escape_code)
440 case RleEol: /* =0, end of line */
442 x = 0;
443 line--;
444 break;
447 case RleEnd: /* =1, end of bitmap */
450 * Not all RLE8 bitmaps end with this
451 * code. For example, Paint Shop Pro
452 * produces some that don't. That's (I think)
453 * what caused the previous implementation to
454 * fail. [JAY]
456 line=-1; /* Cause exit from do loop. */
457 break;
460 case RleDelta: /* =2, a delta */
463 * Note that deltaing to line 0
464 * will cause an exit from the loop,
465 * which may not be what is intended.
466 * The fact that there is a delta in the bits
467 * almost certainly implies that there is data
468 * to follow. You may feel that we should
469 * jump to the top of the loop to avoid exiting
470 * in this case.
472 * TODO: Decide what to do here in that case. [JAY]
474 x += (*pIn++);
475 line -= (*pIn++);
476 if (line == 0)
478 dprintf_bitmap(stddeb,
479 "DIB_SetImageBits_RLE8(): "
480 "Delta to last line of bitmap "
481 "(wrongly?) causes loop exit\n");
483 break;
486 default: /* >2, switch to absolute mode */
489 * Absolute Mode
491 length = escape_code;
492 while(length--)
494 color_index = (*pIn++);
495 XPutPixel(bmpImage, x++, line,
496 colors[color_index]);
500 * If you think for a moment you'll realise that the
501 * only time we could ever possibly read an odd
502 * number of bytes is when there is a 0x00 (escape),
503 * a value >0x02 (absolute mode) and then an odd-
504 * length run. Therefore this is the only place we
505 * need to worry about it. Everywhere else the
506 * bytes are always read in pairs. [JAY]
508 if (escape_code & 1)
509 pIn++; /* Throw away the pad byte. */
510 break;
512 } /* switch (escape_code) : Escape sequence */
513 } /* process either an encoded sequence or an escape sequence */
515 /* We expect to come here more than once per line. */
516 } while (line >= 0); /* Do this until the bitmap is filled */
519 * Everybody comes here at the end.
520 * Check how we exited the loop and print a message if it's a bit odd.
521 * [JAY]
523 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
525 dprintf_bitmap(stddeb, "DIB_SetImageBits_RLE8(): End-of-bitmap "
526 "without (strictly) proper escape code. Last two "
527 "bytes were: %02X %02X.\n",
528 (int)*(pIn-2),
529 (int)*(pIn-1));
534 /***********************************************************************
535 * DIB_SetImageBits_24
537 * SetDIBits for a 24-bit deep DIB.
539 static void DIB_SetImageBits_24( WORD lines, BYTE *bits, WORD width,
540 DC *dc, XImage *bmpImage )
542 WORD x;
543 BYTE pad = (4 - ((width*3) & 3)) & 3;
545 /* "bits" order is reversed for some reason */
547 while (lines--)
549 for (x = 0; x < width; x++, bits += 3)
550 XPutPixel( bmpImage, x, lines,
551 COLOR_ToPhysical(dc, RGB(bits[2],bits[1],bits[0])) );
553 bits += pad;
558 /***********************************************************************
559 * DIB_SetImageBits
561 * Transfer the bits to an X image.
562 * Helper function for SetDIBits() and SetDIBitsToDevice().
564 static int DIB_SetImageBits( DC *dc, WORD lines, WORD depth, LPSTR bits,
565 DWORD infoWidth, WORD infoBpp, DWORD compression,
566 BITMAPINFO *info, WORD coloruse,
567 Drawable drawable, GC gc, int xSrc, int ySrc,
568 int xDest, int yDest, int width, int height )
570 int *colorMapping;
571 XImage *bmpImage;
573 /* Build the color mapping table */
575 if (infoBpp == 24) colorMapping = NULL;
576 else
577 if (!(colorMapping = DIB_BuildColorMap( dc, coloruse, depth, info )))
578 return 0;
580 if( dc->w.flags & DC_DIRTY ) CLIPPING_UpdateGCRegion(dc);
582 /* Transfer the pixels */
583 XCREATEIMAGE(bmpImage, infoWidth, lines, depth );
585 switch(infoBpp)
587 case 1:
588 DIB_SetImageBits_1( lines, bits, infoWidth,
589 colorMapping, bmpImage );
590 break;
591 case 4:
592 if (compression) DIB_SetImageBits_RLE4( lines, bits, infoWidth,
593 colorMapping, bmpImage );
594 else DIB_SetImageBits_4( lines, bits, infoWidth,
595 colorMapping, bmpImage );
596 break;
597 case 8:
598 if (compression) DIB_SetImageBits_RLE8( lines, bits, infoWidth,
599 colorMapping, bmpImage );
600 else DIB_SetImageBits_8( lines, bits, infoWidth,
601 colorMapping, bmpImage );
602 break;
603 case 24:
604 DIB_SetImageBits_24( lines, bits, infoWidth, dc, bmpImage );
605 break;
606 default:
607 fprintf( stderr, "Invalid depth %d for SetDIBits!\n", infoBpp );
608 break;
610 if (colorMapping) free(colorMapping);
611 XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
612 xDest, yDest, width, height );
613 XDestroyImage( bmpImage );
614 return lines;
618 /***********************************************************************
619 * StretchDIBits (GDI.439)
621 int StretchDIBits( HDC hdc,
622 WORD xDest, WORD yDest, WORD wDestWidth, WORD wDestHeight,
623 WORD xSrc, WORD ySrc, WORD wSrcWidth, WORD wSrcHeight,
624 LPSTR bits, LPBITMAPINFO info, WORD wUsage, DWORD dwRop )
626 HBITMAP hBitmap, hOldBitmap;
627 HDC hdcMem;
629 hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
630 bits, info, wUsage );
631 hdcMem = CreateCompatibleDC( hdc );
632 hOldBitmap = SelectObject( hdcMem, hBitmap );
633 StretchBlt( hdc, xDest, yDest, wDestWidth, wDestHeight,
634 hdcMem, xSrc, ySrc, wSrcWidth, wSrcHeight, dwRop );
635 SelectObject( hdcMem, hOldBitmap );
636 DeleteDC( hdcMem );
637 DeleteObject( hBitmap );
638 return wSrcHeight;
642 /***********************************************************************
643 * SetDIBits (GDI.440) (GDI32.312)
645 INT16 SetDIBits( HDC32 hdc, HBITMAP32 hbitmap, UINT32 startscan, UINT32 lines,
646 LPCVOID bits, const BITMAPINFO *info, UINT32 coloruse )
648 DC * dc;
649 BITMAPOBJ * bmp;
650 DWORD width, height, compression = 0;
651 WORD bpp;
653 /* Check parameters */
655 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
656 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
657 return 0;
658 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
659 return 0;
660 if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
661 compression = info->bmiHeader.biCompression;
662 if (!lines || (startscan >= (WORD)height)) return 0;
663 if (startscan + lines > height) lines = height - startscan;
665 return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
666 dc, lines, bmp->bitmap.bmBitsPixel,
667 bits, width, bpp, compression, info,
668 coloruse, bmp->pixmap, BITMAP_GC(bmp), 0, 0, 0,
669 startscan, bmp->bitmap.bmWidth, lines );
673 /***********************************************************************
674 * SetDIBitsToDevice (GDI.443) (GDI32.313)
676 INT16 SetDIBitsToDevice( HDC32 hdc, INT32 xDest, INT32 yDest, DWORD cx,
677 DWORD cy, INT32 xSrc, INT32 ySrc, UINT32 startscan,
678 UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
679 UINT32 coloruse )
681 DC * dc;
682 DWORD width, height, compression = 0;
683 WORD bpp;
685 /* Check parameters */
687 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
688 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
689 return 0;
690 if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
691 compression = info->bmiHeader.biCompression;
692 if (!lines || (startscan >= height)) return 0;
693 if (startscan + lines > height) lines = height - startscan;
694 if (ySrc < startscan) ySrc = startscan;
695 else if (ySrc >= startscan + lines) return 0;
696 if (xSrc >= width) return 0;
697 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
698 if (xSrc + cx >= width) cx = width - xSrc;
699 if (!cx || !cy) return 0;
701 DC_SetupGCForText( dc ); /* To have the correct colors */
702 XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
703 return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
704 dc, lines, dc->w.bitsPerPixel, bits, width,
705 bpp, compression, info, coloruse,
706 dc->u.x.drawable, dc->u.x.gc,
707 xSrc, ySrc - startscan,
708 dc->w.DCOrgX + XLPTODP( dc, xDest ),
709 dc->w.DCOrgY + YLPTODP( dc, yDest ),
710 cx, cy );
715 /***********************************************************************
716 * GetDIBits (GDI.441)
718 int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
719 LPSTR bits, BITMAPINFO * info, WORD coloruse )
721 DC * dc;
722 BITMAPOBJ * bmp;
723 PALETTEENTRY * palEntry;
724 PALETTEOBJ * palette;
725 XImage * bmpImage, * dibImage;
726 int i, x, y;
728 if (!lines) return 0;
729 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
730 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
731 return 0;
732 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
733 return 0;
735 /* Transfer color info */
737 palEntry = palette->logpalette.palPalEntry;
738 for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
740 if (coloruse == DIB_RGB_COLORS)
742 info->bmiColors[i].rgbRed = palEntry->peRed;
743 info->bmiColors[i].rgbGreen = palEntry->peGreen;
744 info->bmiColors[i].rgbBlue = palEntry->peBlue;
745 info->bmiColors[i].rgbReserved = 0;
747 else ((WORD *)info->bmiColors)[i] = (WORD)i;
750 /* Transfer the pixels (very slow...) */
752 if (bits)
754 bmpImage = (XImage *)CallTo32_LargeStack( (int (*)())XGetImage, 8,
755 display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
756 bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
757 dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
759 for (y = 0; y < lines; y++)
761 for (x = 0; x < info->bmiHeader.biWidth; x++)
763 XPutPixel( dibImage, x, y,
764 XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
769 dibImage->data = NULL;
770 XDestroyImage( dibImage );
771 XDestroyImage( bmpImage );
773 info->bmiHeader.biCompression = 0;
774 return lines;
778 /***********************************************************************
779 * CreateDIBitmap (GDI.442)
781 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
782 LPVOID bits, BITMAPINFO * data, UINT coloruse )
784 HBITMAP handle;
785 BOOL fColor;
786 DWORD width, height;
787 WORD bpp;
789 if (DIB_GetBitmapInfo( header, &width, &height, &bpp ) == -1) return 0;
791 /* Check if we should create a monochrome or color bitmap. */
792 /* We create a monochrome bitmap only if it has exactly 2 */
793 /* colors, which are either black or white, nothing else. */
794 /* In all other cases, we create a color bitmap. */
796 if (bpp != 1) fColor = TRUE;
797 else if ((coloruse != DIB_RGB_COLORS) ||
798 (init != CBM_INIT) || !data) fColor = FALSE;
799 else
801 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
803 RGBQUAD *rgb = data->bmiColors;
804 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
805 if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
807 rgb++;
808 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
809 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
811 else fColor = TRUE;
813 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
815 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
816 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
817 if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
819 rgb++;
820 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
821 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
823 else fColor = TRUE;
825 else
827 fprintf( stderr, "CreateDIBitmap: wrong size (%ld) for data\n",
828 data->bmiHeader.biSize );
829 return 0;
833 /* Now create the bitmap */
835 handle = fColor ? CreateCompatibleBitmap( hdc, width, height ) :
836 CreateBitmap( width, height, 1, 1, NULL );
837 if (!handle) return 0;
839 if (init == CBM_INIT)
840 SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
841 return handle;