/* @(#)idilocal4.c 17.1.1.1 (ESO-DMD) 01/25/02 17:34:25 */ /*=========================================================================== Copyright (C) 2000 Craig B. Markwardt This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. Correspondence concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*********************************************************************** * * file idilocal4.c * * IDI Device Dependent Routines * (version for XWindows release 11) * * * V 1.00 001129: C. Markwardt - conversions for 24- and 16-bit visuals * * get_plane_offset : convert bitmask to a shift offset * idi_conv32_24 : convert 32-bit RGB to 24-bit RGB * idi_conv24_32 : convert 24-bit RGB to 32-bit RGB * idi_conv32_16 : convert 32-bit RGB to 16-bit RGB * idi_conv16_32 : convert 16-bit RGB to 32-bit RGB * idi_putimage : wrapper for XPutImage * idi_getsubimage : wrapper for XGetSubImage 010514 last modif KB ************************************************************************/ /* */ #include #include #include #include #include /* Determine the shift to apply to 8-bit data to align with "mask" */ int get_plane_offset(mask, wordsize) unsigned int mask, wordsize; { int i; for (i=31; i>=0; i--) if ( (mask>>i) & 1 ) return (i+1-wordsize); return 0; } /* Convert 32-bit input to 24-bit output. The image data sizes are the same, hence each line output line will be padded by 25%. Note that this function allocates memory which must be freed by the caller. */ unsigned char *idi_conv32_24(image, src) XImage *image; unsigned char *src; { unsigned char *dst, *p, *q; unsigned int nbytes; unsigned int test = 0x000000ff; unsigned char *ptest = (unsigned char *)&test; int lend; int j, i; if ( *ptest == 0xff ) lend = 1; else lend = 0; /* Allocate a destination image */ nbytes = image->bytes_per_line*image->height; dst = malloc(nbytes); if (dst == 0) return 0; /* Zero the new image data */ q = dst; for (i=0; iheight; j++) { p = src + image->bytes_per_line*j; q = dst + image->bytes_per_line*j; /* Note that for 24-bit data, all we have to do is copy the 3 lsb's and discard the msb, while otherwise preserving the byte order. */ if (lend) { /* Little-endian - discard msb at end of each source word */ for (i=0; iwidth; i++) { *q++ = *p++; *q++ = *p++; *q++ = *p++; p++; } } else { /* Big-endian - discard msb at beginning of each source word */ for (i=0; iwidth; i++) { p++; *q++ = *p++; *q++ = *p++; *q++ = *p++; } } } return dst; } /* Convert 24-bit input to 32-bit output. The image data sizes are the same, hence each input line must be padded by 25%. Note that this function allocates memory which must be freed by the caller. */ unsigned char *idi_conv24_32(image, src) XImage *image; unsigned char *src; { unsigned char *dst, *p, *q; unsigned int nbytes; unsigned int test = 0x000000ff; unsigned char *ptest = (unsigned char *)&test; int lend; int j, i; /* Test for endian-ness */ if ( *ptest == 0xff ) lend = 1; else lend = 0; #if 0 fprintf(stderr, "%s-endian\n", lend?"little":"big"); fprintf(stderr, "red_mask = 0x%08x\n", image->red_mask); fprintf(stderr, "green_mask = 0x%08x\n", image->green_mask); fprintf(stderr, "blue_mask = 0x%08x\n", image->blue_mask); #endif /* Allocate a destination image */ nbytes = image->bytes_per_line*image->height; dst = malloc(nbytes); if (dst == 0) return 0; /* Zero the new image data */ q = dst; for (i=0; iheight; j++) { p = src + image->bytes_per_line*j; q = dst + image->bytes_per_line*j; /* Note that for 24-bit data, all we have to do is copy the 3 lsb's and discard the msb, while otherwise preserving the byte order. */ if (lend > 0) { /* Little-endian - insert msb at end of each dest word */ for (i=0; iwidth; i++) { *q++ = *p++; *q++ = *p++; *q++ = *p++; q++; } } else { /* Big-endian - insert msb at beginning of each dest word */ for (i=0; iwidth; i++) { q++; *q++ = *p++; *q++ = *p++; *q++ = *p++; } } } return dst; } /* Convert 32-bit input to 16-bit output. The image data sizes are the same, hence each line output line will be padded by 50%. Note that this function allocates memory which must be freed by the caller. Also, the conversion from 24-bit to 16-bit is inherently lossy. */ unsigned char *idi_conv32_16(image, src, wordsize) XImage *image; unsigned char *src; unsigned int wordsize; { unsigned char *dst, *p, *q; unsigned short int *qi; unsigned int *pi; unsigned int nbytes; unsigned char r, g, b; unsigned int rm, gm, bm; /* Red green and blue masks */ unsigned int ro, go, bo; /* Red green and blue mask offsets */ unsigned int word; int j, i; rm = image->red_mask; gm = image->green_mask; bm = image->blue_mask; ro = get_plane_offset(rm, wordsize); go = get_plane_offset(gm, wordsize); bo = get_plane_offset(bm, wordsize); if (ro < 0 || go < 0 || bo < 0) return 0; #if 0 fprintf(stderr, "red_offset=%d red_mask=0x%08x\n", ro, rm); fprintf(stderr, "green_offset=%d green_mask=0x%08x\n", go, gm); fprintf(stderr, "blue_offset=%d blue_mask=0x%08x\n", bo, bm); #endif /* Allocate a destination image */ nbytes = image->bytes_per_line*image->height; dst = malloc(nbytes); if (dst == 0) return 0; for (i=0, q=dst; iheight; j++) { p = src + image->bytes_per_line*j; q = dst + image->bytes_per_line*j; pi = (unsigned int *) p; qi = (unsigned short int *) q; /* Note that for 16-bit output data the red element in the 24-bit input data will always be in the LSB, given the way that RGBord is constructed */ if (ro > 0) { /* bo must be negative */ for (i=0; iwidth; i++) { word = *pi++; r = word & 0xff; g = (word >> 8) & 0xff; b = (word >> 16) & 0xff; *qi++ = ((r << ro) & rm) | ((g << go) & gm) | ((b >> -bo) & bm); } } else { /* ro must be negative */ for (i=0; iwidth; i++) { word = *pi++; r = word & 0xff; g = (word >> 8) & 0xff; b = (word >> 16) & 0xff; *qi++ = ((r >> -ro) & rm) | ((g << go) & gm) | ((b << bo) & bm); } } } return dst; } /* Convert 16-bit input to 32-bit output. The image data sizes are the same, hence each input line must be padded by 50%. Note that this function allocates memory which must be freed by the caller. Also, the conversion from 16-bit to 24-bit assumes that the low-order bits are zero. */ unsigned char *idi_conv16_32(image, src, wordsize) XImage *image; unsigned char *src; unsigned int wordsize; { unsigned char *dst, *p, *q; unsigned short int *pi; unsigned int *qi; unsigned int nbytes; unsigned char r, g, b; unsigned int rm, gm, bm; /* Red green and blue masks */ unsigned int ro, go, bo; /* Red green and blue mask offsets */ unsigned short int word; int j, i; rm = image->red_mask; gm = image->green_mask; bm = image->blue_mask; ro = get_plane_offset(rm, wordsize); go = get_plane_offset(gm, wordsize); bo = get_plane_offset(bm, wordsize); if (ro < 0 || go < 0 || bo < 0) return 0; /* Allocate a destination image */ nbytes = image->bytes_per_line*image->height; dst = malloc(nbytes); if (dst == 0) return 0; for (i=0, q=dst; iheight; j++) { p = src + image->bytes_per_line*j; q = dst + image->bytes_per_line*j; pi = (unsigned short int *) p; qi = (unsigned int *) q; /* Note that for 16-bit input data the red element in the 24-bit output data will always be in the LSB, given the way that RGBord is constructed */ if (ro > 0) { /* bo must be negative */ for (i=0; iwidth; i++) { word = *pi++; r = (word & rm) >> ro; g = (word & gm) >> go; b = (word & bm) << -bo; *qi++ = r | (g << 8) | (b << 16); } } else { /* ro must be negative */ for (i=0; iwidth; i++) { word = *pi++; r = (word & rm) << -ro; g = (word & gm) >> go; b = (word & bm) >> bo; *qi++ = r | (g << 8) | (b << 16); } } } return dst; } /* Wrapper for XPutImage. The arguments are identical. This function takes an XImage either in 32-bit truecolor or 8-bit pseudocolor and converts to the appropriate bitsize and depth of the output drawable. No error checking is done on the arguments. */ void idi_putimage(display, draw, gc, image, sx, sy, dx, dy, width, height) Display *display; Drawable draw; GC gc; XImage *image; int sx, sy, dx, dy; unsigned int width, height; { unsigned char *dst = 0; unsigned char *src = (unsigned char *)image->data; int wordsize = 8; /* Convert from a standard size, either 8-bit or 32-bit, to the native pixel size */ switch (image->bits_per_pixel) { /* 32-bit true-color, and 8-bit pseudo color are output immediately */ case 8: case 32: break; case 16: dst = idi_conv32_16(image, src, wordsize); /* 32 bits to 16 bits */ break; case 24: dst = idi_conv32_24(image, src); /* 32 bits to 24 bits */ break; } /* Temporarily insert the transformed data into the XImage, Put the image, and then restore the original data */ if (dst) image->data = (char *) dst; XPutImage(display, draw, gc, image, sx, sy, dx, dy, width, height); image->data = (char *) src; if (dst) free(dst); return; } /* Wrapper for XGetSubImage. The arguments are identical. This function reads an XImage from the drawable, in the native bitsize and depth of the drawable, and then converts to either an 8-bit pseudocolor or 32-bit RGB image. No error checking is done on the arguments. */ XImage * idi_getsubimage(display, draw, x, y, width, height, plane_mask, format, dimage, dx, dy) Display *display; Drawable draw; int x, y; unsigned int width, height; unsigned long plane_mask; int format; XImage *dimage; int dx, dy; { XImage *image; unsigned char *dst, *p, *q; unsigned int nbytes, i; int wordsize = 8; /* Do the actual XGetSubImage, which will return in the native depth and bit_per_pixel of the drawable */ image = XGetSubImage(display, draw, x, y, width, height, plane_mask, format, dimage, dx, dy); /* Convert to a standard size, either 8-bit or 32-bit */ switch (image->bits_per_pixel) { /* 32-bit true-color, and 8-bit pseudo color are done immediately */ case 8: case 32: return image; break; case 16: /* 16 bits to 32 bits */ dst = idi_conv16_32(image, (unsigned char *) image->data, wordsize); break; case 24: /* 24 bits to 32 bits */ dst = idi_conv24_32(image, (unsigned char *) image->data); break; } if (dst == 0) return image; /* Now copy the "destination" image back into the original "source" */ nbytes = image->bytes_per_line * image->height; p = dst; q = (unsigned char *) image->data; for (i=0; i