4 * This file contains routines for manipulation full-color images.
6 * Copyright (c) 1995 Sun Microsystems, Inc.
8 * See the file "license.terms" for information on usage and redistribution
9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 static int DestroyImage(XImage* data);
15 static unsigned long ImageGetPixel(XImage *image, int x, int y);
16 static int PutPixel(XImage *image, int x, int y,
20 *----------------------------------------------------------------------
24 * This is a trivial wrapper around ckfree to make it possible to pass
25 * ckfree as a pointer.
31 * Deallocates the image.
33 *----------------------------------------------------------------------
38 XImage *imagePtr) /* Image to free. */
42 ckfree(imagePtr->data);
50 *----------------------------------------------------------------------
54 * Get a single pixel from an image.
57 * Returns the 32 bit pixel value.
62 *----------------------------------------------------------------------
70 unsigned long pixel = 0;
71 unsigned char *srcPtr = (unsigned char *) &(image->data[(y * image->bytes_per_line)
72 + ((x * image->bits_per_pixel) / NBBY)]);
74 switch (image->bits_per_pixel) {
77 pixel = RGB(srcPtr[2], srcPtr[1], srcPtr[0]);
80 pixel = RGB(((((WORD*)srcPtr)[0]) >> 7) & 0xf8,
81 ((((WORD*)srcPtr)[0]) >> 2) & 0xf8,
82 ((((WORD*)srcPtr)[0]) << 3) & 0xf8);
88 pixel = ((x%2) ? (*srcPtr) : ((*srcPtr) >> 4)) & 0x0f;
91 pixel = ((*srcPtr) & (0x80 >> (x%8))) ? 1 : 0;
98 *----------------------------------------------------------------------
102 * Set a single pixel in an image.
110 *----------------------------------------------------------------------
119 unsigned char *destPtr = (unsigned char *) &(image->data[(y * image->bytes_per_line)
120 + ((x * image->bits_per_pixel) / NBBY)]);
122 switch (image->bits_per_pixel) {
125 * Pixel is DWORD: 0x00BBGGRR
132 * Pixel is triplet: 0xBBGGRR.
135 destPtr[0] = (unsigned char) GetBValue(pixel);
136 destPtr[1] = (unsigned char) GetGValue(pixel);
137 destPtr[2] = (unsigned char) GetRValue(pixel);
141 * Pixel is WORD: 5-5-5 (R-G-B)
144 (*(WORD*)destPtr) = ((GetRValue(pixel) & 0xf8) << 7)
145 | ((GetGValue(pixel) & 0xf8) <<2)
146 | ((GetBValue(pixel) & 0xf8) >> 3);
150 * Pixel is 8-bit index into color table.
153 (*destPtr) = (unsigned char) pixel;
157 * Pixel is 4-bit index in MSBFirst order.
161 (*destPtr) = (unsigned char) (((*destPtr) & 0xf0)
164 (*destPtr) = (unsigned char) (((*destPtr) & 0x0f)
165 | ((pixel << 4) & 0xf0));
170 * Pixel is bit in MSBFirst order.
173 int mask = (0x80 >> (x%8));
187 *----------------------------------------------------------------------
191 * Allocates storage for a new XImage.
194 * Returns a newly allocated XImage.
199 *----------------------------------------------------------------------
215 XImage* imagePtr = ckalloc(sizeof(XImage));
216 imagePtr->width = width;
217 imagePtr->height = height;
218 imagePtr->xoffset = offset;
219 imagePtr->format = format;
220 imagePtr->data = data;
221 imagePtr->byte_order = LSBFirst;
222 imagePtr->bitmap_unit = 8;
223 imagePtr->bitmap_bit_order = LSBFirst;
224 imagePtr->bitmap_pad = bitmap_pad;
225 imagePtr->bits_per_pixel = depth;
226 imagePtr->depth = depth;
229 * Under Windows, bitmap_pad must be on an LONG data-type boundary.
232 #define LONGBITS (sizeof(LONG) * 8)
234 bitmap_pad = (bitmap_pad + LONGBITS - 1) / LONGBITS * LONGBITS;
237 * Round to the nearest bitmap_pad boundary.
240 if (bytes_per_line) {
241 imagePtr->bytes_per_line = bytes_per_line;
243 imagePtr->bytes_per_line = (((depth * width)
244 + (bitmap_pad - 1)) >> 3) & ~((bitmap_pad >> 3) - 1);
247 imagePtr->red_mask = 0;
248 imagePtr->green_mask = 0;
249 imagePtr->blue_mask = 0;
251 imagePtr->f.put_pixel = PutPixel;
252 imagePtr->f.get_pixel = ImageGetPixel;
253 imagePtr->f.destroy_image = DestroyImage;
254 imagePtr->f.create_image = NULL;
255 imagePtr->f.sub_image = NULL;
256 imagePtr->f.add_pixel = NULL;
262 *----------------------------------------------------------------------
264 * XGetImageZPixmap --
266 * This function copies data from a pixmap or window into an XImage. This
267 * handles the ZPixmap case only.
270 * Returns a newly allocated image containing the data from the given
271 * rectangle of the given drawable.
276 * This procedure is adapted from the XGetImage implementation in TkNT. That
277 * code is Copyright (c) 1994 Software Research Associates, Inc.
279 *----------------------------------------------------------------------
287 unsigned int width, unsigned int height,
288 unsigned long plane_mask,
291 TkWinDrawable *twdPtr = (TkWinDrawable *)d;
294 HBITMAP hbmp, hbmpPrev;
295 BITMAPINFO *bmInfo = NULL;
296 HPALETTE hPal, hPalPrev1 = 0, hPalPrev2 = 0;
304 if (format != ZPixmap) {
305 TkpDisplayWarning("Only ZPixmap types are implemented",
306 "XGetImageZPixmap Failure");
310 hdc = TkWinGetDrawableDC(display, d, &state);
313 * Need to do a Blt operation to copy into a new bitmap.
316 hbmp = CreateCompatibleBitmap(hdc, (int) width, (int) height);
317 hdcMem = CreateCompatibleDC(hdc);
318 hbmpPrev = SelectObject(hdcMem, hbmp);
319 hPal = state.palette;
321 hPalPrev1 = SelectPalette(hdcMem, hPal, FALSE);
322 n = RealizePalette(hdcMem);
324 UpdateColors(hdcMem);
326 hPalPrev2 = SelectPalette(hdc, hPal, FALSE);
327 n = RealizePalette(hdc);
333 ret = BitBlt(hdcMem, 0, 0, (int) width, (int) height, hdc, x, y, SRCCOPY);
335 SelectPalette(hdc, hPalPrev2, FALSE);
337 SelectObject(hdcMem, hbmpPrev);
338 TkWinReleaseDrawableDC(d, hdc, &state);
343 if (twdPtr->type == TWD_WINDOW) {
344 depth = Tk_Depth((Tk_Window) twdPtr->window.winPtr);
346 depth = twdPtr->bitmap.depth;
349 size = sizeof(BITMAPINFO);
351 size += sizeof(unsigned short) << depth;
353 bmInfo = ckalloc(size);
355 bmInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
356 bmInfo->bmiHeader.biWidth = width;
357 bmInfo->bmiHeader.biHeight = -(int) height;
358 bmInfo->bmiHeader.biPlanes = 1;
359 bmInfo->bmiHeader.biBitCount = depth;
360 bmInfo->bmiHeader.biCompression = BI_RGB;
361 bmInfo->bmiHeader.biSizeImage = 0;
362 bmInfo->bmiHeader.biXPelsPerMeter = 0;
363 bmInfo->bmiHeader.biYPelsPerMeter = 0;
364 bmInfo->bmiHeader.biClrUsed = 0;
365 bmInfo->bmiHeader.biClrImportant = 0;
368 unsigned char *p, *pend;
370 GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);
371 data = ckalloc(bmInfo->bmiHeader.biSizeImage);
373 /* printf("Failed to allocate data area for XImage.\n"); */
377 ret_image = XCreateImage(display, NULL, depth, ZPixmap, 0, (char *) data,
378 width, height, 32, (int) ((width + 31) >> 3) & ~1);
379 if (ret_image == NULL) {
385 * Get the BITMAP info into the Image.
388 if (GetDIBits(hdcMem, hbmp, 0, height, data, bmInfo,
389 DIB_PAL_COLORS) == 0) {
390 ckfree(ret_image->data);
396 pend = data + bmInfo->bmiHeader.biSizeImage;
401 } else if (depth == 8) {
402 unsigned short *palette;
406 GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);
407 data = ckalloc(bmInfo->bmiHeader.biSizeImage);
409 /* printf("Failed to allocate data area for XImage.\n"); */
413 ret_image = XCreateImage(display, NULL, 8, ZPixmap, 0, (char *) data,
414 width, height, 8, (int) width);
415 if (ret_image == NULL) {
421 * Get the BITMAP info into the Image.
424 if (GetDIBits(hdcMem, hbmp, 0, height, data, bmInfo,
425 DIB_PAL_COLORS) == 0) {
426 ckfree(ret_image->data);
432 palette = (unsigned short *) bmInfo->bmiColors;
433 for (i = 0; i < bmInfo->bmiHeader.biSizeImage; i++, p++) {
434 *p = (unsigned char) palette[*p];
436 } else if (depth == 16) {
437 GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_RGB_COLORS);
438 data = ckalloc(bmInfo->bmiHeader.biSizeImage);
440 /* printf("Failed to allocate data area for XImage.\n"); */
444 ret_image = XCreateImage(display, NULL, 16, ZPixmap, 0, (char *) data,
445 width, height, 16, 0 /* will be calc'ed from bitmap_pad */);
446 if (ret_image == NULL) {
452 * Get the BITMAP info directly into the Image.
455 if (GetDIBits(hdcMem, hbmp, 0, height, ret_image->data, bmInfo,
456 DIB_RGB_COLORS) == 0) {
457 ckfree(ret_image->data);
463 GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_RGB_COLORS);
464 data = ckalloc(width * height * 4);
466 /* printf("Failed to allocate data area for XImage.\n"); */
470 ret_image = XCreateImage(display, NULL, 32, ZPixmap, 0, (char *) data,
471 width, height, 0, (int) width * 4);
472 if (ret_image == NULL) {
479 * This used to handle 16 and 24 bpp, but now just handles 24. It
480 * can likely be optimized for that. -- hobbs
483 unsigned char *smallBitData, *smallBitBase, *bigBitData;
484 unsigned int byte_width, h, w;
486 byte_width = ((width * 3 + 3) & ~(unsigned)3);
487 smallBitBase = ckalloc(byte_width * height);
489 ckfree(ret_image->data);
494 smallBitData = smallBitBase;
497 * Get the BITMAP info into the Image.
500 if (GetDIBits(hdcMem, hbmp, 0, height, smallBitData, bmInfo,
501 DIB_RGB_COLORS) == 0) {
502 ckfree(ret_image->data);
504 ckfree(smallBitBase);
510 * Copy the 24 Bit Pixmap to a 32-Bit one.
513 for (h = 0; h < height; h++) {
514 bigBitData = (unsigned char *) ret_image->data + h * ret_image->bytes_per_line;
515 smallBitData = smallBitBase + h * byte_width;
517 for (w = 0; w < width; w++) {
518 *bigBitData++ = ((*smallBitData++));
519 *bigBitData++ = ((*smallBitData++));
520 *bigBitData++ = ((*smallBitData++));
526 * Free the Device contexts, and the Bitmap.
529 ckfree(smallBitBase);
532 * Get the BITMAP info directly into the Image.
535 if (GetDIBits(hdcMem, hbmp, 0, height, ret_image->data, bmInfo,
536 DIB_RGB_COLORS) == 0) {
537 ckfree(ret_image->data);
550 SelectPalette(hdcMem, hPalPrev1, FALSE);
559 *----------------------------------------------------------------------
563 * This function copies data from a pixmap or window into an XImage.
566 * Returns a newly allocated image containing the data from the given
567 * rectangle of the given drawable.
572 *----------------------------------------------------------------------
580 unsigned int width, unsigned int height,
581 unsigned long plane_mask,
584 TkWinDrawable *twdPtr = (TkWinDrawable *)d;
590 if (twdPtr == NULL) {
592 * Avoid unmapped windows or bad drawables
598 if (twdPtr->type != TWD_BITMAP) {
600 * This handles TWD_WINDOW or TWD_WINDC, always creating a 32bit
601 * image. If the window being copied isn't visible (unmapped or
602 * obscured), we quietly stop copying (no user error). The user will
603 * see black where the widget should be. This branch is likely
604 * followed in favor of XGetImageZPixmap as postscript printed widgets
609 unsigned int xx, yy, size;
612 dc = TkWinGetDrawableDC(display, d, &state);
614 imagePtr = XCreateImage(display, NULL, 32, format, 0, NULL,
615 width, height, 32, 0);
616 size = imagePtr->bytes_per_line * imagePtr->height;
617 imagePtr->data = ckalloc(size);
618 ZeroMemory(imagePtr->data, size);
620 for (yy = 0; yy < height; yy++) {
621 for (xx = 0; xx < width; xx++) {
622 pixel = GetPixel(dc, x+(int)xx, y+(int)yy);
623 if (pixel == CLR_INVALID) {
626 PutPixel(imagePtr, (int) xx, (int) yy, pixel);
630 TkWinReleaseDrawableDC(d, dc, &state);
631 } else if (format == ZPixmap) {
633 * This actually handles most TWD_WINDOW requests, but it varies from
634 * the above in that it really does a screen capture of an area, which
635 * is consistent with the Unix behavior, but does not appear to handle
636 * all bit depths correctly. -- hobbs
639 imagePtr = XGetImageZPixmap(display, d, x, y,
640 width, height, plane_mask, format);
642 const char *errMsg = NULL;
643 char infoBuf[sizeof(BITMAPINFO) + sizeof(RGBQUAD)];
644 BITMAPINFO *infoPtr = (BITMAPINFO*)infoBuf;
646 if (twdPtr->bitmap.handle == NULL) {
647 errMsg = "XGetImage: not implemented for empty bitmap handles";
648 } else if (format != XYPixmap) {
649 errMsg = "XGetImage: not implemented for format != XYPixmap";
650 } else if (plane_mask != 1) {
651 errMsg = "XGetImage: not implemented for plane_mask != 1";
653 if (errMsg != NULL) {
655 * Do a soft warning for the unsupported XGetImage types.
658 TkpDisplayWarning(errMsg, "XGetImage Failure");
662 imagePtr = XCreateImage(display, NULL, 1, XYBitmap, 0, NULL,
663 width, height, 32, 0);
664 imagePtr->data = ckalloc(imagePtr->bytes_per_line * imagePtr->height);
668 GetDIBits(dc, twdPtr->bitmap.handle, 0, height, NULL,
669 infoPtr, DIB_RGB_COLORS);
671 infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
672 infoPtr->bmiHeader.biWidth = width;
673 infoPtr->bmiHeader.biHeight = -(LONG)height;
674 infoPtr->bmiHeader.biPlanes = 1;
675 infoPtr->bmiHeader.biBitCount = 1;
676 infoPtr->bmiHeader.biCompression = BI_RGB;
677 infoPtr->bmiHeader.biSizeImage = 0;
678 infoPtr->bmiHeader.biXPelsPerMeter = 0;
679 infoPtr->bmiHeader.biYPelsPerMeter = 0;
680 infoPtr->bmiHeader.biClrUsed = 0;
681 infoPtr->bmiHeader.biClrImportant = 0;
683 GetDIBits(dc, twdPtr->bitmap.handle, 0, height, imagePtr->data,
684 infoPtr, DIB_RGB_COLORS);