/* * file x11c_image.c - convert images to window system * * $Id: x11c_image.c,v 1.3 2004/05/14 10:00:36 alfie Exp $ * * Program XBLAST * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net) * * 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; or (at your option) * any later version * * This program is distributed in the hope that it will be entertaining, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILTY 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. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "x11c_image.h" #include "gui.h" #include "util.h" #include "color.h" /* * local variables */ static int rgb_color[6][6][6]; static unsigned long rmask, gmask, bmask; static int rbits, rshift; static int gbits, gshift; static int bbits, bshift; static int rbase, gbase, bbase; /* pointer to conversion functions (rgb to pixel) */ static void (*ppm_to_image) (unsigned char *ppm, int width, int height, XImage *image); /* * */ static void AnalyzeColorMask (unsigned long mask, int *bits, int *shift) { *shift = 0; *bits = 0; if (mask) { while (0 == (mask % 2) ) { (*shift) ++; mask >>= 1; } while (1== (mask % 2) ){ (*bits) ++; mask >>= 1; } } } /* AnalyzeColorMask */ /* * */ static void PpmToImageRgb (unsigned char *ppm, int width, int height, XImage *image) { int x, y, i; int pixel; int base[3], scale[3], shift[3], mask[3]; base[0] = rbase; base[1] = gbase; base[2] = bbase; scale[0] = 65535 - base[0]; scale[1] = 65535 - base[1]; scale[2] = 65535 - base[2]; shift[0] = 16 - rshift - rbits ; shift[1] = 16 - gshift - gbits ; shift[2] = 16 - bshift - bbits ; mask[0] = rmask; mask[1] = gmask; mask[2] = bmask; for (y=0; y 0) { pixel |= ( ( (scale[i]*(*ppm))/255 + base[i]) >> shift[i] ) & mask[i]; } else { pixel |= ( ( (scale[i]*(*ppm))/255 + base[i]) << -shift[i] ) & mask[i]; } ppm++; } XPutPixel(image, x, y, pixel); } } } /* PpmToImageRgb */ /* * */ static void AllocRgbColor (int red, int green, int blue) { XColor colorUsed; #ifdef DEBUG static int num_rgb_colors = 0; fprintf(stderr, "Allocating RGB color %d\n", ++ num_rgb_colors); #endif /* default pixel is white */ rgb_color[red][green][blue] = whitePixel; /* try to alloc a new color cell */ colorUsed.red = (65535 - rbase) * red /5 + rbase; colorUsed.green = (65535 - gbase) * green /5 + gbase; colorUsed.blue = (65535 - bbase) * blue /5 + bbase; colorUsed.flags = DoRed | DoGreen | DoBlue; if (XAllocColor(dpy, cmap, &colorUsed) ) { rgb_color[red][green][blue] = colorUsed.pixel; } else { /* if private colormap is in not in use,try agaian white */ if (cmap == DefaultColormap(dpy, DefaultScreen(dpy) ) ) { /* create private color map */ cmap = XCopyColormapAndFree(dpy, cmap); XSetWindowColormap(dpy, win, cmap); /* alloc again */ colorUsed.red = 65535 * red /5; colorUsed.green = 65535 * green /5; colorUsed.blue = 65535 * blue /5; colorUsed.flags = DoRed | DoGreen | DoBlue; if (XAllocColor(dpy, cmap, &colorUsed) ) { rgb_color[red][green][blue] = colorUsed.pixel; } } } } /* AllocRgbColor */ /* * */ static void PpmToImage8Bit (unsigned char *ppm, int width, int height, XImage *image) { int x, y; unsigned char *ptr; int red, green, blue; /* upper left pixels */ ptr = ppm; for (y=0; y 8) { /* get visual for true color display */ vinfo.class = visual_class; result = XGetVisualInfo (dpy, VisualClassMask, &vinfo, &nitems); for (i = 0; i < nitems; i ++) { if (result[i].depth == defDepth) { break; } } if (i == nitems) { fprintf (stderr, "cannot find VisalInfo for current bpp. Expect color problems"); i = 0; } /* get pixel format */ rmask = result[i].red_mask; gmask = result[i].green_mask; bmask = result[i].blue_mask; AnalyzeColorMask (rmask, &rbits, &rshift); AnalyzeColorMask (gmask, &gbits, &gshift); AnalyzeColorMask (bmask, &bbits, &bshift); #ifdef DEBUG fprintf (stderr, "Red: mask=%08lx, bits=%d, shift=%d\n", rmask, rbits, rshift); fprintf (stderr, "Green: mask=%08lx, bits=%d, shift=%d\n", gmask, gbits, gshift); fprintf (stderr, "Blue: mask=%08lx, bits=%d, shift=%d\n", bmask, bbits, bshift); #endif ppm_to_image = PpmToImageRgb; } else { /* 8 bit display with color map */ int r,g,b; for (r=0; r<6; r++) { for (g=0; g<6; g++) { for (b=0; b<6; b++) { rgb_color[r][g][b] = -1; } } } ppm_to_image = PpmToImage8Bit; } /* set up offset for r,g,b values */ rbase = gbase = bbase = 0x1000; /* that's all */ return XBTrue; } /* InitImage */ /* * */ Pixmap ReadCchPixmap (const char *path, const char *filename, XBColor fg, XBColor bg, XBColor add) { XImage *image; Pixmap tmp; int width, height; unsigned char *ppm; char *data; /* load ppm file */ if (NULL == (ppm = ReadPpmFile (path, filename, &width, &height) ) ) { fprintf (stderr, "failed to load pixmap %s\n", filename); return None; } /* alloc ppm and image data */ if (NULL == (data = malloc( ( (bitsPerPixel + 7) / 8) * width * height ) ) ) { fprintf (stderr, "failed to alloc image data\n"); return None; } /* create image */ image = XCreateImage (dpy, defVisual, defDepth, ZPixmap, 0, data, width, height, 32, 0 ); if (image == NULL) { fprintf (stderr, "create image failed\n"); return None; } /* recolor ppm image */ CchToPpm (ppm, width, height, fg, bg, add); /* convert ppm to image */ (*ppm_to_image)(ppm, width, height, image); /* free ppm data */ free(ppm); /* create pixmap */ tmp = XCreatePixmap (dpy, win, width, height, defDepth); /* put image */ XPutImage (dpy, tmp, gcWindow, image, 0, 0, 0, 0, width, height); /* delete image */ #ifdef DEBUG_ALLOC Dbg_Vfree (__FILE__, __LINE__, data); #endif XDestroyImage (image); /* thats 'all */ return tmp; } /* ReadCchPixmap */ /* * */ Pixmap ReadEpmPixmap (const char *path, const char *filename, int n_colors, const XBColor *color) { XImage *image; Pixmap tmp; int width, height; unsigned char *epm, *ppm; char *data; int depth; /* load ppm file */ if (NULL == (epm = ReadEpmFile (path, filename, &width, &height, &depth) ) ) { fprintf (stderr, "failed to load pixmap %s\n", filename); return None; } /* adjust number of colors */ if (n_colors > depth) { n_colors = depth; } /* alloc ppm and image data */ data = malloc ( ((bitsPerPixel + 7) / 8) * width * height ); assert (data != NULL); ppm = malloc (depth * width * height); assert (ppm != NULL); /* create image */ image = XCreateImage (dpy, defVisual, defDepth, ZPixmap, 0, data, width, height, 32, 0 ); if (image == NULL) { fprintf (stderr, "create image failed\n"); return None; } /* recolor ppm image */ EpmToPpm (epm, ppm, width, height, n_colors, color); /* convert ppm to image */ (*ppm_to_image)(ppm, width, height, image); /* free ppm data */ free(epm); free(ppm); /* create pixmap */ tmp = XCreatePixmap(dpy, win, width, height, defDepth); /* put image */ XPutImage (dpy, tmp, gcWindow, image, 0, 0, 0, 0, width, height); /* delete image */ #ifdef DEBUG_ALLOC Dbg_Vfree (__FILE__, __LINE__, data); #endif XDestroyImage (image); /* thats 'all */ return tmp; } /* ReadEpmPixmap */ /* * */ Pixmap ReadRgbPixmap (const char *path, const char *filename) { XImage *image; Pixmap tmp; int width, height; char *data; unsigned char *ppm; /* load ppm file */ if (NULL == (ppm = ReadPpmFile (path, filename, &width, &height) ) ) { fprintf (stderr, "Failed to load pixmap %s\n",filename); return None; } /* alloc ppm and image data */ if (NULL == (data = malloc( ( (bitsPerPixel + 7) / 8) * width * height ) ) ) { fprintf (stderr, "failed to alloc image data\n"); return None; } /* create image */ image = XCreateImage (dpy, defVisual, defDepth, ZPixmap, 0, data, width, height, 32, 0 ); if (image == NULL) { fprintf (stderr, "create image failed\n"); return None; } /* convert ppm to image */ (*ppm_to_image)(ppm, width, height, image); /* free ppm data */ free (ppm); /* create pixmap */ tmp = XCreatePixmap(dpy, win, width, height, defDepth); /* put image */ XPutImage (dpy, tmp, gcWindow, image, 0, 0, 0, 0, width, height); /* delete image */ #ifdef DEBUG_ALLOC Dbg_Vfree (__FILE__, __LINE__, data); #endif XDestroyImage (image); return tmp; } /* ReadRgbPixmap */ /* * */ Pixmap ReadPbmBitmap (const char *path, const char *filename) { int width, height; unsigned char *pbm; Pixmap tmp; /* load ppm file */ if (NULL == (pbm = ReadPbmFile (path, filename, &width, &height) ) ) { fprintf (stderr, "Failed to load bitmap %s\n", filename); return None; } /* create bitmap data */ tmp = XCreateBitmapFromData (dpy, win, (char *)pbm, width, height); /* free ppm data */ free (pbm); return tmp; } /* ReadPbmBitmap */ /* * convert colorname to value */ XBColor GUI_ParseColor (const char *name) { XColor color; if (! XParseColor (dpy, DefaultColormap(dpy, DefaultScreen(dpy)), name, &color) ) { return COLOR_INVALID; } return SET_COLOR (color.red >> 11, color.green >> 11, color.blue >> 11); } /* GUI_ParseColor */ /* * end of file x11c_image.c */