summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xwud.c1144
-rw-r--r--xwud.man150
2 files changed, 1294 insertions, 0 deletions
diff --git a/xwud.c b/xwud.c
new file mode 100644
index 0000000..2b1e6c9
--- /dev/null
+++ b/xwud.c
@@ -0,0 +1,1144 @@
+/* $Xorg: xwud.c,v 1.5 2001/02/09 02:06:04 xorgcvs Exp $ */
+/*
+
+Copyright 1985, 1986, 1988, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 OPEN GROUP 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 Open Group 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 Open Group.
+
+*/
+
+/* xwud - marginally useful raster image undumper */
+
+
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+#include <X11/XWDFile.h>
+#define XK_LATIN1
+#include <X11/keysymdef.h>
+#include <errno.h>
+
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#endif
+
+extern char *malloc();
+unsigned Image_Size();
+Atom wm_protocols;
+Atom wm_delete_window;
+int split;
+
+char *progname;
+
+usage()
+{
+ fprintf(stderr, "usage: %s [-in <file>] [-noclick] [-geometry <geom>] [-display <display>]\n", progname);
+ fprintf(stderr, " [-new] [-std <maptype>] [-raw] [-vis <vis-type-or-id>]\n");
+ fprintf(stderr, " [-help] [-rv] [-plane <number>] [-fg <color>] [-bg <color>]\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;
+ }
+}
diff --git a/xwud.man b/xwud.man
new file mode 100644
index 0000000..6a730df
--- /dev/null
+++ b/xwud.man
@@ -0,0 +1,150 @@
+.\" $Xorg: xwud.man,v 1.4 2001/02/09 02:06:04 xorgcvs Exp $
+.\" Copyright 1988, 1998 The Open Group
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, provided that
+.\" the above copyright notice appear in all copies and that both that
+.\" copyright notice and this permission notice appear in supporting
+.\" documentation.
+.\"
+.\" 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 OPEN GROUP 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 Open Group 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 Open Group.
+.TH XWUD 1 "Release 6.4" "X Version 11"
+.SH NAME
+xwud - image displayer for X
+.SH SYNOPSIS
+.B "xwud"
+[-in \fIfile\fP] [-noclick] [-geometry \fIgeom\fP] [-display \fIdisplay\fP]
+[-new] [-std <maptype>] [-raw] [-vis <vis-type-or-id>] [-scale]
+[-help] [-rv] [-plane \fInumber\fP] [-fg \fIcolor\fP] [-bg \fIcolor\fP]
+.SH DESCRIPTION
+.PP
+.I Xwud
+is an X Window System image undumping utility.
+.I Xwud
+allows X users to display in a window an image saved
+in a specially formatted dump file, such as produced by \fIxwd(1)\fP.
+.SH OPTIONS
+.PP
+.TP 8
+.B "-bg \fIcolor\fP"
+If a bitmap image (or a single plane of an image) is displayed, this option
+can be used to specify the color to display for the "0" bits in the image.
+.PP
+.TP 8
+.B "-display \fIdisplay\fP"
+This option allows you to specify the server to connect to; see \fIX(1)\fP.
+.PP
+.TP 8
+.B "-fg \fIcolor\fP"
+If a bitmap image (or a single plane of an image) is displayed, this option
+can be used to specify the color to display for the "1" bits in the image.
+.PP
+.TP 8
+.B "-geometry \fIgeom\fP"
+This option allows you to specify the size and position of the window.
+Typically you will only want to specify the position, and let the size
+default to the actual size of the image.
+.PP
+.TP 8
+.B "-help"
+Print out a short description of the allowable options.
+.PP
+.TP 8
+.B "-in \fIfile\fP"
+This option allows the user to explicitly specify the input
+file on the command line. If no input file is given, the standard input
+is assumed.
+.PP
+.TP 8
+.B -new
+This option forces creation of a new colormap for displaying the image.
+If the image characteristics happen to match those of the display, this
+can get the image on the screen faster, but at the cost of using a new
+colormap (which on most displays will cause other windows to go
+technicolor).
+.PP
+.TP 8
+.B "-noclick"
+Clicking any button in the window will terminate the application,
+unless this option is specified. Termination can always be achieved
+by typing 'q', 'Q', or ctrl-c.
+.PP
+.TP 8
+.B "-plane \fInumber\fP"
+You can select a single bit plane of the image to display
+with this option. Planes are numbered with zero being the least
+significant bit. This option can be used to figure out which plane to
+pass to \fIxpr(1)\fP for printing.
+.PP
+.TP 8
+.B -raw
+This option forces the image to be displayed with whatever color values
+happen to currently exist on the screen. This option is mostly useful when
+undumping an image back onto the same screen that the image originally
+came from, while the original windows are still on the screen, and results
+in getting the image on the screen faster.
+.PP
+.TP 8
+.B -rv
+If a bitmap image (or a single plane of an image) is displayed, this option
+forces the foreground and background colors to be swapped. This may be
+needed when displaying a bitmap image which has the color sense of pixel
+values "0" and "1" reversed from what they are on your display.
+.PP
+.TP 8
+.B -scale
+Allow the window to be resized, and scale the image to the size of the window.
+.PP
+.TP 8
+.B "-std \fImaptype\fP"
+This option causes the image to be displayed using the specified
+Standard Colormap. The property name is obtained by converting the
+type to upper case, prepending "RGB_", and appending "_MAP".
+Typical types are "best", "default", and "gray". See \fIxstdcmap(1)\fP
+for one way of creating Standard Colormaps.
+.PP
+.TP 8
+.B "-vis \fIvis-type-or-id\fP"
+This option allows you to specify a particular visual or visual class.
+The default is to pick the "best" one. A particular class can be
+specified: "StaticGray", "GrayScale", "StaticColor", "PseudoColor",
+"DirectColor", or "TrueColor". Or "Match" can be specified, meaning
+use the same class as the source image. Alternatively, an exact
+visual id (specific to the server) can be specified, either as a
+hexadecimal number (prefixed with "0x") or as a decimal number.
+Finally, "default" can be specified, meaning to use the same class
+as the colormap of the root window. Case is not significant in
+any of these strings.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+To get default display.
+.SH FILES
+.PP
+.TP 8
+.B XWDFile.h
+X Window Dump File format definition file.
+.SH BUGS
+xwud doesn't handle big/deep images very well on servers that don't
+have the BIG-REQUESTS extension.
+.SH SEE ALSO
+xwd(1), xpr(1), xstdcmap(1), X(1)
+.SH AUTHOR
+Bob Scheifler, MIT X Consortium
+
+