2 * GDI device independent bitmaps
4 * Copyright 1993 Alexandre Julliard
6 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
11 #include <X11/Xutil.h>
20 static int get_bpp(int depth)
32 fprintf(stderr, "DIB: unsupported depth %d!\n", depth);
37 /***********************************************************************
40 * Return the size of the bitmap info structure.
42 int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
44 int size = info->bmiHeader.biClrUsed;
45 if (!size && (info->bmiHeader.biBitCount != 24))
46 size = 1 << info->bmiHeader.biBitCount;
47 if (coloruse == DIB_RGB_COLORS)
48 size = info->bmiHeader.biSize + size * sizeof(RGBQUAD);
50 size = info->bmiHeader.biSize + size * sizeof(WORD);
55 /***********************************************************************
58 * Create an XImage pointing to the bitmap data.
60 static XImage *DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
62 extern void _XInitImageFuncPtrs( XImage* );
64 int bytesPerLine = bmp->biWidth * get_bpp(bmp->biBitCount);
66 image = XCreateImage( display, DefaultVisualOfScreen( screen ),
67 bmp->biBitCount, ZPixmap, 0, bmpData,
68 bmp->biWidth, bmp->biHeight, 32, bytesPerLine );
70 image->byte_order = MSBFirst;
71 image->bitmap_bit_order = MSBFirst;
72 image->bitmap_unit = 16;
73 _XInitImageFuncPtrs(image);
78 /***********************************************************************
81 * SetDIBits for a 1-bit deep DIB.
83 static void DIB_SetImageBits_1( WORD lines, BYTE *bits, WORD width,
84 int *colors, XImage *bmpImage )
89 if (!(width & 31)) pad = 0;
90 else pad = ((32 - (width & 31)) + 7) / 8;
94 for (i = width/8, x = 0; (i > 0); i--)
97 XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
98 XPutPixel( bmpImage, x++, lines, colors[(pix >> 6) & 1] );
99 XPutPixel( bmpImage, x++, lines, colors[(pix >> 5) & 1] );
100 XPutPixel( bmpImage, x++, lines, colors[(pix >> 4) & 1] );
101 XPutPixel( bmpImage, x++, lines, colors[(pix >> 3) & 1] );
102 XPutPixel( bmpImage, x++, lines, colors[(pix >> 2) & 1] );
103 XPutPixel( bmpImage, x++, lines, colors[(pix >> 1) & 1] );
104 XPutPixel( bmpImage, x++, lines, colors[pix & 1] );
109 case 7: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
110 case 6: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
111 case 5: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
112 case 4: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
113 case 3: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
114 case 2: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
115 case 1: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
122 /***********************************************************************
125 * SetDIBits for a 4-bit deep DIB.
127 static void DIB_SetImageBits_4( WORD lines, BYTE *bits, WORD width,
128 int *colors, XImage *bmpImage )
133 if (!(width & 7)) pad = 0;
134 else pad = ((8 - (width & 7)) + 1) / 2;
138 for (i = width/2, x = 0; i > 0; i--)
141 XPutPixel( bmpImage, x++, lines, colors[pix >> 4] );
142 XPutPixel( bmpImage, x++, lines, colors[pix & 0x0f] );
144 if (width & 1) XPutPixel( bmpImage, x, lines, colors[*bits >> 4] );
149 #define check_xy(x,y) \
156 /***********************************************************************
157 * DIB_SetImageBits_RLE4
159 * SetDIBits for a 4-bit deep compressed DIB.
161 static void DIB_SetImageBits_RLE4( WORD lines, BYTE *bits, WORD width,
162 int *colors, XImage *bmpImage )
164 int x = 0, c, length;
170 if (length) { /* encoded */
173 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
177 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
189 case 1: /* eopicture */
197 default: /* absolute */
200 XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
204 XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
208 if ((bits - begin) & 1)
215 /***********************************************************************
218 * SetDIBits for an 8-bit deep DIB.
220 static void DIB_SetImageBits_8( WORD lines, BYTE *bits, WORD width,
221 int *colors, XImage *bmpImage )
224 BYTE pad = (4 - (width & 3)) & 3;
228 for (x = 0; x < width; x++)
229 XPutPixel( bmpImage, x, lines, colors[*bits++] );
234 /***********************************************************************
235 * DIB_SetImageBits_RLE8
237 * SetDIBits for an 8-bit deep compressed DIB.
239 * This function rewritten 941113 by James Youngman. WINE blew out when I
240 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
242 * This was because the algorithm assumed that all RLE8 bitmaps end with the
243 * 'End of bitmap' escape code. This code is very much laxer in what it
244 * allows to end the expansion. Possibly too lax. See the note by
245 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
246 * bitmap should end with RleEnd, but on the other hand, software exists
247 * that produces ones that don't and Windows 3.1 doesn't complain a bit
250 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
251 * James A. Youngman <mbcstjy@afs.man.ac.uk>
255 enum Rle8_EscapeCodes
258 * Apologies for polluting your file's namespace...
260 RleEol = 0, /* End of line */
261 RleEnd = 1, /* End of bitmap */
262 RleDelta = 2 /* Delta */
265 static void DIB_SetImageBits_RLE8(WORD lines,
271 int x; /* X-positon on each line. Increases. */
272 int line; /* Line #. Starts at lines-1, decreases */
273 BYTE *pIn = bits; /* Pointer to current position in bits */
274 BYTE length; /* The length pf a run */
275 BYTE color_index; /* index into colors[] as read from bits */
276 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
277 WORD color; /* value of colour[color_index] */
279 if (lines == 0) /* Let's hope this doesn't happen. */
283 * Note that the bitmap data is stored by Windows starting at the
284 * bottom line of the bitmap and going upwards. Within each line,
285 * the data is stored left-to-right. That's the reason why line
286 * goes from lines-1 to 0. [JAY]
296 * If the length byte is not zero (which is the escape value),
297 * We have a run of length pixels all the same colour. The colour
298 * index is stored next.
300 * If the length byte is zero, we need to read the next byte to
301 * know what to do. [JAY]
306 * [Run-Length] Encoded mode
308 color_index = (*pIn++); /* Get the colour index. */
309 color = colors[color_index];
312 XPutPixel(bmpImage, x++, line, color);
317 * Escape codes (may be an absolute sequence though)
319 escape_code = (*pIn++);
322 case RleEol: /* =0, end of line */
329 case RleEnd: /* =1, end of bitmap */
332 * Not all RLE8 bitmaps end with this
333 * code. For example, Paint Shop Pro
334 * produces some that don't. That's (I think)
335 * what caused the previous implementation to
338 line=0; /* Cause exit from do loop. */
341 case RleDelta: /* =2, a delta */
344 * Note that deltaing to line 0
345 * will cause an exit from the loop,
346 * which may not be what is intended.
347 * The fact that there is a delta in the bits
348 * almost certainly implies that there is data
349 * to follow. You may feel that we should
350 * jump to the top of the loop to avoid exiting
353 * TODO: Decide what to do here in that case. [JAY]
359 dprintf_bitmap(stddeb,
360 "DIB_SetImageBits_RLE8(): "
361 "Delta to last line of bitmap "
362 "(wrongly??) causes loop exit\n");
367 default: /* >2, switch to absolute mode */
372 length = escape_code;
375 color_index = (*pIn++);
376 XPutPixel(bmpImage, x++, line,
377 colors[color_index]);
381 * If you think for a moment you'll realise that the
382 * only time we could ever possibly read an odd
383 * number of bytes is when there is a 0x00 (escape),
384 * a value >0x02 (absolute mode) and then an odd-
385 * length run. Therefore this is the only place we
386 * need to worry about it. Everywhere else the
387 * bytes are always read in pairs. [JAY]
390 (*pIn++); /* Get and throw away the pad byte. */
393 } /* switch (escape_code) : Escape sequence */
394 } /* process either an encoded sequence or an escape sequence */
396 /* We expect to come here more than once per line. */
397 } while (line > 0); /* Do this until the bitmap is filled */
400 * Everybody comes here at the end.
401 * Check how we exited the loop and print a message if it's a bit odd.
404 if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
406 dprintf_bitmap(stddeb, "DIB_SetImageBits_RLE8(): End-of-bitmap "
407 "without (strictly) proper escape code. Last two "
408 "bytes were: %02X %02X.\n",
415 /***********************************************************************
416 * DIB_SetImageBits_24
418 * SetDIBits for a 24-bit deep DIB.
420 static void DIB_SetImageBits_24( WORD lines, BYTE *bits, WORD width,
421 DC *dc, XImage *bmpImage )
424 BYTE pad = (4 - ((width*3) & 3)) & 3;
428 for (x = 0; x < width; x++, bits += 3)
430 XPutPixel( bmpImage, x, lines,
431 COLOR_ToPhysical( dc, RGB(bits[0],bits[1],bits[2]) ));
438 /***********************************************************************
441 * Transfer the bits to an X image.
442 * Helper function for SetDIBits() and SetDIBitsToDevice().
444 static int DIB_SetImageBits( DC *dc, WORD lines, WORD depth, LPSTR bits,
445 BITMAPINFO *info, WORD coloruse,
446 Drawable drawable, GC gc, int xSrc, int ySrc,
447 int xDest, int yDest, int width, int height )
452 int i, colors, widthBytes;
454 /* Build the color mapping table */
456 if (info->bmiHeader.biBitCount == 24) colorMapping = NULL;
459 colors = info->bmiHeader.biClrUsed;
460 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
461 if (!(colorMapping = (int *)malloc( colors * sizeof(int) )))
463 if (coloruse == DIB_RGB_COLORS)
465 RGBQUAD * rgbPtr = info->bmiColors;
466 for (i = 0; i < colors; i++, rgbPtr++)
467 colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgbPtr->rgbRed,
473 WORD * index = (WORD *)info->bmiColors;
474 for (i = 0; i < colors; i++, index++)
475 colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*index) );
479 /* Transfer the pixels */
480 widthBytes = info->bmiHeader.biWidth * get_bpp(depth);
482 bmpData = malloc( lines * widthBytes );
483 bmpImage = XCreateImage( display, DefaultVisualOfScreen(screen),
484 depth, ZPixmap, 0, bmpData,
485 info->bmiHeader.biWidth, lines, 32, widthBytes );
487 switch(info->bmiHeader.biBitCount)
490 DIB_SetImageBits_1( lines, bits, info->bmiHeader.biWidth,
491 colorMapping, bmpImage );
494 if (info->bmiHeader.biCompression)
495 DIB_SetImageBits_RLE4( lines, bits, info->bmiHeader.biWidth,
496 colorMapping, bmpImage );
498 DIB_SetImageBits_4( lines, bits, info->bmiHeader.biWidth,
499 colorMapping, bmpImage );
502 if (info->bmiHeader.biCompression)
503 DIB_SetImageBits_RLE8( lines, bits, info->bmiHeader.biWidth,
504 colorMapping, bmpImage );
506 DIB_SetImageBits_8( lines, bits, info->bmiHeader.biWidth,
507 colorMapping, bmpImage );
510 DIB_SetImageBits_24( lines, bits, info->bmiHeader.biWidth,
514 if (colorMapping) free(colorMapping);
516 XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
517 xDest, yDest, width, height );
518 XDestroyImage( bmpImage );
523 /***********************************************************************
524 * SetDIBits (GDI.440)
526 int SetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
527 LPSTR bits, BITMAPINFO * info, WORD coloruse )
532 /* Check parameters */
534 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
535 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
537 if (!lines || (startscan >= (WORD)info->bmiHeader.biHeight)) return 0;
538 if (startscan+lines > info->bmiHeader.biHeight)
539 lines = info->bmiHeader.biHeight - startscan;
541 return DIB_SetImageBits( dc, lines, bmp->bitmap.bmBitsPixel,
542 bits, info, coloruse, bmp->pixmap, BITMAP_GC(bmp),
543 0, 0, 0, startscan, bmp->bitmap.bmWidth, lines );
547 /***********************************************************************
548 * SetDIBitsToDevice (GDI.443)
550 int SetDIBitsToDevice( HDC hdc, short xDest, short yDest, WORD cx, WORD cy,
551 WORD xSrc, WORD ySrc, WORD startscan, WORD lines,
552 LPSTR bits, BITMAPINFO * info, WORD coloruse )
556 /* Check parameters */
558 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
559 if (!lines || (startscan >= info->bmiHeader.biHeight)) return 0;
560 if (startscan+lines > info->bmiHeader.biHeight)
561 lines = info->bmiHeader.biHeight - startscan;
562 if (ySrc < startscan) ySrc = startscan;
563 else if (ySrc >= startscan+lines) return 0;
564 if (xSrc >= info->bmiHeader.biWidth) return 0;
565 if (ySrc+cy >= startscan+lines) cy = startscan + lines - ySrc;
566 if (xSrc+cx >= info->bmiHeader.biWidth) cx = info->bmiHeader.biWidth-xSrc;
567 if (!cx || !cy) return 0;
569 DC_SetupGCForText( dc ); /* To have the correct colors */
570 XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
571 return DIB_SetImageBits( dc, lines, dc->w.bitsPerPixel,
572 bits, info, coloruse,
573 dc->u.x.drawable, dc->u.x.gc,
574 xSrc, ySrc - startscan,
575 dc->w.DCOrgX + XLPTODP( dc, xDest ),
576 dc->w.DCOrgY + YLPTODP( dc, yDest ),
581 /***********************************************************************
582 * GetDIBits (GDI.441)
584 int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
585 LPSTR bits, BITMAPINFO * info, WORD coloruse )
589 PALETTEENTRY * palEntry;
590 PALETTEOBJ * palette;
591 XImage * bmpImage, * dibImage;
594 if (!lines) return 0;
595 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
596 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
598 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
601 /* Transfer color info */
603 palEntry = palette->logpalette.palPalEntry;
604 for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
606 if (coloruse == DIB_RGB_COLORS)
608 info->bmiColors[i].rgbRed = palEntry->peRed;
609 info->bmiColors[i].rgbGreen = palEntry->peGreen;
610 info->bmiColors[i].rgbBlue = palEntry->peBlue;
611 info->bmiColors[i].rgbReserved = 0;
613 else ((WORD *)info->bmiColors)[i] = (WORD)i;
616 /* Transfer the pixels (very slow...) */
620 bmpImage = XGetImage( display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
621 bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
622 dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
624 for (y = 0; y < lines; y++)
626 for (x = 0; x < info->bmiHeader.biWidth; x++)
628 XPutPixel( dibImage, x, y,
629 XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
634 dibImage->data = NULL;
635 XDestroyImage( dibImage );
636 XDestroyImage( bmpImage );
642 /***********************************************************************
643 * CreateDIBitmap (GDI.442)
645 HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
646 LPSTR bits, BITMAPINFO * data, WORD coloruse )
650 handle = CreateCompatibleBitmap( hdc, header->biWidth, header->biHeight );
651 if (!handle) return 0;
652 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, header->biHeight,
653 bits, data, coloruse );
657 /***********************************************************************
660 BOOL DrawIcon(HDC hDC, short x, short y, HICON hIcon)
667 dprintf_icon(stddeb,"DrawIcon(%04X, %d, %d, %04X) \n", hDC, x, y, hIcon);
668 if (hIcon == (HICON)NULL) return FALSE;
669 lpico = (ICONALLOC *)GlobalLock(hIcon);
670 GetObject(lpico->hBitmap, sizeof(BITMAP), (LPSTR)&bm);
671 dprintf_icon(stddeb,"DrawIcon / x=%d y=%d\n", x, y);
672 dprintf_icon(stddeb,"DrawIcon / icon Width=%d\n",
673 (int)lpico->descriptor.Width);
674 dprintf_icon(stddeb,"DrawIcon / icon Height=%d\n",
675 (int)lpico->descriptor.Height);
676 dprintf_icon(stddeb,"DrawIcon / icon ColorCount=%d\n",
677 (int)lpico->descriptor.ColorCount);
678 dprintf_icon(stddeb,"DrawIcon / icon icoDIBSize=%lX\n",
679 (DWORD)lpico->descriptor.icoDIBSize);
680 dprintf_icon(stddeb,"DrawIcon / icon icoDIBOffset=%lX\n",
681 (DWORD)lpico->descriptor.icoDIBOffset);
682 dprintf_icon(stddeb,"DrawIcon / bitmap bmWidth=%d bmHeight=%d\n",
683 bm.bmWidth, bm.bmHeight);
684 hMemDC = CreateCompatibleDC(hDC);
686 hBitTemp = SelectObject(hMemDC, lpico->hBitmap);
687 BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
688 SelectObject(hMemDC, lpico->hBitMask);
689 BitBlt(hDC, x, y + bm.bmHeight, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
691 hBitTemp = SelectObject(hMemDC, lpico->hBitMask);
692 BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCAND);
693 SelectObject(hMemDC, lpico->hBitmap);
694 BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCPAINT);
696 SelectObject( hMemDC, hBitTemp );