2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
10 #include <X11/Xutil.h>
15 #include "stackframe.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 )
34 case 1: words = (width + 31) / 32; break;
35 case 4: words = (width + 7) / 8; break;
36 case 8: words = (width + 3) / 4; break;
38 case 16: words = (width + 1) / 2; break;
39 case 24: words = width; break;
41 fprintf(stderr, "DIB: unsupported depth %d.\n", depth );
48 /***********************************************************************
51 * Return the size of the bitmap info structure.
53 int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
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 /***********************************************************************
78 * Create an XImage pointing to the bitmap data.
80 static XImage *DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
82 extern void _XInitImageFuncPtrs( XImage* );
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));
90 image->byte_order = MSBFirst;
91 image->bitmap_bit_order = MSBFirst;
92 image->bitmap_unit = 16;
93 _XInitImageFuncPtrs(image);
98 /***********************************************************************
101 * Get the info from a bitmap header.
102 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
104 static int DIB_GetBitmapInfo( 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;
114 if (header->biSize == sizeof(BITMAPCOREHEADER))
116 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
117 *width = core->bcWidth;
118 *height = core->bcHeight;
119 *bpp = core->bcBitCount;
122 fprintf( stderr, "DIB_GetBitmapInfo: wrong size (%ld) for header\n",
128 /***********************************************************************
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,
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)
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);
166 for (i = 0; i < colors; i++, rgb++)
167 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbRed,
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);
180 for (i = 0; i < colors; i++, rgb++)
181 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgb->rgbtRed,
186 else /* DIB_PAL_COLORS */
188 for (i = 0; i < colors; i++, colorPtr++)
189 colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*colorPtr) );
195 /***********************************************************************
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 )
206 if (!(width & 31)) pad = 0;
207 else pad = ((32 - (width & 31)) + 7) / 8;
211 for (i = width/8, x = 0; (i > 0); i--)
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] );
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] );
239 /***********************************************************************
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 )
250 if (!(width & 7)) pad = 0;
251 else pad = ((8 - (width & 7)) + 1) / 2;
255 for (i = width/2, x = 0; i > 0; i--)
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] );
266 #define check_xy(x,y) \
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;
285 while ((short)lines >= 0)
288 if (length) { /* encoded */
291 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
295 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
307 case 1: /* eopicture */
315 default: /* absolute */
318 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
322 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
326 if ((bits - begin) & 1)
333 /***********************************************************************
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 )
342 BYTE pad = (4 - (width & 3)) & 3;
346 for (x = 0; x < width; x++)
347 XPutPixel( bmpImage, x, lines, colors[*bits++] );
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
368 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
369 * James A. Youngman <mbcstjy@afs.man.ac.uk>
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,
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. */
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]
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]
424 * [Run-Length] Encoded mode
426 color_index = (*pIn++); /* Get the colour index. */
427 color = colors[color_index];
430 XPutPixel(bmpImage, x++, line, color);
435 * Escape codes (may be an absolute sequence though)
437 escape_code = (*pIn++);
440 case RleEol: /* =0, end of line */
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
456 line=-1; /* Cause exit from do loop. */
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
472 * TODO: Decide what to do here in that case. [JAY]
478 dprintf_bitmap(stddeb,
479 "DIB_SetImageBits_RLE8(): "
480 "Delta to last line of bitmap "
481 "(wrongly?) causes loop exit\n");
486 default: /* >2, switch to absolute mode */
491 length = escape_code;
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]
509 pIn++; /* Throw away the pad byte. */
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.
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",
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 )
543 BYTE pad = (4 - ((width*3) & 3)) & 3;
547 for (x = 0; x < width; x++, bits += 3)
549 XPutPixel( bmpImage, x, lines,
550 COLOR_ToPhysical( dc, RGB(bits[0],bits[1],bits[2]) ));
557 /***********************************************************************
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, DWORD compression,
565 BITMAPINFO *info, WORD coloruse,
566 Drawable drawable, GC gc, int xSrc, int ySrc,
567 int xDest, int yDest, int width, int height )
572 /* Build the color mapping table */
574 if (infoBpp == 24) colorMapping = NULL;
576 if (!(colorMapping = DIB_BuildColorMap( dc, coloruse, depth, info )))
579 if( dc->w.flags & DC_DIRTY ) CLIPPING_UpdateGCRegion(dc);
581 /* Transfer the pixels */
582 XCREATEIMAGE(bmpImage, infoWidth, lines, depth );
587 DIB_SetImageBits_1( lines, bits, infoWidth,
588 colorMapping, bmpImage );
591 if (compression) DIB_SetImageBits_RLE4( lines, bits, infoWidth,
592 colorMapping, bmpImage );
593 else DIB_SetImageBits_4( lines, bits, infoWidth,
594 colorMapping, bmpImage );
597 if (compression) DIB_SetImageBits_RLE8( lines, bits, infoWidth,
598 colorMapping, bmpImage );
599 else DIB_SetImageBits_8( lines, bits, infoWidth,
600 colorMapping, bmpImage );
603 DIB_SetImageBits_24( lines, bits, infoWidth, dc, bmpImage );
606 fprintf( stderr, "Invalid depth %d for SetDIBits!\n", infoBpp );
609 if (colorMapping) free(colorMapping);
610 XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
611 xDest, yDest, width, height );
612 XDestroyImage( bmpImage );
617 /***********************************************************************
618 * StretchDIBits (GDI.439)
620 int StretchDIBits( HDC hdc,
621 WORD xDest, WORD yDest, WORD wDestWidth, WORD wDestHeight,
622 WORD xSrc, WORD ySrc, WORD wSrcWidth, WORD wSrcHeight,
623 LPSTR bits, LPBITMAPINFO info, WORD wUsage, DWORD dwRop )
625 HBITMAP hBitmap, hOldBitmap;
628 hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
629 bits, info, wUsage );
630 hdcMem = CreateCompatibleDC( hdc );
631 hOldBitmap = SelectObject( hdcMem, hBitmap );
632 StretchBlt( hdc, xDest, yDest, wDestWidth, wDestHeight,
633 hdcMem, xSrc, ySrc, wSrcWidth, wSrcHeight, dwRop );
634 SelectObject( hdcMem, hOldBitmap );
636 DeleteObject( hBitmap );
641 /***********************************************************************
642 * SetDIBits (GDI.440)
644 int SetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
645 LPSTR bits, BITMAPINFO * info, WORD coloruse )
649 DWORD width, height, compression = 0;
652 /* Check parameters */
654 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
655 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
657 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
659 if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
660 compression = info->bmiHeader.biCompression;
661 if (!lines || (startscan >= (WORD)height)) return 0;
662 if (startscan + lines > height) lines = height - startscan;
664 return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
665 dc, lines, bmp->bitmap.bmBitsPixel,
666 bits, width, bpp, compression, info,
667 coloruse, bmp->pixmap, BITMAP_GC(bmp), 0, 0, 0,
668 startscan, bmp->bitmap.bmWidth, lines );
672 /***********************************************************************
673 * SetDIBitsToDevice (GDI.443)
675 int SetDIBitsToDevice( HDC hdc, short xDest, short yDest, WORD cx, WORD cy,
676 WORD xSrc, WORD ySrc, WORD startscan, WORD lines,
677 LPSTR bits, BITMAPINFO * info, WORD coloruse )
680 DWORD width, height, compression = 0;
683 /* Check parameters */
685 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
686 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &bpp ) == -1)
688 if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
689 compression = info->bmiHeader.biCompression;
690 if (!lines || (startscan >= height)) return 0;
691 if (startscan + lines > height) lines = height - startscan;
692 if (ySrc < startscan) ySrc = startscan;
693 else if (ySrc >= startscan + lines) return 0;
694 if (xSrc >= width) return 0;
695 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
696 if (xSrc + cx >= width) cx = width - xSrc;
697 if (!cx || !cy) return 0;
699 DC_SetupGCForText( dc ); /* To have the correct colors */
700 XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
701 return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 17,
702 dc, lines, dc->w.bitsPerPixel, bits, width,
703 bpp, compression, info, coloruse,
704 dc->u.x.drawable, dc->u.x.gc,
705 xSrc, ySrc - startscan,
706 dc->w.DCOrgX + XLPTODP( dc, xDest ),
707 dc->w.DCOrgY + YLPTODP( dc, yDest ),
713 /***********************************************************************
714 * GetDIBits (GDI.441)
716 int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
717 LPSTR bits, BITMAPINFO * info, WORD coloruse )
721 PALETTEENTRY * palEntry;
722 PALETTEOBJ * palette;
723 XImage * bmpImage, * dibImage;
726 if (!lines) return 0;
727 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
728 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
730 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
733 /* Transfer color info */
735 palEntry = palette->logpalette.palPalEntry;
736 for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
738 if (coloruse == DIB_RGB_COLORS)
740 info->bmiColors[i].rgbRed = palEntry->peRed;
741 info->bmiColors[i].rgbGreen = palEntry->peGreen;
742 info->bmiColors[i].rgbBlue = palEntry->peBlue;
743 info->bmiColors[i].rgbReserved = 0;
745 else ((WORD *)info->bmiColors)[i] = (WORD)i;
748 /* Transfer the pixels (very slow...) */
752 bmpImage = (XImage *)CallTo32_LargeStack( (int (*)())XGetImage, 8,
753 display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
754 bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
755 dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
757 for (y = 0; y < lines; y++)
759 for (x = 0; x < info->bmiHeader.biWidth; x++)
761 XPutPixel( dibImage, x, y,
762 XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
767 dibImage->data = NULL;
768 XDestroyImage( dibImage );
769 XDestroyImage( bmpImage );
771 info->bmiHeader.biCompression = 0;
776 /***********************************************************************
777 * CreateDIBitmap (GDI.442)
779 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
780 LPVOID bits, BITMAPINFO * data, UINT coloruse )
787 if (DIB_GetBitmapInfo( header, &width, &height, &bpp ) == -1) return 0;
789 /* Check if we should create a monochrome or color bitmap. */
790 /* We create a monochrome bitmap only if it has exactly 2 */
791 /* colors, which are either black or white, nothing else. */
792 /* In all other cases, we create a color bitmap. */
794 if (bpp != 1) fColor = TRUE;
795 else if ((coloruse != DIB_RGB_COLORS) ||
796 (init != CBM_INIT) || !data) fColor = FALSE;
799 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
801 RGBQUAD *rgb = data->bmiColors;
802 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
803 if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
806 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
807 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
811 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
813 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
814 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
815 if ((col == RGB(0,0,0)) || (col == RGB(0xff,0xff,0xff)))
818 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
819 fColor = ((col != RGB(0,0,0)) && (col != RGB(0xff,0xff,0xff)));
825 fprintf( stderr, "CreateDIBitmap: wrong size (%ld) for data\n",
826 data->bmiHeader.biSize );
831 /* Now create the bitmap */
833 handle = fColor ? CreateCompatibleBitmap( hdc, width, height ) :
834 CreateBitmap( width, height, 1, 1, NULL );
835 if (!handle) return 0;
837 if (init == CBM_INIT)
838 SetDIBits( hdc, handle, 0, height, bits, data, coloruse );