From: Holger Schemel Date: Mon, 9 Nov 1998 21:33:47 +0000 (+0100) Subject: rnd-19981109-2 X-Git-Tag: 1.2.0^2~33 X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=commitdiff_plain;h=d46a473059b29c03d44430dfc75f170e3eb7cf63 rnd-19981109-2 --- diff --git a/src/Makefile b/src/Makefile index 50502fa7..ca65fea5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -94,7 +94,7 @@ SRCS = main.c \ random.c \ gifload.c \ gif.c \ - send.c \ + image.c \ new.c \ network.c \ netserv.c @@ -116,7 +116,7 @@ OBJS = main.o \ random.o \ gifload.o \ gif.o \ - send.o \ + image.o \ new.o \ network.o \ netserv.o diff --git a/src/gif.c b/src/gif.c index d2fdda81..bf3f5fc7 100644 --- a/src/gif.c +++ b/src/gif.c @@ -3,8 +3,8 @@ #define GIF_C -#include "xli.h" #include "gif.h" +#include "image.h" #define PUSH_PIXEL(p) \ { \ @@ -468,7 +468,7 @@ static int gifin_add_string(int p, int e) return GIFIN_SUCCESS; } -Image *gifLoad(char *fullname) +Image *Read_GIF_to_Image(char *fullname) { FILE *f; Image *image; @@ -508,7 +508,6 @@ Image *gifLoad(char *fullname) image = newRGBImage(gifin_img_width, gifin_img_height, (gifin_l_cmap_flag ? gifin_l_pixel_bits : gifin_g_pixel_bits)); - image->title = dupString(fullname); /* if image has a local colormap, override global colormap */ diff --git a/src/gifload.c b/src/gifload.c index 1e1aebcd..977678cd 100644 --- a/src/gifload.c +++ b/src/gifload.c @@ -14,7 +14,7 @@ #ifndef MSDOS #include "gifload.h" -#include "xli.h" +#include "image.h" #ifdef DEBUG /* @@ -27,7 +27,6 @@ extern long Counter(void); - int Read_GIF_to_Pixmaps(Display *display, Window window, char *filename, Pixmap *pixmap, Pixmap *pixmap_mask) { @@ -43,7 +42,7 @@ int Read_GIF_to_Pixmaps(Display *display, Window window, char *filename, #endif /* load GIF file */ - if (!(image = gifLoad(filename))) + if (!(image = Read_GIF_to_Image(filename))) { printf("Loading GIF image failed -- maybe no GIF...\n"); exit(1); @@ -77,7 +76,7 @@ int Read_GIF_to_Pixmaps(Display *display, Window window, char *filename, depth = DefaultDepth(display, screen); /* convert internal image structure to X11 XImage */ - if (!(ximageinfo = imageToXImage(display, screen, visual, depth, image))) + if (!(ximageinfo = Image_to_XImage(display, screen, visual, depth, image))) { fprintf(stderr, "Cannot convert Image to XImage.\n"); exit(1); @@ -94,7 +93,7 @@ int Read_GIF_to_Pixmaps(Display *display, Window window, char *filename, XSetWindowColormap(display, window, ximageinfo->cmap); /* convert XImage to Pixmap */ - if ((*pixmap = ximageToPixmap(display, window, ximageinfo)) == None) + if ((*pixmap = XImage_to_Pixmap(display, window, ximageinfo)) == None) { fprintf(stderr, "Cannot convert XImage to Pixmap.\n"); exit(1); @@ -118,7 +117,7 @@ int Read_GIF_to_Pixmaps(Display *display, Window window, char *filename, #endif /* convert internal image structure to X11 XImage */ - if (!(ximageinfo_mask = imageToXImage(display, screen, visual, depth, + if (!(ximageinfo_mask = Image_to_XImage(display, screen, visual, depth, image_mask))) { fprintf(stderr, "Cannot convert Image to XImage.\n"); @@ -133,7 +132,7 @@ int Read_GIF_to_Pixmaps(Display *display, Window window, char *filename, #endif /* convert XImage to Pixmap */ - if ((*pixmap_mask = ximageToPixmap(display, window, ximageinfo_mask)) == None) + if ((*pixmap_mask = XImage_to_Pixmap(display, window, ximageinfo_mask)) == None) { fprintf(stderr, "Cannot convert XImage to Pixmap.\n"); exit(1); diff --git a/src/image.c b/src/image.c new file mode 100644 index 00000000..f72ea230 --- /dev/null +++ b/src/image.c @@ -0,0 +1,864 @@ + +/* image.c */ + +#include "image.h" +#include "misc.h" + +/* extra colors to try allocating in private color maps to minimise flashing */ +#define NOFLASH_COLORS 256 + +Image *monochrome(Image *cimage) +{ + Image *image; + unsigned char *sp, *dp, *dp2; /* data pointers */ + unsigned int spl; /* source pixel length in bytes */ + unsigned int dll; /* destination line length in bytes */ + Pixel color; /* pixel color */ + unsigned int x, y; /* random counters */ + int bitmap_pixel; + + if (BITMAPP(cimage)) + return(NULL); + + image = newBitImage(cimage->width, cimage->height); + + spl = cimage->pixlen; + dll = (image->width / 8) + (image->width % 8 ? 1 : 0); + + sp = cimage->data; + dp = image->data; + + for (y= 0; y < cimage->height; y++) + { + for (x= 0; x < cimage->width; x++) + { + dp2 = dp + (x / 8); /* dp + x/8 */ + color= memToVal(sp, spl); + + if (cimage->rgb.red[color] > 0x0000 || + cimage->rgb.green[color] > 0x0000 || + cimage->rgb.blue[color] > 0x0000) + bitmap_pixel = 0x00; + else + bitmap_pixel = 0x80; + + *dp2 |= bitmap_pixel >> ( x % 8); + sp += spl; + } + + dp += dll; /* next row */ + } + + return(image); +} + +static unsigned int *buildIndex(unsigned int width, + unsigned int zoom, + unsigned int *rwidth) +{ + float fzoom; + unsigned int *index; + unsigned int a; + + if (!zoom) + { + fzoom= 100.0; + *rwidth= width; + } + else + { + fzoom= (float)zoom / 100.0; + *rwidth= (unsigned int)(fzoom * width + 0.5); + } + index= (unsigned int *)checked_malloc(sizeof(unsigned int) * *rwidth); + for (a= 0; a < *rwidth; a++) + { + if (zoom) + *(index + a)= (unsigned int)((float)a / fzoom + 0.5); + else + *(index + a)= a; + } + return(index); +} + +Image *zoom(Image *oimage, unsigned int xzoom, unsigned int yzoom) +{ + Image *image; + unsigned int *xindex, *yindex; + unsigned int xwidth, ywidth; + unsigned int x, y, xsrc, ysrc; + unsigned int pixlen; + unsigned int srclinelen; + unsigned int destlinelen; + byte *srcline, *srcptr; + byte *destline, *destptr; + byte srcmask, destmask, bit; + Pixel value; + + if ((!xzoom || xzoom==100) && (!yzoom || yzoom==100)) + return(oimage); + + if (!xzoom) + printf(" Zooming image Y axis by %d%%...", yzoom); + else if (!yzoom) + printf(" Zooming image X axis by %d%%...", xzoom); + else if (xzoom == yzoom) + printf(" Zooming image by %d%%...", xzoom); + else + printf(" Zooming image X axis by %d%% and Y axis by %d%%...", + xzoom, yzoom); + fflush(stdout); + + xindex= buildIndex(oimage->width, xzoom, &xwidth); + yindex= buildIndex(oimage->height, yzoom, &ywidth); + + switch (oimage->type) + { + case IBITMAP: + image= newBitImage(xwidth, ywidth); + for (x= 0; x < oimage->rgb.used; x++) + { + *(image->rgb.red + x)= *(oimage->rgb.red + x); + *(image->rgb.green + x)= *(oimage->rgb.green + x); + *(image->rgb.blue + x)= *(oimage->rgb.blue + x); + } + image->rgb.used= oimage->rgb.used; + destline= image->data; + destlinelen= (xwidth / 8) + (xwidth % 8 ? 1 : 0); + srcline= oimage->data; + srclinelen= (oimage->width / 8) + (oimage->width % 8 ? 1 : 0); + for (y= 0, ysrc= *(yindex + y); y < ywidth; y++) + { + while (ysrc != *(yindex + y)) + { + ysrc++; + srcline += srclinelen; + } + srcptr= srcline; + destptr= destline; + srcmask= 0x80; + destmask= 0x80; + bit= srcmask & *srcptr; + for (x= 0, xsrc= *(xindex + x); x < xwidth; x++) + { + if (xsrc != *(xindex + x)) + { + do + { + xsrc++; + if (!(srcmask >>= 1)) + { + srcmask= 0x80; + srcptr++; + } + } + while (xsrc != *(xindex + x)); + + bit= srcmask & *srcptr; + } + if (bit) + *destptr |= destmask; + if (!(destmask >>= 1)) + { + destmask= 0x80; + destptr++; + } + } + destline += destlinelen; + } + break; + + case IRGB: + image= newRGBImage(xwidth, ywidth, oimage->depth); + for (x= 0; x < oimage->rgb.used; x++) + { + *(image->rgb.red + x)= *(oimage->rgb.red + x); + *(image->rgb.green + x)= *(oimage->rgb.green + x); + *(image->rgb.blue + x)= *(oimage->rgb.blue + x); + } + image->rgb.used= oimage->rgb.used; + + pixlen= oimage->pixlen; + destptr= image->data; + srcline= oimage->data; + srclinelen= oimage->width * pixlen; + for (y= 0, ysrc= *(yindex + y); y < ywidth; y++) + { + while (ysrc != *(yindex + y)) + { + ysrc++; + srcline += srclinelen; + } + + srcptr = srcline; + value = memToVal(srcptr, image->pixlen); + + for (x=0, xsrc= *(xindex + x); xrgb.red, + *green = image->rgb.green, + *blue = image->rgb.blue; + Intensity r,g,b; + unsigned int x, y, badcount = 0, dupcount = 0, unusedcount = 0; + unsigned char *pixptr, *pixend; + + if (!RGBP(image) || image->rgb.compressed) + return; + + used = (unsigned char *)checked_calloc(sizeof(unsigned char) * depthToColors(image->depth)); + dmask = (1 << image->depth) -1; /* Mask any illegal bits for that depth */ + map = (Pixel *)checked_calloc(sizeof(Pixel) * depthToColors(image->depth)); + + /* init fast duplicate check table */ + for(r=0;r<32;r++) + for(g=0;g<32;g++) + for(b=0;b<32;b++) + fast[r][g][b] = 0; + + /* do pass 1 through the image to check index usage */ + + pixptr = image->data; + pixend = pixptr + (image->height * image->width); + for(;pixptr < pixend; pixptr++) + used[(*pixptr) & dmask] = 1; + + /* count the bad pixels */ + for (x = image->rgb.used; x < depthToColors(image->depth); x++) + if (used[x]) + badcount++; + + /* figure out duplicates and unuseds, and create the new mapping */ + next_index = 0; + for (x = 0; x < image->rgb.used; x++) + { + if (!used[x]) + { + unusedcount++; + continue; /* delete this index */ + } + + /* check for duplicate */ + r = red[x]; + g = green[x]; + b = blue[x]; + if (fast[r>>11][g>>11][b>>11]) /* if matches fast check */ + { + /* then do a linear search */ + for (y = x+1; y < image->rgb.used; y++) + { + if (r == red[y] && g == green[y] && b == blue[y]) + break; + } + if (y < image->rgb.used) /* found match */ + { + map[x] = y; + dupcount++; + continue; /* delete this index */ + } + fast[r>>11][g>>11][b>>11] = 1; + } + /* will map to this index */ + map[x] = next_index; + next_index++; + } + + /* change the image pixels */ + pixptr = image->data; + pixend = pixptr + (image->height * image->width); + for(;pixptr < pixend; pixptr++) + *pixptr = map[(*pixptr) & dmask]; + + /* change the colormap */ + for (x = 0; x < image->rgb.used; x++) + { + if (!used[x]) + continue; + red[map[x]] = red[x]; + green[map[x]] = green[x]; + blue[map[x]] = blue[x]; + } + image->rgb.used = next_index; + + /* clean up */ + free(map); + free(used); + +#if 0 + if (badcount) + printf("%d out-of-range pixels, ", badcount); + + if (!unusedcount && !dupcount) + printf("no improvment\n"); + else + { + if (dupcount) + printf("%d duplicate%s and %d unused color%s removed...", + dupcount, (dupcount == 1 ? "" : "s"), + unusedcount, (unusedcount == 1 ? "" : "s")); + printf("%d unique color%s\n", + next_index, (next_index == 1 ? "" : "s")); + } +#endif + + image->rgb.compressed= TRUE; /* don't do it again */ +} + + + + +Pixmap XImage_to_Pixmap(Display *disp, Window parent, XImageInfo *ximageinfo) +{ + Pixmap pixmap; + + pixmap = XCreatePixmap(disp, parent, + ximageinfo->ximage->width, ximageinfo->ximage->height, + ximageinfo->depth); + + ximageinfo->drawable = pixmap; + + XImage_to_Drawable(ximageinfo, 0, 0, 0, 0, + ximageinfo->ximage->width, ximageinfo->ximage->height); + return(pixmap); +} + +/* find the best pixmap depth supported by the server for a particular + * visual and return that depth. + * + * this is complicated by R3's lack of XListPixmapFormats so we fake it + * by looking at the structure ourselves. + */ + +static unsigned int bitsPerPixelAtDepth(Display *disp, int scrn, + unsigned int depth) +{ + XPixmapFormatValues *xf; + int nxf, a; + + xf = XListPixmapFormats(disp, &nxf); + for (a = 0; a < nxf; a++) + { + if (xf[a].depth == depth) + { + int bpp; + bpp = xf[a].bits_per_pixel; + XFree(xf); + return (unsigned int) bpp; + } + } + XFree(xf); + + /* this should never happen; if it does, we're in trouble + */ + + fprintf(stderr, "bitsPerPixelAtDepth: Can't find pixmap depth info!\n"); + exit(1); +} + +XImageInfo *Image_to_XImage(Display *disp, int scrn, Visual *visual, + unsigned int ddepth, Image *image) +{ + static XColor xcolor_private[NOFLASH_COLORS]; + static int colorcell_used[NOFLASH_COLORS]; + static Colormap global_cmap = 0; + static Pixel *global_cmap_index; + static int num_cmap_entries, free_cmap_entries; + static private_cmap = FALSE; + Pixel *redvalue, *greenvalue, *bluevalue; + unsigned int a, c=0, x, y, linelen, dpixlen, dbits; + XColor xcolor; + XGCValues gcv; + XImageInfo *ximageinfo; + + if (!global_cmap) + { + if (visual == DefaultVisual(disp, scrn)) + global_cmap = DefaultColormap(disp, scrn); + else + { + global_cmap = XCreateColormap(disp, RootWindow(disp, scrn), + visual, AllocNone); + private_cmap = TRUE; + } + } + + xcolor.flags = DoRed | DoGreen | DoBlue; + redvalue = greenvalue = bluevalue = NULL; + ximageinfo = (XImageInfo *)checked_malloc(sizeof(XImageInfo)); + ximageinfo->disp = disp; + ximageinfo->scrn = scrn; + ximageinfo->depth = 0; + ximageinfo->drawable = None; + ximageinfo->index = NULL; + ximageinfo->rootimage = FALSE; + ximageinfo->foreground = ximageinfo->background= 0; + ximageinfo->gc = NULL; + ximageinfo->ximage = NULL; + + switch (visual->class) + { + case TrueColor: + case DirectColor: + { + Pixel pixval; + unsigned int redcolors, greencolors, bluecolors; + unsigned int redstep, greenstep, bluestep; + unsigned int redbottom, greenbottom, bluebottom; + unsigned int redtop, greentop, bluetop; + + redvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256); + greenvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256); + bluevalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256); + + ximageinfo->cmap = global_cmap; + + retry_direct: /* tag we hit if a DirectColor allocation fails on + * default colormap */ + + /* calculate number of distinct colors in each band + */ + + redcolors = greencolors = bluecolors = 1; + for (pixval=1; pixval; pixval <<= 1) + { + if (pixval & visual->red_mask) + redcolors <<= 1; + if (pixval & visual->green_mask) + greencolors <<= 1; + if (pixval & visual->blue_mask) + bluecolors <<= 1; + } + + /* sanity check + */ + + if ((redcolors > visual->map_entries) || + (greencolors > visual->map_entries) || + (bluecolors > visual->map_entries)) + { + fprintf(stderr, "Warning: inconsistency in color information (this may be ugly)\n"); + } + + redstep = 256 / redcolors; + greenstep = 256 / greencolors; + bluestep = 256 / bluecolors; + redbottom = greenbottom = bluebottom = 0; + redtop = greentop = bluetop = 0; + for (a=0; amap_entries; a++) + { + if (redbottom < 256) + redtop = redbottom + redstep; + if (greenbottom < 256) + greentop = greenbottom + greenstep; + if (bluebottom < 256) + bluetop = bluebottom + bluestep; + + xcolor.red = (redtop - 1) << 8; + xcolor.green = (greentop - 1) << 8; + xcolor.blue = (bluetop - 1) << 8; + if (!XAllocColor(disp, ximageinfo->cmap, &xcolor)) + { + /* if an allocation fails for a DirectColor default visual then + * we should create a private colormap and try again. + */ + + if ((visual->class == DirectColor) && + (visual == DefaultVisual(disp, scrn))) + { + global_cmap = XCopyColormapAndFree(disp, global_cmap); + ximageinfo->cmap = global_cmap; + private_cmap = TRUE; + + goto retry_direct; + } + + /* something completely unexpected happened + */ + + fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n"); + free((byte *)redvalue); + free((byte *)greenvalue); + free((byte *)bluevalue); + free((byte *)ximageinfo); + return(NULL); + } + + /* fill in pixel values for each band at this intensity + */ + + while ((redbottom < 256) && (redbottom < redtop)) + redvalue[redbottom++] = xcolor.pixel & visual->red_mask; + while ((greenbottom < 256) && (greenbottom < greentop)) + greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask; + while ((bluebottom < 256) && (bluebottom < bluetop)) + bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask; + } + break; + } + + case PseudoColor: + + ximageinfo->cmap = global_cmap; + ximageinfo->index = + (Pixel *)checked_malloc(sizeof(Pixel) * image->rgb.used); + + for (a=0; argb.used; a++) + { + XColor xcolor2; + unsigned short mask; + int color_found; + int i; + + xcolor.red = *(image->rgb.red + a); + xcolor.green = *(image->rgb.green + a); + xcolor.blue = *(image->rgb.blue + a); + + /* look if this color already exists in our colormap */ + if (!XAllocColor(disp, ximageinfo->cmap, &xcolor)) + { + if (!private_cmap) + { + /* + printf("switching to private colormap...\n"); + */ + + /* we just filled up the default colormap -- get a private one + which contains all already allocated colors */ + + global_cmap = XCopyColormapAndFree(disp, global_cmap); + ximageinfo->cmap = global_cmap; + private_cmap = TRUE; + + /* allocate the rest of the color cells read/write */ + global_cmap_index = + (Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS); + for (i=0; i=0; i--) + { + xcolor2.pixel = *(global_cmap_index + i); + xcolor2 = xcolor_private[xcolor2.pixel]; + + if (colorcell_used[xcolor2.pixel]) + continue; + + if ((xcolor.red & mask) == (xcolor2.red & mask) && + (xcolor.green & mask) == (xcolor2.green & mask) && + (xcolor.blue & mask) == (xcolor2.blue & mask)) + { + /* + printf("replacing color cell %ld with a close color\n", + xcolor2.pixel); + */ + color_found = TRUE; + break; + } + } + + if (mask == 0x0000) + break; + + mask = (mask << 1) & 0xffff; + } + + if (!color_found) /* no more free color cells */ + { + printf("Sorry, cannot allocate enough colors!\n"); + exit(0); + } + + xcolor.pixel = xcolor2.pixel; + xcolor_private[xcolor.pixel] = xcolor; + colorcell_used[xcolor.pixel] = TRUE; + XStoreColor(disp, ximageinfo->cmap, &xcolor); + free_cmap_entries--; + } + + *(ximageinfo->index + a) = xcolor.pixel; + } + + /* + printf("still %d free colormap entries\n", free_cmap_entries); + */ + + ximageinfo->no = a; /* number of pixels allocated for this image */ + break; + + default: + printf("Sorry, only DirectColor, TrueColor and PseudoColor supported\n"); + exit(0); + break; + } + + /* create an XImage and related colormap based on the image type + * we have. + */ + + /* + printf(" Building XImage..."); + fflush(stdout); + */ + + switch (image->type) + { + case IBITMAP: + { + byte *data; + + /* we copy the data to be more consistent + */ + + linelen = ((image->width + 7) / 8); + data= checked_malloc(linelen * image->height); + + memcpy((char *)data, (char *)image->data, linelen * image->height); + + gcv.function= GXcopy; + ximageinfo->ximage= XCreateImage(disp, visual, 1, XYBitmap, + 0, (char *)data, image->width, image->height, + 8, linelen); + + /* use this if you want to use the bitmap as a mask */ + ximageinfo->depth = image->depth; + + if(visual->class == DirectColor || visual->class == TrueColor) + { + Pixel pixval; + dbits= bitsPerPixelAtDepth(disp, scrn, ddepth); + dpixlen= (dbits + 7) / 8; + pixval= redvalue[image->rgb.red[0] >> 8] | + greenvalue[image->rgb.green[0] >> 8] | + bluevalue[image->rgb.blue[0] >> 8]; + ximageinfo->background = pixval; + pixval= redvalue[image->rgb.red[1] >> 8] | + greenvalue[image->rgb.green[1] >> 8] | + bluevalue[image->rgb.blue[1] >> 8]; + ximageinfo->foreground = pixval; + } + else /* Not Direct or True Color */ + { + ximageinfo->foreground = BlackPixel(disp,scrn); + ximageinfo->background = WhitePixel(disp,scrn); + } + ximageinfo->ximage->bitmap_bit_order= MSBFirst; + ximageinfo->ximage->byte_order= MSBFirst; + + break; + } + + case IRGB: + { + /* modify image data to match visual and colormap + */ + + byte *data, *destptr, *srcptr; + + dbits = bitsPerPixelAtDepth(disp, scrn, ddepth); /* bits per pixel */ + dpixlen = (dbits + 7) / 8; /* bytes per pixel */ + + ximageinfo->ximage = XCreateImage(disp, visual, ddepth, ZPixmap, 0, + NULL, image->width, image->height, + 8, image->width * dpixlen); + + data = (byte *)checked_malloc(image->width * image->height * dpixlen); + ximageinfo->depth = ddepth; + ximageinfo->ximage->data = (char *)data; + ximageinfo->ximage->byte_order = MSBFirst; + srcptr = image->data; + destptr = data; + + switch (visual->class) + { + case DirectColor: + case TrueColor: + { + Pixel pixval; + + for (y=0; yheight; y++) + { + for (x=0; xwidth; x++) + { + pixval = memToVal(srcptr, 1); + pixval = redvalue[image->rgb.red[pixval] >> 8] | + greenvalue[image->rgb.green[pixval] >> 8] | + bluevalue[image->rgb.blue[pixval] >> 8]; + valToMem(pixval, destptr, dpixlen); + srcptr += 1; + destptr += dpixlen; + } + } + break; + } + + default: + { + if (dpixlen == 1) /* most common */ + { + for (y=0; yheight; y++) + { + for (x=0; xwidth; x++) + { + *destptr = ximageinfo->index[c + *srcptr]; + srcptr++; + destptr++; + } + } + } + else /* less common */ + { + for (y=0; yheight; y++) + { + for (x=0; xwidth; x++) + { + register unsigned long temp; + temp = memToVal(srcptr, 1); + valToMem(ximageinfo->index[c + temp], destptr, dpixlen); + srcptr += 1; + destptr += dpixlen; + } + } + } + } + break; + } + } + } + + /* + printf("done\n"); + */ + + if (redvalue) + { + free((byte *)redvalue); + free((byte *)greenvalue); + free((byte *)bluevalue); + } + + return(ximageinfo); +} + +/* Given an XImage and a drawable, move a rectangle from the Ximage + * to the drawable. + */ + +void XImage_to_Drawable(XImageInfo *ximageinfo, + int src_x, int src_y, int dst_x, int dst_y, + unsigned int w, unsigned int h) +{ + XGCValues gcv; + + /* build and cache the GC + */ + + if (!ximageinfo->gc) + { + gcv.function = GXcopy; + if (ximageinfo->ximage->depth == 1) + { + gcv.foreground = ximageinfo->foreground; + gcv.background = ximageinfo->background; + ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable, + GCFunction | GCForeground | GCBackground, + &gcv); + } + else + ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable, + GCFunction, &gcv); + } + + XPutImage(ximageinfo->disp, ximageinfo->drawable, ximageinfo->gc, + ximageinfo->ximage, src_x, src_y, dst_x, dst_y, w, h); +} + +/* free up anything cached in the local Ximage structure. + */ + +void freeXImage(Image *image, XImageInfo *ximageinfo) +{ + if (ximageinfo->index != NULL) /* if we allocated colors */ + { + if (ximageinfo->no > 0 && !ximageinfo->rootimage) /* don't free root colors */ + XFreeColors(ximageinfo->disp, ximageinfo->cmap, ximageinfo->index, + ximageinfo->no, 0); + free(ximageinfo->index); + } + if (ximageinfo->gc) + XFreeGC(ximageinfo->disp, ximageinfo->gc); + free((byte *)ximageinfo->ximage->data); + ximageinfo->ximage->data= NULL; + XDestroyImage(ximageinfo->ximage); + free((byte *)ximageinfo); + /* should we free private color map to ??? */ +} diff --git a/src/image.h b/src/image.h new file mode 100644 index 00000000..b6c6dfbd --- /dev/null +++ b/src/image.h @@ -0,0 +1,110 @@ + +/* image.h */ + +#include "main.h" + +typedef unsigned short Intensity; /* what X thinks an RGB intensity is */ + +/* This struct holds the X-client side bits for a rendered image. */ +typedef struct +{ + Display *disp; /* destination display */ + int scrn; /* destination screen */ + int depth; /* depth of drawable we want/have */ + Drawable drawable; /* drawable to send image to */ + Pixel *index; /* array of pixel values allocated */ + int no; /* number of pixels in the array */ + int rootimage; /* True if is a root image - eg, retain colors */ + Pixel foreground; /* foreground and background pixels for mono images */ + Pixel background; + Colormap cmap; /* colormap used for image */ + GC gc; /* cached gc for sending image */ + XImage *ximage; /* ximage structure */ +} XImageInfo; + +/* Function declarations */ +void sendXImage(); /* send.c */ +XImageInfo *imageToXImage(); +Pixmap ximageToPixmap(); +void freeXImage(); + + +typedef struct rgbmap +{ + unsigned int size; /* size of RGB map */ + unsigned int used; /* number of colors used in RGB map */ + int compressed; /* image uses colormap fully */ + Intensity *red; /* color values in X style */ + Intensity *green; + Intensity *blue; +} RGBMap; + +/* image structure + */ + +typedef struct { + unsigned int type; /* type of image */ + RGBMap rgb; /* RGB map of image if IRGB type */ + unsigned int width; /* width of image in pixels */ + unsigned int height; /* height of image in pixels */ + unsigned int depth; /* depth of image in bits if IRGB type */ + unsigned int pixlen; /* length of pixel if IRGB type */ + byte *data; /* data rounded to full byte for each row */ + float gamma; /* gamma of display the image is adjusted for */ +} Image; + +#define IBITMAP 0 /* image is a bitmap */ +#define IRGB 1 /* image is RGB */ + +#define BITMAPP(IMAGE) ((IMAGE)->type == IBITMAP) +#define RGBP(IMAGE) ((IMAGE)->type == IRGB) + +#define depthToColors(n) DepthToColorsTable[((n) < 24 ? (n) : 24)] + +/* + * Architecture independent memory to value conversions. + * Note the "Normal" internal format is big endian. + */ + +#define memToVal(PTR,LEN) ( \ +(LEN) == 1 ? (unsigned long)( *( (byte *)(PTR)) ) : \ +(LEN) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<< 8) \ + + ( *(((byte *)(PTR))+1) ) : \ +(LEN) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<16) \ + + (((unsigned long)(*(((byte *)(PTR))+1)))<< 8) \ + + ( *(((byte *)(PTR))+2) ) : \ + (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<24) \ + + (((unsigned long)(*(((byte *)(PTR))+1)))<<16) \ + + (((unsigned long)(*(((byte *)(PTR))+2)))<< 8) \ + + ( *(((byte *)(PTR))+3) ) ) + +#define valToMem(VAL,PTR,LEN) ( \ +(LEN) == 1 ? (*( (byte *)(PTR) ) = ( VAL ) ) : \ +(LEN) == 2 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>> 8), \ + *(((byte *)(PTR))+1) = ( VAL ) ) : \ +(LEN) == 3 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>16), \ + *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>> 8), \ + *(((byte *)(PTR))+2) = ( VAL ) ) : \ + (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>24), \ + *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>>16), \ + *(((byte *)(PTR))+2) = (((unsigned long)(VAL))>> 8), \ + *(((byte *)(PTR))+3) = ( VAL ) )) + + +/* functions */ + +extern unsigned long DepthToColorsTable[]; +Image *newBitImage(); +Image *newRGBImage(); +void freeImage(); +void freeImageData(); +void newRGBMapData(); +void freeRGBMapData(); +byte *lcalloc(); +byte *lmalloc(); + +Image *Read_GIF_to_Image(); +Image *monochrome(); +Image *zoom(); + +void compress(); diff --git a/src/misc.c b/src/misc.c index c560ae4b..a7e52dcc 100644 --- a/src/misc.c +++ b/src/misc.c @@ -446,6 +446,18 @@ void *checked_malloc(unsigned long size) return ptr; } +void *checked_calloc(unsigned long size) +{ + void *ptr; + + ptr = calloc(1, size); + + if (ptr == NULL) + Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size); + + return ptr; +} + #define TRANSLATE_KEYSYM_TO_KEYNAME 0 #define TRANSLATE_KEYSYM_TO_X11KEYNAME 1 #define TRANSLATE_X11KEYNAME_TO_KEYSYM 2 diff --git a/src/misc.h b/src/misc.h index 798e61ef..c0109175 100644 --- a/src/misc.h +++ b/src/misc.h @@ -45,6 +45,7 @@ void MarkTileDirty(int, int); void GetOptions(char **); void Error(int, char *, ...); void *checked_malloc(unsigned long); +void *checked_calloc(unsigned long); char *getKeyNameFromKeySym(KeySym); char *getX11KeyNameFromKeySym(KeySym); KeySym getKeySymFromX11KeyName(char *); diff --git a/src/new.c b/src/new.c index 508f7393..d1744d5e 100644 --- a/src/new.c +++ b/src/new.c @@ -1,7 +1,8 @@ /* new.c */ -#include "xli.h" +#include "image.h" +#include "misc.h" /* this table is useful for quick conversions between depth and ncolors */ @@ -35,26 +36,14 @@ unsigned long DepthToColorsTable[] = /* 24 */ 16777216 }; -char *dupString(char *s) -{ - char *d; - - if (!s) - return(NULL); - - d = (char *)lmalloc(strlen(s) + 1); - strcpy(d, s); - return(d); -} - void newRGBMapData(RGBMap *rgb, unsigned int size) { rgb->used = 0; rgb->size = size; rgb->compressed = FALSE; - rgb->red = (Intensity *)lmalloc(sizeof(Intensity) * size); - rgb->green = (Intensity *)lmalloc(sizeof(Intensity) * size); - rgb->blue = (Intensity *)lmalloc(sizeof(Intensity) * size); + rgb->red = (Intensity *)checked_malloc(sizeof(Intensity) * size); + rgb->green = (Intensity *)checked_malloc(sizeof(Intensity) * size); + rgb->blue = (Intensity *)checked_malloc(sizeof(Intensity) * size); } void freeRGBMapData(RGBMap *rgb) @@ -69,9 +58,8 @@ Image *newBitImage(unsigned int width, unsigned int height) Image *image; unsigned int linelen; - image = (Image *)lmalloc(sizeof(Image)); + image = (Image *)checked_malloc(sizeof(Image)); image->type = IBITMAP; - image->title = NULL; newRGBMapData(&(image->rgb), (unsigned int)2); *(image->rgb.red)= *(image->rgb.green) = *(image->rgb.blue)= 65535; *(image->rgb.red + 1)= *(image->rgb.green + 1) = *(image->rgb.blue + 1)= 0; @@ -80,7 +68,7 @@ Image *newBitImage(unsigned int width, unsigned int height) image->height = height; image->depth = 1; linelen = ((width + 7) / 8); - image->data = (unsigned char *)lcalloc(linelen * height); + image->data = (unsigned char *)checked_calloc(linelen * height); return(image); } @@ -93,25 +81,19 @@ Image *newRGBImage(unsigned int width, unsigned int height, unsigned int depth) depth = 1; /* sometimes interpreted as `one color' */ pixlen = ((depth+7) / 8); numcolors = depthToColors(depth); - image = (Image *)lmalloc(sizeof(Image)); + image = (Image *)checked_malloc(sizeof(Image)); image->type = IRGB; - image->title = NULL; newRGBMapData(&(image->rgb), numcolors); image->width = width; image->height = height; image->depth = depth; image->pixlen = pixlen; - image->data = (unsigned char *)lmalloc(width * height * pixlen); + image->data = (unsigned char *)checked_malloc(width * height * pixlen); return(image); } void freeImageData(Image *image) { - if (image->title) - { - free((byte *)image->title); - image->title= NULL; - } freeRGBMapData(&(image->rgb)); free(image->data); } @@ -121,37 +103,3 @@ void freeImage(Image *image) freeImageData(image); free((byte *)image); } - -byte *lmalloc(unsigned int size) -{ - byte *area; - - if (size == 0) - { - size = 1; - } - if (!(area = (byte *)malloc(size))) - { - fprintf(stderr, "Out of memory!\n"); - exit(1); - } - - return(area); -} - -byte *lcalloc(unsigned int size) -{ - byte *area; - - if (size == 0) - { - size = 1; - } - if (!(area = (byte *)calloc(1, size))) - { - fprintf(stderr, "Out of memory!\n"); - exit(1); - } - - return(area); -} diff --git a/src/send.c b/src/send.c deleted file mode 100644 index f0aeee1a..00000000 --- a/src/send.c +++ /dev/null @@ -1,890 +0,0 @@ - -/* send.c */ - -#include "xli.h" - -/* extra colors to try allocating in private color maps to minimise flashing */ -#define NOFLASH_COLORS 256 - -Image *monochrome(Image *cimage) -{ - Image *image; - unsigned char *sp, *dp, *dp2; /* data pointers */ - unsigned int spl; /* source pixel length in bytes */ - unsigned int dll; /* destination line length in bytes */ - Pixel color; /* pixel color */ - unsigned int x, y; /* random counters */ - int bitmap_pixel; - - if (BITMAPP(cimage)) - return(NULL); - - /* - printf(" Converting to monochrome..."); - fflush(stdout); - */ - - image= newBitImage(cimage->width, cimage->height); - if (cimage->title) - { - image->title= (char *)lmalloc(strlen(cimage->title) + 13); - sprintf(image->title, "%s (monochrome)", cimage->title); - } - - spl = cimage->pixlen; - dll = (image->width / 8) + (image->width % 8 ? 1 : 0); - - sp = cimage->data; - dp = image->data; - - for (y= 0; y < cimage->height; y++) - { - for (x= 0; x < cimage->width; x++) - { - dp2 = dp + (x / 8); /* dp + x/8 */ - color= memToVal(sp, spl); - - if (cimage->rgb.red[color] > 0x0000 || - cimage->rgb.green[color] > 0x0000 || - cimage->rgb.blue[color] > 0x0000) - bitmap_pixel = 0x00; - else - bitmap_pixel = 0x80; - - *dp2 |= bitmap_pixel >> ( x % 8); - sp += spl; - } - - dp += dll; /* next row */ - } - - /* - printf("done\n"); - */ - - return(image); -} - -static unsigned int *buildIndex(unsigned int width, - unsigned int zoom, - unsigned int *rwidth) -{ - float fzoom; - unsigned int *index; - unsigned int a; - - if (!zoom) - { - fzoom= 100.0; - *rwidth= width; - } - else - { - fzoom= (float)zoom / 100.0; - *rwidth= (unsigned int)(fzoom * width + 0.5); - } - index= (unsigned int *)lmalloc(sizeof(unsigned int) * *rwidth); - for (a= 0; a < *rwidth; a++) - { - if (zoom) - *(index + a)= (unsigned int)((float)a / fzoom + 0.5); - else - *(index + a)= a; - } - return(index); -} - -Image *zoom(Image *oimage, unsigned int xzoom, unsigned int yzoom) -{ - Image *image; - unsigned int *xindex, *yindex; - unsigned int xwidth, ywidth; - unsigned int x, y, xsrc, ysrc; - unsigned int pixlen; - unsigned int srclinelen; - unsigned int destlinelen; - byte *srcline, *srcptr; - byte *destline, *destptr; - byte srcmask, destmask, bit; - Pixel value; - - if ((!xzoom || xzoom==100) && (!yzoom || yzoom==100)) - return(oimage); - - if (!xzoom) - printf(" Zooming image Y axis by %d%%...", yzoom); - else if (!yzoom) - printf(" Zooming image X axis by %d%%...", xzoom); - else if (xzoom == yzoom) - printf(" Zooming image by %d%%...", xzoom); - else - printf(" Zooming image X axis by %d%% and Y axis by %d%%...", - xzoom, yzoom); - fflush(stdout); - - xindex= buildIndex(oimage->width, xzoom, &xwidth); - yindex= buildIndex(oimage->height, yzoom, &ywidth); - - switch (oimage->type) - { - case IBITMAP: - image= newBitImage(xwidth, ywidth); - for (x= 0; x < oimage->rgb.used; x++) - { - *(image->rgb.red + x)= *(oimage->rgb.red + x); - *(image->rgb.green + x)= *(oimage->rgb.green + x); - *(image->rgb.blue + x)= *(oimage->rgb.blue + x); - } - image->rgb.used= oimage->rgb.used; - destline= image->data; - destlinelen= (xwidth / 8) + (xwidth % 8 ? 1 : 0); - srcline= oimage->data; - srclinelen= (oimage->width / 8) + (oimage->width % 8 ? 1 : 0); - for (y= 0, ysrc= *(yindex + y); y < ywidth; y++) - { - while (ysrc != *(yindex + y)) - { - ysrc++; - srcline += srclinelen; - } - srcptr= srcline; - destptr= destline; - srcmask= 0x80; - destmask= 0x80; - bit= srcmask & *srcptr; - for (x= 0, xsrc= *(xindex + x); x < xwidth; x++) - { - if (xsrc != *(xindex + x)) - { - do - { - xsrc++; - if (!(srcmask >>= 1)) - { - srcmask= 0x80; - srcptr++; - } - } - while (xsrc != *(xindex + x)); - - bit= srcmask & *srcptr; - } - if (bit) - *destptr |= destmask; - if (!(destmask >>= 1)) - { - destmask= 0x80; - destptr++; - } - } - destline += destlinelen; - } - break; - - case IRGB: - image= newRGBImage(xwidth, ywidth, oimage->depth); - for (x= 0; x < oimage->rgb.used; x++) - { - *(image->rgb.red + x)= *(oimage->rgb.red + x); - *(image->rgb.green + x)= *(oimage->rgb.green + x); - *(image->rgb.blue + x)= *(oimage->rgb.blue + x); - } - image->rgb.used= oimage->rgb.used; - - pixlen= oimage->pixlen; - destptr= image->data; - srcline= oimage->data; - srclinelen= oimage->width * pixlen; - for (y= 0, ysrc= *(yindex + y); y < ywidth; y++) - { - while (ysrc != *(yindex + y)) - { - ysrc++; - srcline += srclinelen; - } - - srcptr = srcline; - value = memToVal(srcptr, image->pixlen); - - for (x=0, xsrc= *(xindex + x); xtitle = dupString(oimage->title); - free((byte *)xindex); - free((byte *)yindex); - - printf("done\n"); - - return(image); -} - -void compress(Image *image) -{ - unsigned char *used, fast[32][32][32]; - unsigned int dmask; /* Depth mask protection */ - Pixel *map; - unsigned int next_index; - Intensity *red = image->rgb.red, - *green = image->rgb.green, - *blue = image->rgb.blue; - Intensity r,g,b; - unsigned int x, y, badcount = 0, dupcount = 0, unusedcount = 0; - unsigned char *pixptr, *pixend; - - if (!RGBP(image) || image->rgb.compressed) - return; - - /* - printf(" Compressing colormap..."); - fflush(stdout); - */ - - used = (unsigned char *)lcalloc(sizeof(unsigned char) * depthToColors(image->depth)); - dmask = (1 << image->depth) -1; /* Mask any illegal bits for that depth */ - map = (Pixel *)lcalloc(sizeof(Pixel) * depthToColors(image->depth)); - - /* init fast duplicate check table */ - for(r=0;r<32;r++) - for(g=0;g<32;g++) - for(b=0;b<32;b++) - fast[r][g][b] = 0; - - /* do pass 1 through the image to check index usage */ - - pixptr = image->data; - pixend = pixptr + (image->height * image->width); - for(;pixptr < pixend; pixptr++) - used[(*pixptr) & dmask] = 1; - - /* count the bad pixels */ - for (x = image->rgb.used; x < depthToColors(image->depth); x++) - if (used[x]) - badcount++; - - /* figure out duplicates and unuseds, and create the new mapping */ - next_index = 0; - for (x = 0; x < image->rgb.used; x++) - { - if (!used[x]) - { - unusedcount++; - continue; /* delete this index */ - } - - /* check for duplicate */ - r = red[x]; - g = green[x]; - b = blue[x]; - if (fast[r>>11][g>>11][b>>11]) /* if matches fast check */ - { - /* then do a linear search */ - for (y = x+1; y < image->rgb.used; y++) - { - if (r == red[y] && g == green[y] && b == blue[y]) - break; - } - if (y < image->rgb.used) /* found match */ - { - map[x] = y; - dupcount++; - continue; /* delete this index */ - } - fast[r>>11][g>>11][b>>11] = 1; - } - /* will map to this index */ - map[x] = next_index; - next_index++; - } - - /* change the image pixels */ - pixptr = image->data; - pixend = pixptr + (image->height * image->width); - for(;pixptr < pixend; pixptr++) - *pixptr = map[(*pixptr) & dmask]; - - /* change the colormap */ - for (x = 0; x < image->rgb.used; x++) - { - if (!used[x]) - continue; - red[map[x]] = red[x]; - green[map[x]] = green[x]; - blue[map[x]] = blue[x]; - } - image->rgb.used = next_index; - - /* clean up */ - free(map); - free(used); - - /* - if (badcount) - printf("%d out-of-range pixels, ", badcount); - - if (!unusedcount && !dupcount) - printf("no improvment\n"); - else - { - if (dupcount) - printf("%d duplicate%s and %d unused color%s removed...", - dupcount, (dupcount == 1 ? "" : "s"), - unusedcount, (unusedcount == 1 ? "" : "s")); - printf("%d unique color%s\n", - next_index, (next_index == 1 ? "" : "s")); - } - */ - - image->rgb.compressed= TRUE; /* don't do it again */ -} - - - - -Pixmap ximageToPixmap(Display *disp, Window parent, XImageInfo *ximageinfo) -{ - Pixmap pixmap; - - pixmap = XCreatePixmap(disp, parent, - ximageinfo->ximage->width, ximageinfo->ximage->height, - ximageinfo->depth); - - ximageinfo->drawable = pixmap; - - sendXImage(ximageinfo, 0, 0, 0, 0, - ximageinfo->ximage->width, ximageinfo->ximage->height); - return(pixmap); -} - -/* find the best pixmap depth supported by the server for a particular - * visual and return that depth. - * - * this is complicated by R3's lack of XListPixmapFormats so we fake it - * by looking at the structure ourselves. - */ - -static unsigned int bitsPerPixelAtDepth(Display *disp, int scrn, - unsigned int depth) -{ -#if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 4) - /* the way things are */ - XPixmapFormatValues *xf; - int nxf, a; - - xf = XListPixmapFormats(disp, &nxf); - for (a = 0; a < nxf; a++) - { - if (xf[a].depth == depth) - { - int bpp; - bpp = xf[a].bits_per_pixel; - XFree(xf); - return (unsigned int) bpp; - } - } - XFree(xf); -#else /* the way things were (X11R3) */ - unsigned int a; - - for (a= 0; a < disp->nformats; a++) - if (disp->pixmap_format[a].depth == depth) - return(disp->pixmap_format[a].bits_per_pixel); -#endif - - /* this should never happen; if it does, we're in trouble - */ - - fprintf(stderr, "bitsPerPixelAtDepth: Can't find pixmap depth info!\n"); - exit(1); -} - -XImageInfo *imageToXImage(Display *disp, int scrn, Visual *visual, - unsigned int ddepth, Image *image) -{ - static XColor xcolor_private[NOFLASH_COLORS]; - static int colorcell_used[NOFLASH_COLORS]; - static Colormap global_cmap = 0; - static Pixel *global_cmap_index; - static int num_cmap_entries, free_cmap_entries; - static private_cmap = FALSE; - Pixel *redvalue, *greenvalue, *bluevalue; - unsigned int a, c=0, x, y, linelen, dpixlen, dbits; - XColor xcolor; - XGCValues gcv; - XImageInfo *ximageinfo; - - if (!global_cmap) - { - if (visual == DefaultVisual(disp, scrn)) - global_cmap = DefaultColormap(disp, scrn); - else - { - global_cmap = XCreateColormap(disp, RootWindow(disp, scrn), - visual, AllocNone); - private_cmap = TRUE; - } - } - - xcolor.flags = DoRed | DoGreen | DoBlue; - redvalue = greenvalue = bluevalue = NULL; - ximageinfo = (XImageInfo *)lmalloc(sizeof(XImageInfo)); - ximageinfo->disp = disp; - ximageinfo->scrn = scrn; - ximageinfo->depth = 0; - ximageinfo->drawable = None; - ximageinfo->index = NULL; - ximageinfo->rootimage = FALSE; - ximageinfo->foreground = ximageinfo->background= 0; - ximageinfo->gc = NULL; - ximageinfo->ximage = NULL; - - switch (visual->class) - { - case TrueColor: - case DirectColor: - { - Pixel pixval; - unsigned int redcolors, greencolors, bluecolors; - unsigned int redstep, greenstep, bluestep; - unsigned int redbottom, greenbottom, bluebottom; - unsigned int redtop, greentop, bluetop; - - redvalue = (Pixel *)lmalloc(sizeof(Pixel) * 256); - greenvalue = (Pixel *)lmalloc(sizeof(Pixel) * 256); - bluevalue = (Pixel *)lmalloc(sizeof(Pixel) * 256); - - ximageinfo->cmap = global_cmap; - - retry_direct: /* tag we hit if a DirectColor allocation fails on - * default colormap */ - - /* calculate number of distinct colors in each band - */ - - redcolors = greencolors = bluecolors = 1; - for (pixval=1; pixval; pixval <<= 1) - { - if (pixval & visual->red_mask) - redcolors <<= 1; - if (pixval & visual->green_mask) - greencolors <<= 1; - if (pixval & visual->blue_mask) - bluecolors <<= 1; - } - - /* sanity check - */ - - if ((redcolors > visual->map_entries) || - (greencolors > visual->map_entries) || - (bluecolors > visual->map_entries)) - { - fprintf(stderr, "Warning: inconsistency in color information (this may be ugly)\n"); - } - - redstep = 256 / redcolors; - greenstep = 256 / greencolors; - bluestep = 256 / bluecolors; - redbottom = greenbottom = bluebottom = 0; - redtop = greentop = bluetop = 0; - for (a=0; amap_entries; a++) - { - if (redbottom < 256) - redtop = redbottom + redstep; - if (greenbottom < 256) - greentop = greenbottom + greenstep; - if (bluebottom < 256) - bluetop = bluebottom + bluestep; - - xcolor.red = (redtop - 1) << 8; - xcolor.green = (greentop - 1) << 8; - xcolor.blue = (bluetop - 1) << 8; - if (!XAllocColor(disp, ximageinfo->cmap, &xcolor)) - { - /* if an allocation fails for a DirectColor default visual then - * we should create a private colormap and try again. - */ - - if ((visual->class == DirectColor) && - (visual == DefaultVisual(disp, scrn))) - { - global_cmap = XCopyColormapAndFree(disp, global_cmap); - ximageinfo->cmap = global_cmap; - private_cmap = TRUE; - - goto retry_direct; - } - - /* something completely unexpected happened - */ - - fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n"); - free((byte *)redvalue); - free((byte *)greenvalue); - free((byte *)bluevalue); - free((byte *)ximageinfo); - return(NULL); - } - - /* fill in pixel values for each band at this intensity - */ - - while ((redbottom < 256) && (redbottom < redtop)) - redvalue[redbottom++] = xcolor.pixel & visual->red_mask; - while ((greenbottom < 256) && (greenbottom < greentop)) - greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask; - while ((bluebottom < 256) && (bluebottom < bluetop)) - bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask; - } - break; - } - - case PseudoColor: - - ximageinfo->cmap = global_cmap; - ximageinfo->index = (Pixel *)lmalloc(sizeof(Pixel) * image->rgb.used); - - for (a=0; argb.used; a++) - { - XColor xcolor2; - unsigned short mask; - int color_found; - int i; - - xcolor.red = *(image->rgb.red + a); - xcolor.green = *(image->rgb.green + a); - xcolor.blue = *(image->rgb.blue + a); - - /* look if this color already exists in our colormap */ - if (!XAllocColor(disp, ximageinfo->cmap, &xcolor)) - { - if (!private_cmap) - { - /* - printf("switching to private colormap...\n"); - */ - - /* we just filled up the default colormap -- get a private one - which contains all already allocated colors */ - - global_cmap = XCopyColormapAndFree(disp, global_cmap); - ximageinfo->cmap = global_cmap; - private_cmap = TRUE; - - /* allocate the rest of the color cells read/write */ - global_cmap_index = - (Pixel *)lmalloc(sizeof(Pixel) * NOFLASH_COLORS); - for (i=0; i=0; i--) - { - xcolor2.pixel = *(global_cmap_index + i); - xcolor2 = xcolor_private[xcolor2.pixel]; - - if (colorcell_used[xcolor2.pixel]) - continue; - - if ((xcolor.red & mask) == (xcolor2.red & mask) && - (xcolor.green & mask) == (xcolor2.green & mask) && - (xcolor.blue & mask) == (xcolor2.blue & mask)) - { - /* - printf("replacing color cell %ld with a close color\n", - xcolor2.pixel); - */ - color_found = TRUE; - break; - } - } - - if (mask == 0x0000) - break; - - mask = (mask << 1) & 0xffff; - } - - if (!color_found) /* no more free color cells */ - { - printf("Sorry, cannot allocate enough colors!\n"); - exit(0); - } - - xcolor.pixel = xcolor2.pixel; - xcolor_private[xcolor.pixel] = xcolor; - colorcell_used[xcolor.pixel] = TRUE; - XStoreColor(disp, ximageinfo->cmap, &xcolor); - free_cmap_entries--; - } - - *(ximageinfo->index + a) = xcolor.pixel; - } - - /* - printf("still %d free colormap entries\n", free_cmap_entries); - */ - - ximageinfo->no = a; /* number of pixels allocated for this image */ - break; - - default: - printf("Sorry, only DirectColor, TrueColor and PseudoColor supported\n"); - exit(0); - break; - } - - /* create an XImage and related colormap based on the image type - * we have. - */ - - /* - printf(" Building XImage..."); - fflush(stdout); - */ - - switch (image->type) - { - case IBITMAP: - { - byte *data; - - /* we copy the data to be more consistent - */ - - linelen = ((image->width + 7) / 8); - data= lmalloc(linelen * image->height); - - memcpy((char *)data, (char *)image->data, linelen * image->height); - - gcv.function= GXcopy; - ximageinfo->ximage= XCreateImage(disp, visual, 1, XYBitmap, - 0, (char *)data, image->width, image->height, - 8, linelen); - - /* use this if you want to use the bitmap as a mask */ - ximageinfo->depth = image->depth; - - if(visual->class == DirectColor || visual->class == TrueColor) - { - Pixel pixval; - dbits= bitsPerPixelAtDepth(disp, scrn, ddepth); - dpixlen= (dbits + 7) / 8; - pixval= redvalue[image->rgb.red[0] >> 8] | - greenvalue[image->rgb.green[0] >> 8] | - bluevalue[image->rgb.blue[0] >> 8]; - ximageinfo->background = pixval; - pixval= redvalue[image->rgb.red[1] >> 8] | - greenvalue[image->rgb.green[1] >> 8] | - bluevalue[image->rgb.blue[1] >> 8]; - ximageinfo->foreground = pixval; - } - else /* Not Direct or True Color */ - { - ximageinfo->foreground = BlackPixel(disp,scrn); - ximageinfo->background = WhitePixel(disp,scrn); - } - ximageinfo->ximage->bitmap_bit_order= MSBFirst; - ximageinfo->ximage->byte_order= MSBFirst; - - break; - } - - case IRGB: - { - /* modify image data to match visual and colormap - */ - - byte *data, *destptr, *srcptr; - - dbits = bitsPerPixelAtDepth(disp, scrn, ddepth); /* bits per pixel */ - dpixlen = (dbits + 7) / 8; /* bytes per pixel */ - - ximageinfo->ximage = XCreateImage(disp, visual, ddepth, ZPixmap, 0, - NULL, image->width, image->height, - 8, image->width * dpixlen); - - data = (byte *)lmalloc(image->width * image->height * dpixlen); - ximageinfo->depth = ddepth; - ximageinfo->ximage->data = (char *)data; - ximageinfo->ximage->byte_order = MSBFirst; - srcptr = image->data; - destptr = data; - - switch (visual->class) - { - case DirectColor: - case TrueColor: - { - Pixel pixval; - - for (y=0; yheight; y++) - { - for (x=0; xwidth; x++) - { - pixval = memToVal(srcptr, 1); - pixval = redvalue[image->rgb.red[pixval] >> 8] | - greenvalue[image->rgb.green[pixval] >> 8] | - bluevalue[image->rgb.blue[pixval] >> 8]; - valToMem(pixval, destptr, dpixlen); - srcptr += 1; - destptr += dpixlen; - } - } - break; - } - - default: - { - if (dpixlen == 1) /* most common */ - { - for (y=0; yheight; y++) - { - for (x=0; xwidth; x++) - { - *destptr = ximageinfo->index[c + *srcptr]; - srcptr++; - destptr++; - } - } - } - else /* less common */ - { - for (y=0; yheight; y++) - { - for (x=0; xwidth; x++) - { - register unsigned long temp; - temp = memToVal(srcptr, 1); - valToMem(ximageinfo->index[c + temp], destptr, dpixlen); - srcptr += 1; - destptr += dpixlen; - } - } - } - } - break; - } - } - } - - /* - printf("done\n"); - */ - - if (redvalue) - { - free((byte *)redvalue); - free((byte *)greenvalue); - free((byte *)bluevalue); - } - - return(ximageinfo); -} - -/* Given an XImage and a drawable, move a rectangle from the Ximage - * to the drawable. - */ - -void sendXImage(XImageInfo *ximageinfo, - int src_x, int src_y, int dst_x, int dst_y, - unsigned int w, unsigned int h) -{ - XGCValues gcv; - - /* build and cache the GC - */ - - if (!ximageinfo->gc) - { - gcv.function = GXcopy; - if (ximageinfo->ximage->depth == 1) - { - gcv.foreground = ximageinfo->foreground; - gcv.background = ximageinfo->background; - ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable, - GCFunction | GCForeground | GCBackground, - &gcv); - } - else - ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable, - GCFunction, &gcv); - } - - XPutImage(ximageinfo->disp, ximageinfo->drawable, ximageinfo->gc, - ximageinfo->ximage, src_x, src_y, dst_x, dst_y, w, h); -} - -/* free up anything cached in the local Ximage structure. - */ - -void freeXImage(Image *image, XImageInfo *ximageinfo) -{ - if (ximageinfo->index != NULL) /* if we allocated colors */ - { - if (ximageinfo->no > 0 && !ximageinfo->rootimage) /* don't free root colors */ - XFreeColors(ximageinfo->disp, ximageinfo->cmap, ximageinfo->index, ximageinfo->no, 0); - free(ximageinfo->index); - } - if (ximageinfo->gc) - XFreeGC(ximageinfo->disp, ximageinfo->gc); - free((byte *)ximageinfo->ximage->data); - ximageinfo->ximage->data= NULL; - XDestroyImage(ximageinfo->ximage); - free((byte *)ximageinfo); - /* should we free private color map to ??? */ -} diff --git a/src/xli.h b/src/xli.h deleted file mode 100644 index 50826558..00000000 --- a/src/xli.h +++ /dev/null @@ -1,153 +0,0 @@ - -/* xli.h: - * - * jim frost 06.21.89 - * - * Copyright 1989 Jim Frost. See included file "copyright.h" for complete - * copyright information. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -typedef unsigned long Pixel; /* what X thinks a pixel is */ -typedef unsigned short Intensity; /* what X thinks an RGB intensity is */ -typedef unsigned char byte; /* unsigned byte type */ - -#define FALSE 0 -#define TRUE (!FALSE) - -/* Display device dependent Information structure */ -typedef struct -{ - int width; /* Display width and height */ - int height; - - Display *disp; - int scrn; - Colormap colormap; -} DisplayInfo; - -/* This struct holds the X-client side bits for a rendered image. */ -typedef struct -{ - Display *disp; /* destination display */ - int scrn; /* destination screen */ - int depth; /* depth of drawable we want/have */ - Drawable drawable; /* drawable to send image to */ - Pixel *index; /* array of pixel values allocated */ - int no; /* number of pixels in the array */ - int rootimage; /* True if is a root image - eg, retain colors */ - Pixel foreground; /* foreground and background pixels for mono images */ - Pixel background; - Colormap cmap; /* colormap used for image */ - GC gc; /* cached gc for sending image */ - XImage *ximage; /* ximage structure */ -} XImageInfo; - -/* Function declarations */ -void sendXImage(); /* send.c */ -XImageInfo *imageToXImage(); -Pixmap ximageToPixmap(); -void freeXImage(); - - -typedef struct rgbmap { - unsigned int size; /* size of RGB map */ - unsigned int used; /* number of colors used in RGB map */ - int compressed; /* image uses colormap fully */ - Intensity *red; /* color values in X style */ - Intensity *green; - Intensity *blue; -} RGBMap; - -/* image structure - */ - -typedef struct { - char *title; /* name of image */ - unsigned int type; /* type of image */ - RGBMap rgb; /* RGB map of image if IRGB type */ - unsigned int width; /* width of image in pixels */ - unsigned int height; /* height of image in pixels */ - unsigned int depth; /* depth of image in bits if IRGB type */ - unsigned int pixlen; /* length of pixel if IRGB type */ - byte *data; /* data rounded to full byte for each row */ - float gamma; /* gamma of display the image is adjusted for */ -} Image; - -#define IBITMAP 0 /* image is a bitmap */ -#define IRGB 1 /* image is RGB */ - -#define BITMAPP(IMAGE) ((IMAGE)->type == IBITMAP) -#define RGBP(IMAGE) ((IMAGE)->type == IRGB) - -#define depthToColors(n) DepthToColorsTable[((n) < 24 ? (n) : 24)] - -/* - * Architecture independent memory to value conversions. - * Note the "Normal" internal format is big endian. - */ - -#define memToVal(PTR,LEN) ( \ -(LEN) == 1 ? (unsigned long)( *( (byte *)(PTR)) ) : \ -(LEN) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<< 8) \ - + ( *(((byte *)(PTR))+1) ) : \ -(LEN) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<16) \ - + (((unsigned long)(*(((byte *)(PTR))+1)))<< 8) \ - + ( *(((byte *)(PTR))+2) ) : \ - (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<24) \ - + (((unsigned long)(*(((byte *)(PTR))+1)))<<16) \ - + (((unsigned long)(*(((byte *)(PTR))+2)))<< 8) \ - + ( *(((byte *)(PTR))+3) ) ) - -#define valToMem(VAL,PTR,LEN) ( \ -(LEN) == 1 ? (*( (byte *)(PTR) ) = ( VAL ) ) : \ -(LEN) == 2 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>> 8), \ - *(((byte *)(PTR))+1) = ( VAL ) ) : \ -(LEN) == 3 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>16), \ - *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>> 8), \ - *(((byte *)(PTR))+2) = ( VAL ) ) : \ - (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>24), \ - *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>>16), \ - *(((byte *)(PTR))+2) = (((unsigned long)(VAL))>> 8), \ - *(((byte *)(PTR))+3) = ( VAL ) )) - - -/* functions */ - -void cleanUpWindow(); /* window.c */ -char imageInWindow(); - -int visualClassFromName(); -char *nameOfVisualClass(); - -extern unsigned long DepthToColorsTable[]; /* new.c */ -char *dupString(); -Image *newBitImage(); -Image *newRGBImage(); -void freeImage(); -void freeImageData(); -void newRGBMapData(); -void freeRGBMapData(); -byte *lcalloc(); -byte *lmalloc(); - -Image *gifLoad(); -Image *monochrome(); -Image *zoom(); - -void compress(); /* compress.c */ - -int xliOpenDisplay(); -void tellAboutDisplay(DisplayInfo *); -void xliCloseDisplay(DisplayInfo *);