/* $XConsortium: xwud.c /main/60 1996/11/24 17:23:09 rws $ */ /* $XFree86: xc/programs/xwud/xwud.c,v 3.2 1996/12/23 07:14:50 dawes Exp $ */ /* Copyright (c) 1985, 1986, 1988 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. */ /* xwud - marginally useful raster image undumper */ #include #include #include #include #include #include #define XK_LATIN1 #include #include #ifdef X_NOT_STDC_ENV extern int errno; extern char *malloc(); #else #include #endif unsigned Image_Size(); Atom wm_protocols; Atom wm_delete_window; int split; char *progname; usage() { fprintf(stderr, "usage: %s [-in ] [-noclick] [-geometry ] [-display ]\n", progname); fprintf(stderr, " [-new] [-std ] [-raw] [-vis ]\n"); fprintf(stderr, " [-help] [-rv] [-plane ] [-fg ] [-bg ]\n"); fprintf(stderr, " [-scale]\n"); exit(1); } Bool Read(ptr, size, nitems, stream) char *ptr; int size; int nitems; FILE *stream; { size *= nitems; while (size) { nitems = fread(ptr, 1, size, stream); if (nitems <= 0) return False; size -= nitems; ptr += nitems; } return True; } main(argc, argv) int argc; char **argv; { Display *dpy; int screen; register int i; XImage in_image_struct; XImage *in_image, *out_image; XSetWindowAttributes attributes; XVisualInfo vinfo, *vinfos; long mask; register char *buffer; unsigned long swaptest = 1; int count, stdcnt; unsigned buffer_size; int win_name_size; int ncolors; char *file_name = NULL; char *win_name; Bool inverse = False, rawbits = False, newmap = False; Bool onclick = True; Bool scale = False; int plane = -1; char *std = NULL; char *vis = NULL; char *display_name = NULL; char *fgname = NULL; char *bgname = NULL; char *geom = NULL; int gbits = 0; XSizeHints hints; XTextProperty textprop; XClassHint class_hint; XColor *colors, color, igncolor; Window image_win; Colormap colormap; XEvent event; register XExposeEvent *expose = (XExposeEvent *)&event; GC gc; XGCValues gc_val; XWDFileHeader header; XWDColor xwdcolor; FILE *in_file = stdin; char *map_name; Atom map_prop; XStandardColormap *stdmaps, *stdmap; char c; int win_width, win_height; progname = argv[0]; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-bg") == 0) { if (++i >= argc) usage(); bgname = argv[i]; continue; } if (strcmp(argv[i], "-display") == 0) { if (++i >= argc) usage(); display_name = argv[i]; continue; } if (strcmp(argv[i], "-fg") == 0) { if (++i >= argc) usage(); fgname = argv[i]; continue; } if (strcmp(argv[i], "-geometry") == 0) { if (++i >= argc) usage(); geom = argv[i]; continue; } if (strcmp(argv[i], "-help") == 0) { usage(); } if (strcmp(argv[i], "-in") == 0) { if (++i >= argc) usage(); file_name = argv[i]; continue; } if (strcmp(argv[i], "-inverse") == 0) { /* for compatibility */ inverse = True; continue; } if (strcmp(argv[i], "-new") == 0) { newmap = True; if (std) usage(); continue; } if (strcmp(argv[i], "-noclick") == 0) { onclick = False; continue; } if (strcmp(argv[i], "-plane") == 0) { if (++i >= argc) usage(); plane = atoi(argv[i]); continue; } if (strcmp(argv[i], "-raw") == 0) { rawbits = True; if (std) usage(); continue; } if (strcmp(argv[i], "-rv") == 0) { inverse = True; continue; } if (strcmp(argv[i], "-scale") == 0) { scale = True; continue; } if (strcmp(argv[i], "-split") == 0) { split = True; continue; } if (strcmp(argv[i], "-std") == 0) { if (++i >= argc) usage(); std = argv[i]; if (newmap || rawbits) usage(); continue; } if (strcmp(argv[i], "-vis") == 0) { if (++i >= argc) usage(); vis = argv[i]; continue; } usage(); } if (file_name) { in_file = fopen(file_name, "rb"); if (in_file == NULL) Error("Can't open input file as specified."); } #ifdef WIN32 else _setmode(fileno(in_file), _O_BINARY); #endif dpy = XOpenDisplay(display_name); if (dpy == NULL) { fprintf(stderr, "%s: unable to open display \"%s\"\n", progname, XDisplayName(display_name)); exit(1); } screen = DefaultScreen(dpy); /* * Read in header information. */ if(!Read((char *)&header, SIZEOF(XWDheader), 1, in_file)) Error("Unable to read dump file header."); if (*(char *) &swaptest) _swaplong((char *) &header, SIZEOF(XWDheader)); /* check to see if the dump file is in the proper format */ if (header.file_version != XWD_FILE_VERSION) { fprintf(stderr,"xwud: XWD file format version mismatch."); Error("exiting."); } if (header.header_size < SIZEOF(XWDheader)) { fprintf(stderr,"xwud: XWD header size is too small."); Error("exiting."); } /* alloc window name */ win_name_size = (header.header_size - SIZEOF(XWDheader)); if((win_name = malloc((unsigned) win_name_size + 6)) == NULL) Error("Can't malloc window name storage."); strcpy(win_name, "xwud: "); /* read in window name */ if(!Read(win_name + 6, sizeof(char), win_name_size, in_file)) Error("Unable to read window name from dump file."); /* initialize the input image */ in_image = &in_image_struct; in_image->depth = header.pixmap_depth; in_image->format = header.pixmap_format; in_image->xoffset = header.xoffset; in_image->data = NULL; in_image->width = header.pixmap_width; in_image->height = header.pixmap_height; in_image->bitmap_pad = header.bitmap_pad; in_image->bytes_per_line = header.bytes_per_line; in_image->byte_order = header.byte_order; in_image->bitmap_unit = header.bitmap_unit; in_image->bitmap_bit_order = header.bitmap_bit_order; in_image->bits_per_pixel = header.bits_per_pixel; in_image->red_mask = header.red_mask; in_image->green_mask = header.green_mask; in_image->blue_mask = header.blue_mask; if (!XInitImage(in_image)) Error("Invalid input image header data."); /* read in the color map buffer */ if(ncolors = header.ncolors) { colors = (XColor *)malloc((unsigned) ncolors * sizeof(XColor)); if (!colors) Error("Can't malloc color table"); for (i = 0; i < ncolors; i++) { if(!Read((char *) &xwdcolor, SIZEOF(XWDColor), 1, in_file)) Error("Unable to read color map from dump file."); colors[i].pixel = xwdcolor.pixel; colors[i].red = xwdcolor.red; colors[i].green = xwdcolor.green; colors[i].blue = xwdcolor.blue; colors[i].flags = xwdcolor.flags; } if (*(char *) &swaptest) { for (i = 0; i < ncolors; i++) { _swaplong((char *) &colors[i].pixel, sizeof(long)); _swapshort((char *) &colors[i].red, 3 * sizeof(short)); } } } else /* no color map exists, turn on the raw option */ rawbits = True; /* alloc the pixel buffer */ buffer_size = Image_Size(in_image); if((buffer = malloc(buffer_size)) == NULL) Error("Can't malloc data buffer."); /* read in the image data */ if (!Read(buffer, sizeof(char), (int)buffer_size, in_file)) Error("Unable to read pixmap from dump file."); /* close the input file */ (void) fclose(in_file); if (plane >= in_image->depth) Error("plane number exceeds image depth"); if ((in_image->format == XYPixmap) && (plane >= 0)) { buffer += in_image->bytes_per_line * in_image->height * (in_image->depth - (plane + 1)); in_image->depth = 1; ncolors = 0; } if (in_image->bits_per_pixel == 1 && in_image->depth == 1) { in_image->format = XYBitmap; newmap = False; rawbits = True; } in_image->data = buffer; if (std) { map_name = malloc(strlen(std) + 9); strcpy(map_name, "RGB_"); strcat(map_name, std); strcat(map_name, "_MAP"); Latin1Upper(map_name); map_prop = XInternAtom(dpy, map_name, True); if (!map_prop || !XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdmaps, &stdcnt, map_prop)) Error("specified standard colormap does not exist"); } vinfo.screen = screen; mask = VisualScreenMask; if (vis) { char *vt; vt = malloc(strlen(vis) + 1); strcpy(vt, vis); Latin1Upper(vt); if (strcmp(vt, "STATICGRAY") == 0) { vinfo.class = StaticGray; mask |= VisualClassMask; } else if (strcmp(vt, "GRAYSCALE") == 0) { vinfo.class = GrayScale; mask |= VisualClassMask; } else if (strcmp(vt, "STATICCOLOR") == 0) { vinfo.class = StaticColor; mask |= VisualClassMask; } else if (strcmp(vt, "PSEUDOCOLOR") == 0) { vinfo.class = PseudoColor; mask |= VisualClassMask; } else if (strcmp(vt, "DIRECTCOLOR") == 0) { vinfo.class = DirectColor; mask |= VisualClassMask; } else if (strcmp(vt, "TRUECOLOR") == 0) { vinfo.class = TrueColor; mask |= VisualClassMask; } else if (strcmp(vt, "MATCH") == 0) { vinfo.class = header.visual_class; mask |= VisualClassMask; } else if (strcmp(vt, "DEFAULT") == 0) { vinfo.visualid= XVisualIDFromVisual(DefaultVisual(dpy, screen)); mask |= VisualIDMask; } else { vinfo.visualid = 0; mask |= VisualIDMask; sscanf(vis, "0x%lx", &vinfo.visualid); if (!vinfo.visualid) sscanf(vis, "%ld", &vinfo.visualid); if (!vinfo.visualid) Error("invalid visual specifier"); } } if (rawbits && (in_image->depth > 1) && (plane < 0)) { vinfo.depth = in_image->depth; mask |= VisualDepthMask; } vinfos = XGetVisualInfo(dpy, mask, &vinfo, &count); if (count == 0) Error("no matching visual found"); /* find a workable visual */ if (std) { stdmap = &stdmaps[0]; if (mask & VisualIDMask) { for (i = 0; i < stdcnt; i++) { if (stdmaps[i].visualid == vinfo.visualid) { stdmap = &stdmaps[i]; break; } } if (stdmap->visualid != vinfo.visualid) Error("no standard colormap matching specified visual"); } for (i = 0; i < count; i++) { if (stdmap->visualid == vinfos[i].visualid) { vinfo = vinfos[i]; break; } } } else if ((in_image->depth == 1) || ((in_image->format == ZPixmap) && (plane >= 0)) || rawbits) { vinfo = vinfos[0]; if (!(mask & VisualIDMask)) { for (i = 0; i < count; i++) { if ((vinfos[i].visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen))) && (vinfos[i].depth == DefaultDepth(dpy, screen))) { vinfo = vinfos[i]; break; } } } } else { /* get best visual */ vinfo = vinfos[0]; for (i = 0; i < count; i++) { int z1, z2; z2 = EffectiveSize(&vinfos[i]); if ((z2 >= ncolors) && (vinfos[i].depth == in_image->depth) && (vinfos[i].class == header.visual_class)) { vinfo = vinfos[i]; break; } z1 = EffectiveSize(&vinfo); if ((z2 > z1) || ((z2 == z1) && (VisualRank(vinfos[i].class) >= VisualRank(vinfo.class)))) vinfo = vinfos[i]; } if ((newmap || (vinfo.visual != DefaultVisual(dpy, screen))) && (vinfo.class != StaticGray) && (vinfo.class != StaticColor) && (vinfo.class == header.visual_class) && (vinfo.depth == in_image->depth) && ((vinfo.class == PseudoColor) || (vinfo.class == GrayScale) || ((vinfo.red_mask == header.red_mask) && (vinfo.green_mask == header.green_mask) && (vinfo.blue_mask == header.blue_mask)))) { rawbits = True; newmap = True; } } /* get the appropriate colormap */ if (newmap && (vinfo.class & 1) && (vinfo.depth == in_image->depth) && (vinfo.class == header.visual_class) && (vinfo.colormap_size >= ncolors) && (vinfo.red_mask == header.red_mask) && (vinfo.green_mask == header.green_mask) && (vinfo.blue_mask == header.blue_mask)) { colormap = XCreateColormap(dpy, RootWindow(dpy, screen), vinfo.visual, AllocAll); if (ncolors) { for (i = 0; i < ncolors; i++) colors[i].flags = DoRed|DoGreen|DoBlue; XStoreColors(dpy, colormap, colors, ncolors); } } else if (std) { colormap = stdmap->colormap; } else { if (!newmap && (vinfo.visual == DefaultVisual(dpy, screen))) colormap = DefaultColormap(dpy, screen); else colormap = XCreateColormap(dpy, RootWindow(dpy, screen), vinfo.visual, AllocNone); newmap = False; } /* create the output image */ if ((in_image->format == ZPixmap) && (plane >= 0)) { out_image = XCreateImage(dpy, vinfo.visual, 1, XYBitmap, 0, NULL, in_image->width, in_image->height, XBitmapPad(dpy), 0); out_image->data = malloc(Image_Size(out_image)); Extract_Plane(in_image, out_image, plane); ncolors = 0; } else if (rawbits || newmap) { out_image = in_image; } else { out_image = XCreateImage(dpy, vinfo.visual, vinfo.depth, (vinfo.depth == 1) ? XYBitmap : in_image->format, in_image->xoffset, NULL, in_image->width, in_image->height, XBitmapPad(dpy), 0); out_image->data = malloc(Image_Size(out_image)); if (std) { if (!stdmap->green_max && !stdmap->blue_max && IsGray(dpy, stdmap)) Do_StdGray(dpy, stdmap, ncolors, colors, in_image, out_image); else Do_StdCol(dpy, stdmap, ncolors, colors, in_image, out_image); } else if ((header.visual_class == TrueColor) || (header.visual_class == DirectColor)) Do_Direct(dpy, &header, &colormap, ncolors, colors, in_image, out_image); else Do_Pseudo(dpy, &colormap, ncolors, colors, in_image, out_image); } if (out_image->depth == 1) { if (fgname && XAllocNamedColor(dpy, colormap, fgname, &color, &igncolor)) gc_val.foreground = color.pixel; else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[1])) gc_val.foreground = colors[1].pixel; else gc_val.foreground = BlackPixel (dpy, screen); if (bgname && XAllocNamedColor(dpy, colormap, bgname, &color, &igncolor)) gc_val.background = color.pixel; else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[0])) gc_val.background = colors[0].pixel; else gc_val.background = WhitePixel (dpy, screen); if (inverse) { unsigned long tmp; tmp = gc_val.foreground; gc_val.foreground = gc_val.background; gc_val.background = tmp; } } else { gc_val.background = XGetPixel(out_image, 0, 0); gc_val.foreground = 0; } attributes.background_pixel = gc_val.background; attributes.border_pixel = gc_val.background; if (scale) attributes.bit_gravity = ForgetGravity; else attributes.bit_gravity = NorthWestGravity; attributes.event_mask = ButtonPressMask|ButtonReleaseMask|KeyPressMask| ExposureMask; if (scale) attributes.event_mask |= StructureNotifyMask; attributes.colormap = colormap; hints.x = header.window_x; hints.y = header.window_y; hints.width = out_image->width; hints.height = out_image->height; if (geom) gbits = XParseGeometry(geom, &hints.x, &hints.y, (unsigned int *)&hints.width, (unsigned int *)&hints.height); hints.flags = ((gbits & (XValue|YValue)) ? USPosition : 0) | ((gbits & (HeightValue|WidthValue)) ? USSize : PSize); if (!scale) { hints.flags |= PMaxSize; hints.max_width = (hints.width > out_image->width) ? hints.width : out_image->width; hints.max_height = (hints.height > out_image->height) ? hints.height : out_image->height; } if ((gbits & XValue) && (gbits & XNegative)) hints.x += DisplayWidth(dpy, screen) - hints.width; if ((gbits & YValue) && (gbits & YNegative)) hints.y += DisplayHeight(dpy, screen) - hints.height; /* create the image window */ image_win = XCreateWindow(dpy, RootWindow(dpy, screen), hints.x, hints.y, hints.width, hints.height, 0, vinfo.depth, InputOutput, vinfo.visual, CWBorderPixel|CWBackPixel|CWColormap|CWEventMask|CWBitGravity, &attributes); win_width = hints.width; win_height = hints.height; /* Setup for ICCCM delete window. */ wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); (void) XSetWMProtocols (dpy, image_win, &wm_delete_window, 1); textprop.value = (unsigned char *) win_name; textprop.encoding = XA_STRING; textprop.format = 8; textprop.nitems = strlen(win_name); class_hint.res_name = (char *)NULL; class_hint.res_class = "Xwud"; /* set standard properties */ XSetWMProperties(dpy, image_win, &textprop, (XTextProperty *)NULL, argv, argc, &hints, (XWMHints *)NULL, &class_hint); /* map the image window */ XMapWindow(dpy, image_win); gc = XCreateGC (dpy, image_win, GCForeground|GCBackground, &gc_val); while (1) { /* wait on mouse input event to terminate */ XNextEvent(dpy, &event); switch(event.type) { case ClientMessage: if (event.xclient.message_type == wm_protocols && event.xclient.data.l[0] == wm_delete_window) { XCloseDisplay(dpy); exit(0); /* ICCCM delete window */ } break; case ButtonPress: break; case ButtonRelease: if (onclick) { XCloseDisplay(dpy); exit(0); } break; case KeyPress: i = XLookupString(&event.xkey, &c, 1, NULL, NULL); if ((i == 1) && ((c == 'q') || (c == 'Q') || (c == '\03'))) { XCloseDisplay(dpy); exit(0); } break; case ConfigureNotify: win_width = event.xconfigure.width; win_height = event.xconfigure.height; break; case Expose: if (scale) putScaledImage(dpy, image_win, gc, out_image, expose->x, expose->y, expose->width, expose->height, win_width, win_height); else if ((expose->x < out_image->width) && (expose->y < out_image->height)) { if ((out_image->width - expose->x) < expose->width) expose->width = out_image->width - expose->x; if ((out_image->height - expose->y) < expose->height) expose->height = out_image->height - expose->y; putImage(dpy, image_win, gc, out_image, expose->x, expose->y, expose->width, expose->height); } break; } } } putImage (dpy, image_win, gc, out_image, x, y, w, h) Display *dpy; Window image_win; GC gc; XImage *out_image; int x, y, w, h; { #define SPLIT_SIZE 100 int t_x, t_y, t_w, t_h; if (split) { for (t_y = y; t_y < y + h; t_y += t_h) { t_h = SPLIT_SIZE; if (t_y + t_h > y + h) t_h = y + h - t_y; for (t_x = x; t_x < x + w; t_x += t_w) { t_w = SPLIT_SIZE; if (t_x + t_w > x + w) t_w = x + w - t_x; XPutImage(dpy, image_win, gc, out_image, t_x, t_y, t_x, t_y, t_w, t_h); } } } else { XPutImage (dpy, image_win, gc, out_image, x, y, x, y, w, h); } } typedef short Position; typedef unsigned short Dimension; typedef unsigned long Pixel; #define roundint(x) (int)((x) + 0.5) typedef struct { Position *x, *y; Dimension *width, *height; } Table; putScaledImage(display, d, gc, src_image, exp_x, exp_y, exp_width, exp_height, dest_width, dest_height) Display* display; Drawable d; GC gc; XImage* src_image; int exp_x; int exp_y; unsigned int exp_width; unsigned int exp_height; unsigned int dest_width; unsigned int dest_height; { XImage *dest_image; Position x, y, min_y, max_y, exp_max_y, src_x, src_max_x, src_y; Dimension w, h, strip_height; Table table; Pixel pixel; double ratio_x, ratio_y; Bool fast8; if (dest_width == src_image->width && dest_height == src_image->height) { /* same for x and y, just send it out */ XPutImage(display, d, gc, src_image, exp_x, exp_y, exp_x, exp_y, exp_width, exp_height); return; } ratio_x = (double)dest_width / (double)src_image->width; ratio_y = (double)dest_height / (double)src_image->height; src_x = exp_x / ratio_x; if (src_x >= src_image->width) src_x = src_image->width - 1; src_y = exp_y / ratio_y; if (src_y >= src_image->height) src_y = src_image->height - 1; exp_max_y = exp_y + exp_height; src_max_x = roundint((exp_x + exp_width) / ratio_x) + 1; if (src_max_x > src_image->width) src_max_x = src_image->width; strip_height = 65536 / roundint(ratio_x * src_image->bytes_per_line); if (strip_height == 0) strip_height = 1; if (strip_height > exp_height) strip_height = exp_height; h = strip_height + roundint(ratio_y); dest_image = XCreateImage(display, DefaultVisualOfScreen( DefaultScreenOfDisplay(display)), src_image->depth, src_image->format, 0, NULL, dest_width, h, src_image->bitmap_pad, 0); dest_image->data = malloc(dest_image->bytes_per_line * h); fast8 = (src_image->depth == 8 && src_image->bits_per_pixel == 8 && dest_image->bits_per_pixel == 8 && src_image->format == ZPixmap); table.x = (Position *) malloc(sizeof(Position) * (src_image->width + 1)); table.y = (Position *) malloc(sizeof(Position) * (src_image->height + 1)); table.width = (Dimension *) malloc(sizeof(Dimension) * src_image->width); table.height = (Dimension *) malloc(sizeof(Dimension)*src_image->height); table.x[0] = 0; for (x = 1; x <= src_image->width; x++) { table.x[x] = roundint(ratio_x * x); table.width[x - 1] = table.x[x] - table.x[x - 1]; } table.y[0] = 0; for (y = 1; y <= src_image->height; y++) { table.y[y] = roundint(ratio_y * y); table.height[y - 1] = table.y[y] - table.y[y - 1]; } for (min_y = table.y[src_y]; min_y < exp_max_y; min_y = table.y[y]) { max_y = min_y + strip_height; if (max_y > exp_max_y) { strip_height = exp_max_y - min_y; max_y = exp_max_y; } for (y = src_y; table.y[y] < max_y; y++) { if (table.y[y] < min_y) continue; if (fast8) { for (x = src_x; x < src_max_x; x++) { pixel = ((unsigned char *)src_image->data) [y * src_image->bytes_per_line + x]; for (h = 0; h < table.height[y]; h++) { memset(dest_image->data + (table.y[y] + h - min_y) * dest_image->bytes_per_line + table.x[x], pixel, table.width[x]); } } } else { for (x = src_x; x < src_max_x; x++) { pixel = XGetPixel(src_image, x, y); for (h = 0; h < table.height[y]; h++) { for (w = 0; w < table.width[x]; w++) XPutPixel(dest_image, table.x[x] + w, table.y[y] + h - min_y, pixel); } } } } XPutImage(display, d, gc, dest_image, exp_x, 0, exp_x, min_y, exp_width, table.y[y] - min_y); if (y >= src_image->height) break; } XFree((char *)table.x); XFree((char *)table.y); XFree((char *)table.width); XFree((char *)table.height); XDestroyImage(dest_image); } Latin1Upper(s) char *s; { unsigned char *str = (unsigned char *)s; unsigned char c; for (; c = *str; str++) { if ((c >= XK_a) && (c <= XK_z)) *str = c - (XK_a - XK_A); else if ((c >= XK_agrave) && (c <= XK_odiaeresis)) *str = c - (XK_agrave - XK_Agrave); else if ((c >= XK_oslash) && (c <= XK_thorn)) *str = c - (XK_oslash - XK_Ooblique); } } Extract_Plane(in_image, out_image, plane) register XImage *in_image, *out_image; int plane; { register int x, y; for (y = 0; y < in_image->height; y++) for (x = 0; x < in_image->width; x++) XPutPixel(out_image, x, y, (XGetPixel(in_image, x, y) >> plane) & 1); } int EffectiveSize(vinfo) XVisualInfo *vinfo; { if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor)) return (vinfo->red_mask | vinfo->green_mask | vinfo->blue_mask) + 1; else return vinfo->colormap_size; } VisualRank(class) int class; { switch (class) { case PseudoColor: return 5; case DirectColor: return 4; case TrueColor: return 3; case StaticColor: return 2; case GrayScale: return 1; case StaticGray: return 0; } } int IsGray(dpy, stdmap) Display *dpy; XStandardColormap *stdmap; { XColor color; color.pixel = stdmap->base_pixel + (stdmap->red_max * stdmap->red_mult); XQueryColor(dpy, stdmap->colormap, &color); return (color.green || color.blue); } Do_StdGray(dpy, stdmap, ncolors, colors, in_image, out_image) Display *dpy; XStandardColormap *stdmap; int ncolors; XColor *colors; register XImage *in_image, *out_image; { register int i, x, y; register XColor *color; unsigned lim; lim = stdmap->red_max + 1; for (i = 0, color = colors; i < ncolors; i++, color++) color->pixel = stdmap->base_pixel + (((((int)(30L * color->red + 59L * color->green + 11L * color->blue) / 100) * lim) >> 16) * stdmap->red_mult); for (y = 0; y < in_image->height; y++) { for (x = 0; x < in_image->width; x++) { XPutPixel(out_image, x, y, colors[XGetPixel(in_image, x, y)].pixel); } } } #define MapVal(val,lim,mult) ((((val * lim) + 32768) / 65535) * mult) Do_StdCol(dpy, stdmap, ncolors, colors, in_image, out_image) Display *dpy; XStandardColormap *stdmap; int ncolors; XColor *colors; register XImage *in_image, *out_image; { register int i, x, y; register XColor *color; unsigned limr, limg, limb; limr = stdmap->red_max; limg = stdmap->green_max; limb = stdmap->blue_max; for (i = 0, color = colors; i < ncolors; i++, color++) color->pixel = stdmap->base_pixel + MapVal(color->red, limr, stdmap->red_mult) + MapVal(color->green, limg, stdmap->green_mult) + MapVal(color->blue, limb, stdmap->blue_mult); for (y = 0; y < in_image->height; y++) { for (x = 0; x < in_image->width; x++) { XPutPixel(out_image, x, y, colors[XGetPixel(in_image, x, y)].pixel); } } } Colormap CopyColormapAndFree(dpy, colormap) Display *dpy; Colormap colormap; { if (colormap == DefaultColormap(dpy, DefaultScreen(dpy))) return XCopyColormapAndFree(dpy, colormap); Error("Visual type is not large enough to hold all colors of the image."); } Do_Pseudo(dpy, colormap, ncolors, colors, in_image, out_image) Display *dpy; Colormap *colormap; int ncolors; XColor *colors; register XImage *in_image, *out_image; { register int i, x, y; register XColor *color; for (i = 0; i < ncolors; i++) colors[i].flags = 0; for (y = 0; y < in_image->height; y++) { for (x = 0; x < in_image->width; x++) { color = &colors[XGetPixel(in_image, x, y)]; if (!color->flags) { color->flags = DoRed | DoGreen | DoBlue; if (!XAllocColor(dpy, *colormap, color)) { *colormap = CopyColormapAndFree(dpy, *colormap); XAllocColor(dpy, *colormap, color); } } XPutPixel(out_image, x, y, color->pixel); } } } Do_Direct(dpy, header, colormap, ncolors, colors, in_image, out_image) Display *dpy; XWDFileHeader *header; Colormap *colormap; int ncolors; XColor *colors; XImage *in_image, *out_image; { register int x, y; XColor color; unsigned long rmask, gmask, bmask; int rshift = 0, gshift = 0, bshift = 0; int i; unsigned long pix, xpix; unsigned long *pixels, *rpixels; rmask = header->red_mask; while (!(rmask & 1)) { rmask >>= 1; rshift++; } gmask = header->green_mask; while (!(gmask & 1)) { gmask >>= 1; gshift++; } bmask = header->blue_mask; while (!(bmask & 1)) { bmask >>= 1; bshift++; } if (in_image->depth <= 12) { pix = 1 << in_image->depth; pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix); for (i = 0; i < pix; i++) pixels[i] = ~0L; color.flags = DoRed | DoGreen | DoBlue; for (y = 0; y < in_image->height; y++) { for (x = 0; x < in_image->width; x++) { pix = XGetPixel(in_image, x, y); if ((color.pixel = pixels[pix]) == ~0L) { color.red = (pix >> rshift) & rmask; color.green = (pix >> gshift) & gmask; color.blue = (pix >> bshift) & bmask; if (ncolors) { color.red = colors[color.red].red; color.green = colors[color.green].green; color.blue = colors[color.blue].blue; } else { color.red = (((unsigned long)color.red * 65535) / rmask); color.green = (((unsigned long)color.green * 65535) / gmask); color.blue = (((unsigned long)color.blue * 65535) / bmask); } if (!XAllocColor(dpy, *colormap, &color)) { *colormap = CopyColormapAndFree(dpy, *colormap); XAllocColor(dpy, *colormap, &color); } pixels[pix] = color.pixel; } XPutPixel(out_image, x, y, color.pixel); } } } else { pix = 1 << 12; pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix); rpixels = (unsigned long *)malloc(sizeof(unsigned long) * pix); for (i = 0; i < pix; i++) { pixels[i] = ~0L; rpixels[i] = ~0L; } color.flags = DoRed | DoGreen | DoBlue; for (y = 0; y < in_image->height; y++) { for (x = 0; x < in_image->width; x++) { pix = XGetPixel(in_image, x, y); xpix = ((pix >> 12) ^ pix) & ((1 << 12) - 1); if (((color.pixel = pixels[xpix]) == ~0L) || (rpixels[xpix] != pix)) { color.red = (pix >> rshift) & rmask; color.green = (pix >> gshift) & gmask; color.blue = (pix >> bshift) & bmask; if (ncolors) { color.red = colors[color.red].red; color.green = colors[color.green].green; color.blue = colors[color.blue].blue; } else { color.red = (((unsigned long)color.red * 65535) / rmask); color.green = (((unsigned long)color.green * 65535) / gmask); color.blue = (((unsigned long)color.blue * 65535) / bmask); } if (!XAllocColor(dpy, *colormap, &color)) { *colormap = CopyColormapAndFree(dpy, *colormap); XAllocColor(dpy, *colormap, &color); } pixels[xpix] = color.pixel; rpixels[xpix] = pix; } XPutPixel(out_image, x, y, color.pixel); } } } } unsigned Image_Size(image) XImage *image; { if (image->format != ZPixmap) return(image->bytes_per_line * image->height * image->depth); return((unsigned)image->bytes_per_line * image->height); } Error(string) char *string; { fprintf(stderr, "xwud: Error => %s\n", string); if (errno != 0) { perror("xwud"); fprintf(stderr, "\n"); } exit(1); } _swapshort (bp, n) register char *bp; register unsigned n; { register char c; register char *ep = bp + n; while (bp < ep) { c = *bp; *bp = *(bp + 1); bp++; *bp++ = c; } } _swaplong (bp, n) register char *bp; register unsigned n; { register char c; register char *ep = bp + n; register char *sp; while (bp < ep) { sp = bp + 3; c = *sp; *sp = *bp; *bp++ = c; sp = bp + 1; c = *sp; *sp = *bp; *bp++ = c; bp += 2; } }