xwud.c revision 1b1389ee
1/* 2 3Copyright 1985, 1986, 1988, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29/* xwud - marginally useful raster image undumper */ 30 31 32#include <X11/Xos.h> 33#include <X11/Xlib.h> 34#include <X11/Xutil.h> 35#include <X11/Xatom.h> 36#include <stdio.h> 37#include <X11/XWDFile.h> 38#define XK_LATIN1 39#include <X11/keysymdef.h> 40#include <errno.h> 41#include <stdlib.h> 42 43static Atom wm_protocols; 44static Atom wm_delete_window; 45static int split; 46 47static char *progname; 48 49static void usage(void); 50static Bool Read(char *ptr, int size, int nitems, FILE *stream); 51static void putImage(Display *dpy, Window image_win, GC gc, 52 XImage *out_image, int x, int y, int w, int h); 53static void putScaledImage(Display *display, Drawable d, GC gc, 54 XImage *src_image, int exp_x, int exp_y, 55 unsigned int exp_width, unsigned int exp_height, 56 unsigned int dest_width, unsigned dest_height); 57static void Latin1Upper(char *s); 58static void Extract_Plane(XImage *in_image, XImage *out_image, int plane); 59static int EffectiveSize(XVisualInfo *vinfo); 60static int VisualRank(int class); 61static int IsGray(Display *dpy, XStandardColormap *stdmap); 62static void Do_StdGray(Display *dpy, XStandardColormap *stdmap, int ncolors, 63 XColor *colors, XImage *in_image, XImage *out_image); 64static void Do_StdCol(Display *dpy, XStandardColormap *stdmap, int ncolors, 65 XColor *colors, XImage *in_image, XImage *out_image); 66static Colormap CopyColormapAndFree(Display *dpy, Colormap colormap); 67static void Do_Pseudo(Display *dpy, Colormap *colormap, int ncolors, 68 XColor *colors, XImage *in_image, XImage *out_image); 69static void Do_Direct(Display *dpy, XWDFileHeader *header, Colormap *colormap, 70 int ncolors, XColor *colors, 71 XImage *in_image, XImage *out_image, XVisualInfo *vinfo); 72static unsigned int Image_Size(XImage *image); 73static void Error(char *string) _X_NORETURN; 74static void _swapshort(char *bp, unsigned int n); 75static void _swaplong(char *bp, unsigned int n); 76static void DumpHeader(const XWDFileHeader *header, const char *win_name); 77 78static void 79usage(void) 80{ 81 fprintf(stderr, "usage: %s [-in <file>] [-noclick] [-geometry <geom>] [-display <display>]\n", progname); 82 fprintf(stderr, " [-new] [-std <maptype>] [-raw] [-vis <vis-type-or-id>]\n"); 83 fprintf(stderr, " [-help] [-rv] [-plane <number>] [-fg <color>] [-bg <color>]\n"); 84 fprintf(stderr, " [-scale]\n"); 85 exit(1); 86} 87 88static Bool 89Read(char *ptr, int size, int nitems, FILE *stream) 90{ 91 size *= nitems; 92 while (size) { 93 nitems = fread(ptr, 1, size, stream); 94 if (nitems <= 0) 95 return False; 96 size -= nitems; 97 ptr += nitems; 98 } 99 return True; 100} 101 102int 103main(int argc, char *argv[]) 104{ 105 Display *dpy; 106 int screen; 107 register int i; 108 XImage in_image_struct; 109 XImage *in_image, *out_image; 110 XSetWindowAttributes attributes; 111 XVisualInfo vinfo, *vinfos; 112 long mask; 113 register char *buffer; 114 unsigned long swaptest = 1; 115 int count, stdcnt; 116 unsigned buffer_size; 117 int win_name_size; 118 int ncolors; 119 char *file_name = NULL; 120 char *win_name; 121 Bool inverse = False, rawbits = False, newmap = False; 122 Bool onclick = True; 123 Bool scale = False; 124 int plane = -1; 125 char *std = NULL; 126 char *vis = NULL; 127 char *display_name = NULL; 128 char *fgname = NULL; 129 char *bgname = NULL; 130 char *geom = NULL; 131 int gbits = 0; 132 XSizeHints hints; 133 XTextProperty textprop; 134 XClassHint class_hint; 135 XColor *colors = NULL, color, igncolor; 136 Window image_win; 137 Colormap colormap; 138 XEvent event; 139 register XExposeEvent *expose = (XExposeEvent *)&event; 140 GC gc; 141 XGCValues gc_val; 142 XWDFileHeader header; 143 XWDColor xwdcolor; 144 FILE *in_file = stdin; 145 char *map_name; 146 Atom map_prop; 147 XStandardColormap *stdmaps, *stdmap = NULL; 148 char c; 149 int win_width, win_height; 150 Bool dump_header = False; 151 152 progname = argv[0]; 153 154 for (i = 1; i < argc; i++) { 155 if (strcmp(argv[i], "-bg") == 0) { 156 if (++i >= argc) usage(); 157 bgname = argv[i]; 158 continue; 159 } 160 if (strcmp(argv[i], "-display") == 0) { 161 if (++i >= argc) usage(); 162 display_name = argv[i]; 163 continue; 164 } 165 if (strcmp(argv[i], "-dumpheader") == 0) { 166 dump_header = True; 167 continue; 168 } 169 if (strcmp(argv[i], "-fg") == 0) { 170 if (++i >= argc) usage(); 171 fgname = argv[i]; 172 continue; 173 } 174 if (strcmp(argv[i], "-geometry") == 0) { 175 if (++i >= argc) usage(); 176 geom = argv[i]; 177 continue; 178 } 179 if (strcmp(argv[i], "-help") == 0) { 180 usage(); 181 } 182 if (strcmp(argv[i], "-in") == 0) { 183 if (++i >= argc) usage(); 184 file_name = argv[i]; 185 continue; 186 } 187 if (strcmp(argv[i], "-inverse") == 0) { /* for compatibility */ 188 inverse = True; 189 continue; 190 } 191 if (strcmp(argv[i], "-new") == 0) { 192 newmap = True; 193 if (std) usage(); 194 continue; 195 } 196 if (strcmp(argv[i], "-noclick") == 0) { 197 onclick = False; 198 continue; 199 } 200 if (strcmp(argv[i], "-plane") == 0) { 201 if (++i >= argc) usage(); 202 plane = atoi(argv[i]); 203 continue; 204 } 205 if (strcmp(argv[i], "-raw") == 0) { 206 rawbits = True; 207 if (std) usage(); 208 continue; 209 } 210 if (strcmp(argv[i], "-rv") == 0) { 211 inverse = True; 212 continue; 213 } 214 if (strcmp(argv[i], "-scale") == 0) { 215 scale = True; 216 continue; 217 } 218 if (strcmp(argv[i], "-split") == 0) { 219 split = True; 220 continue; 221 } 222 if (strcmp(argv[i], "-std") == 0) { 223 if (++i >= argc) usage(); 224 std = argv[i]; 225 if (newmap || rawbits) usage(); 226 continue; 227 } 228 if (strcmp(argv[i], "-vis") == 0) { 229 if (++i >= argc) usage(); 230 vis = argv[i]; 231 continue; 232 } 233 usage(); 234 } 235 236 if (file_name) { 237 in_file = fopen(file_name, "rb"); 238 if (in_file == NULL) 239 Error("Can't open input file as specified."); 240 } 241#ifdef WIN32 242 else 243 _setmode(fileno(in_file), _O_BINARY); 244#endif 245 246 dpy = XOpenDisplay(display_name); 247 if (dpy == NULL) { 248 fprintf(stderr, "%s: unable to open display \"%s\"\n", 249 progname, XDisplayName(display_name)); 250 exit(1); 251 } 252 screen = DefaultScreen(dpy); 253 254 /* 255 * Read in header information. 256 */ 257 if(!Read((char *)&header, SIZEOF(XWDheader), 1, in_file)) 258 Error("Unable to read dump file header."); 259 260 if (*(char *) &swaptest) 261 _swaplong((char *) &header, SIZEOF(XWDheader)); 262 263 /* check to see if the dump file is in the proper format */ 264 if (header.file_version != XWD_FILE_VERSION) { 265 fprintf(stderr,"xwud: XWD file format version mismatch."); 266 Error("exiting."); 267 } 268 if (header.header_size < SIZEOF(XWDheader)) { 269 fprintf(stderr,"xwud: XWD header size is too small."); 270 Error("exiting."); 271 } 272 273 /* alloc window name */ 274 win_name_size = (header.header_size - SIZEOF(XWDheader)); 275 if (win_name_size < 1) 276 Error("win_name_size"); 277 if((win_name = malloc((unsigned) win_name_size + 6)) == NULL) 278 Error("Can't malloc window name storage."); 279 strcpy(win_name, "xwud: "); 280 281 /* read in window name */ 282 if(!Read(win_name + 6, sizeof(char), win_name_size, in_file)) 283 Error("Unable to read window name from dump file."); 284 (win_name + 6)[win_name_size - 1] = 0; 285 286 if (dump_header) { 287 DumpHeader(&header, win_name); 288 exit(0); 289 } 290 291 /* initialize the input image */ 292 293 in_image = &in_image_struct; 294 in_image->depth = header.pixmap_depth; 295 in_image->format = header.pixmap_format; 296 in_image->xoffset = header.xoffset; 297 in_image->data = NULL; 298 in_image->width = header.pixmap_width; 299 in_image->height = header.pixmap_height; 300 in_image->bitmap_pad = header.bitmap_pad; 301 in_image->bytes_per_line = header.bytes_per_line; 302 in_image->byte_order = header.byte_order; 303 in_image->bitmap_unit = header.bitmap_unit; 304 in_image->bitmap_bit_order = header.bitmap_bit_order; 305 in_image->bits_per_pixel = header.bits_per_pixel; 306 in_image->red_mask = header.red_mask; 307 in_image->green_mask = header.green_mask; 308 in_image->blue_mask = header.blue_mask; 309 if (!XInitImage(in_image)) 310 Error("Invalid input image header data."); 311 312 /* read in the color map buffer */ 313 if((ncolors = header.ncolors)) { 314 colors = (XColor *)malloc((unsigned) ncolors * sizeof(XColor)); 315 if (!colors) 316 Error("Can't malloc color table"); 317 for (i = 0; i < ncolors; i++) { 318 if(!Read((char *) &xwdcolor, SIZEOF(XWDColor), 1, in_file)) 319 Error("Unable to read color map from dump file."); 320 colors[i].pixel = xwdcolor.pixel; 321 colors[i].red = xwdcolor.red; 322 colors[i].green = xwdcolor.green; 323 colors[i].blue = xwdcolor.blue; 324 colors[i].flags = xwdcolor.flags; 325 } 326 if (*(char *) &swaptest) { 327 for (i = 0; i < ncolors; i++) { 328 _swaplong((char *) &colors[i].pixel, sizeof(long)); 329 _swapshort((char *) &colors[i].red, 3 * sizeof(short)); 330 } 331 } 332 } 333 else 334 /* no color map exists, turn on the raw option */ 335 rawbits = True; 336 337 /* alloc the pixel buffer */ 338 buffer_size = Image_Size(in_image); 339 if((buffer = malloc(buffer_size)) == NULL) 340 Error("Can't malloc data buffer."); 341 342 /* read in the image data */ 343 if (!Read(buffer, sizeof(char), (int)buffer_size, in_file)) 344 Error("Unable to read pixmap from dump file."); 345 346 /* close the input file */ 347 (void) fclose(in_file); 348 349 if (plane >= in_image->depth) 350 Error("plane number exceeds image depth"); 351 if ((in_image->format == XYPixmap) && (plane >= 0)) { 352 buffer += in_image->bytes_per_line * in_image->height * 353 (in_image->depth - (plane + 1)); 354 in_image->depth = 1; 355 ncolors = 0; 356 } 357 if (in_image->bits_per_pixel == 1 && in_image->depth == 1) { 358 in_image->format = XYBitmap; 359 newmap = False; 360 rawbits = True; 361 } 362 in_image->data = buffer; 363 364 if (std) { 365 map_name = malloc(strlen(std) + 9); 366 strcpy(map_name, "RGB_"); 367 strcat(map_name, std); 368 strcat(map_name, "_MAP"); 369 Latin1Upper(map_name); 370 map_prop = XInternAtom(dpy, map_name, True); 371 if (!map_prop || !XGetRGBColormaps(dpy, RootWindow(dpy, screen), 372 &stdmaps, &stdcnt, map_prop)) 373 Error("specified standard colormap does not exist"); 374 } 375 vinfo.screen = screen; 376 mask = VisualScreenMask; 377 if (vis) 378 { 379 char *vt = strdup(vis); 380 Latin1Upper(vt); 381 if (strcmp(vt, "STATICGRAY") == 0) { 382 vinfo.class = StaticGray; 383 mask |= VisualClassMask; 384 } else if (strcmp(vt, "GRAYSCALE") == 0) { 385 vinfo.class = GrayScale; 386 mask |= VisualClassMask; 387 } else if (strcmp(vt, "STATICCOLOR") == 0) { 388 vinfo.class = StaticColor; 389 mask |= VisualClassMask; 390 } else if (strcmp(vt, "PSEUDOCOLOR") == 0) { 391 vinfo.class = PseudoColor; 392 mask |= VisualClassMask; 393 } else if (strcmp(vt, "DIRECTCOLOR") == 0) { 394 vinfo.class = DirectColor; 395 mask |= VisualClassMask; 396 } else if (strcmp(vt, "TRUECOLOR") == 0) { 397 vinfo.class = TrueColor; 398 mask |= VisualClassMask; 399 } else if (strcmp(vt, "MATCH") == 0) { 400 vinfo.class = header.visual_class; 401 mask |= VisualClassMask; 402 } else if (strcmp(vt, "DEFAULT") == 0) { 403 vinfo.visualid= XVisualIDFromVisual(DefaultVisual(dpy, screen)); 404 mask |= VisualIDMask; 405 } else { 406 vinfo.visualid = 0; 407 mask |= VisualIDMask; 408 sscanf(vis, "0x%lx", &vinfo.visualid); 409 if (!vinfo.visualid) 410 sscanf(vis, "%lu", &vinfo.visualid); 411 if (!vinfo.visualid) 412 Error("invalid visual specifier"); 413 } 414 } 415 if (rawbits && (in_image->depth > 1) && (plane < 0)) { 416 vinfo.depth = in_image->depth; 417 mask |= VisualDepthMask; 418 } 419 vinfos = XGetVisualInfo(dpy, mask, &vinfo, &count); 420 if (count == 0) 421 Error("no matching visual found"); 422 423 /* find a workable visual */ 424 if (std) { 425 stdmap = &stdmaps[0]; 426 if (mask & VisualIDMask) { 427 for (i = 0; i < stdcnt; i++) { 428 if (stdmaps[i].visualid == vinfo.visualid) { 429 stdmap = &stdmaps[i]; 430 break; 431 } 432 } 433 if (stdmap->visualid != vinfo.visualid) 434 Error("no standard colormap matching specified visual"); 435 } 436 for (i = 0; i < count; i++) { 437 if (stdmap->visualid == vinfos[i].visualid) { 438 vinfo = vinfos[i]; 439 break; 440 } 441 } 442 } else if ((in_image->depth == 1) || 443 ((in_image->format == ZPixmap) && (plane >= 0)) || 444 rawbits) { 445 vinfo = vinfos[0]; 446 if (!(mask & VisualIDMask)) { 447 for (i = 0; i < count; i++) { 448 if ((vinfos[i].visualid == 449 XVisualIDFromVisual(DefaultVisual(dpy, screen))) && 450 (vinfos[i].depth == DefaultDepth(dpy, screen))) { 451 vinfo = vinfos[i]; 452 break; 453 } 454 } 455 } 456 } else { 457 /* get best visual */ 458 vinfo = vinfos[0]; 459 for (i = 0; i < count; i++) { 460 int z1, z2; 461 z2 = EffectiveSize(&vinfos[i]); 462 if ((z2 >= ncolors) && 463 (vinfos[i].depth == in_image->depth) && 464 (vinfos[i].class == header.visual_class)) 465 { 466 vinfo = vinfos[i]; 467 break; 468 } 469 z1 = EffectiveSize(&vinfo); 470 if ((z2 > z1) || 471 ((z2 == z1) && 472 (VisualRank(vinfos[i].class) >= VisualRank(vinfo.class)))) 473 vinfo = vinfos[i]; 474 } 475 if ((newmap || (vinfo.visual != DefaultVisual(dpy, screen))) && 476 (vinfo.class != StaticGray) && 477 (vinfo.class != StaticColor) && 478 (vinfo.class == header.visual_class) && 479 (vinfo.depth == in_image->depth) && 480 ((vinfo.class == PseudoColor) || 481 (vinfo.class == GrayScale) || 482 ((vinfo.red_mask == header.red_mask) && 483 (vinfo.green_mask == header.green_mask) && 484 (vinfo.blue_mask == header.blue_mask)))) { 485 rawbits = True; 486 newmap = True; 487 } 488 } 489 490 /* get the appropriate colormap */ 491 if (newmap && (vinfo.class & 1) && 492 (vinfo.depth == in_image->depth) && 493 (vinfo.class == header.visual_class) && 494 (vinfo.colormap_size >= ncolors) && 495 (vinfo.red_mask == header.red_mask) && 496 (vinfo.green_mask == header.green_mask) && 497 (vinfo.blue_mask == header.blue_mask)) { 498 colormap = XCreateColormap(dpy, RootWindow(dpy, screen), vinfo.visual, 499 AllocAll); 500 if (ncolors) { 501 for (i = 0; i < ncolors; i++) 502 colors[i].flags = DoRed|DoGreen|DoBlue; 503 XStoreColors(dpy, colormap, colors, ncolors); 504 } 505 } else if (std) { 506 colormap = stdmap->colormap; 507 } else { 508 if (!newmap && (vinfo.visual == DefaultVisual(dpy, screen))) 509 colormap = DefaultColormap(dpy, screen); 510 else 511 colormap = XCreateColormap(dpy, RootWindow(dpy, screen), 512 vinfo.visual, AllocNone); 513 newmap = False; 514 } 515 516 /* create the output image */ 517 if ((in_image->format == ZPixmap) && (plane >= 0)) { 518 out_image = XCreateImage(dpy, vinfo.visual, 1, 519 XYBitmap, 0, NULL, 520 in_image->width, in_image->height, 521 XBitmapPad(dpy), 0); 522 out_image->data = malloc(Image_Size(out_image)); 523 Extract_Plane(in_image, out_image, plane); 524 ncolors = 0; 525 } else if (rawbits || newmap) { 526 out_image = in_image; 527 } else { 528 out_image = XCreateImage(dpy, vinfo.visual, vinfo.depth, 529 (vinfo.depth == 1) ? XYBitmap : 530 in_image->format, 531 in_image->xoffset, NULL, 532 in_image->width, in_image->height, 533 XBitmapPad(dpy), 0); 534 out_image->data = malloc(Image_Size(out_image)); 535 if (std) { 536 if (!stdmap->green_max && !stdmap->blue_max && IsGray(dpy, stdmap)) 537 Do_StdGray(dpy, stdmap, ncolors, colors, in_image, out_image); 538 else 539 Do_StdCol(dpy, stdmap, ncolors, colors, in_image, out_image); 540 } else if ((header.visual_class == TrueColor) || 541 (header.visual_class == DirectColor)) 542 Do_Direct(dpy, &header, &colormap, ncolors, colors, 543 in_image, out_image, &vinfo); 544 else 545 Do_Pseudo(dpy, &colormap, ncolors, colors, in_image, out_image); 546 } 547 548 if (out_image->depth == 1) { 549 if (fgname && 550 XAllocNamedColor(dpy, colormap, fgname, &color, &igncolor)) 551 gc_val.foreground = color.pixel; 552 else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[1])) 553 gc_val.foreground = colors[1].pixel; 554 else 555 gc_val.foreground = BlackPixel (dpy, screen); 556 if (bgname && 557 XAllocNamedColor(dpy, colormap, bgname, &color, &igncolor)) 558 gc_val.background = color.pixel; 559 else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[0])) 560 gc_val.background = colors[0].pixel; 561 else 562 gc_val.background = WhitePixel (dpy, screen); 563 if (inverse) { 564 unsigned long tmp; 565 tmp = gc_val.foreground; 566 gc_val.foreground = gc_val.background; 567 gc_val.background = tmp; 568 } 569 } else { 570 gc_val.background = XGetPixel(out_image, 0, 0); 571 gc_val.foreground = 0; 572 } 573 574 attributes.background_pixel = gc_val.background; 575 attributes.border_pixel = gc_val.background; 576 if (scale) 577 attributes.bit_gravity = ForgetGravity; 578 else 579 attributes.bit_gravity = NorthWestGravity; 580 attributes.event_mask = ButtonPressMask|ButtonReleaseMask|KeyPressMask| 581 ExposureMask; 582 if (scale) 583 attributes.event_mask |= StructureNotifyMask; 584 attributes.colormap = colormap; 585 586 hints.x = header.window_x; 587 hints.y = header.window_y; 588 hints.width = out_image->width; 589 hints.height = out_image->height; 590 if (geom) 591 gbits = XParseGeometry(geom, &hints.x, &hints.y, 592 (unsigned int *)&hints.width, 593 (unsigned int *)&hints.height); 594 hints.flags = ((gbits & (XValue|YValue)) ? USPosition : 0) | 595 ((gbits & (HeightValue|WidthValue)) ? USSize : PSize); 596 if (!scale) { 597 hints.flags |= PMaxSize; 598 hints.max_width = (hints.width > out_image->width) ? 599 hints.width : out_image->width; 600 hints.max_height = (hints.height > out_image->height) ? 601 hints.height : out_image->height; 602 } 603 if ((gbits & XValue) && (gbits & XNegative)) 604 hints.x += DisplayWidth(dpy, screen) - hints.width; 605 if ((gbits & YValue) && (gbits & YNegative)) 606 hints.y += DisplayHeight(dpy, screen) - hints.height; 607 608 /* create the image window */ 609 image_win = XCreateWindow(dpy, RootWindow(dpy, screen), 610 hints.x, hints.y, hints.width, hints.height, 611 0, vinfo.depth, InputOutput, vinfo.visual, 612 CWBorderPixel|CWBackPixel|CWColormap|CWEventMask|CWBitGravity, 613 &attributes); 614 win_width = hints.width; 615 win_height = hints.height; 616 617 /* Setup for ICCCM delete window. */ 618 wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); 619 wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 620 (void) XSetWMProtocols (dpy, image_win, &wm_delete_window, 1); 621 622 textprop.value = (unsigned char *) win_name; 623 textprop.encoding = XA_STRING; 624 textprop.format = 8; 625 textprop.nitems = strlen(win_name); 626 class_hint.res_name = (char *)NULL; 627 class_hint.res_class = "Xwud"; 628 /* set standard properties */ 629 XSetWMProperties(dpy, image_win, &textprop, (XTextProperty *)NULL, 630 argv, argc, &hints, (XWMHints *)NULL, &class_hint); 631 632 /* map the image window */ 633 XMapWindow(dpy, image_win); 634 635 gc = XCreateGC (dpy, image_win, GCForeground|GCBackground, &gc_val); 636 637 while (1) { 638 /* wait on mouse input event to terminate */ 639 XNextEvent(dpy, &event); 640 switch(event.type) { 641 case ClientMessage: 642 if (event.xclient.message_type == wm_protocols && 643 event.xclient.data.l[0] == wm_delete_window) { 644 XCloseDisplay(dpy); 645 exit(0); /* ICCCM delete window */ 646 } 647 break; 648 case ButtonPress: 649 break; 650 case ButtonRelease: 651 if (onclick) { 652 XCloseDisplay(dpy); 653 exit(0); 654 } 655 break; 656 case KeyPress: 657 i = XLookupString(&event.xkey, &c, 1, NULL, NULL); 658 if ((i == 1) && ((c == 'q') || (c == 'Q') || (c == '\03'))) { 659 XCloseDisplay(dpy); 660 exit(0); 661 } 662 break; 663 case ConfigureNotify: 664 win_width = event.xconfigure.width; 665 win_height = event.xconfigure.height; 666 break; 667 case Expose: 668 if (scale) 669 putScaledImage(dpy, image_win, gc, out_image, 670 expose->x, expose->y, 671 expose->width, expose->height, 672 win_width, win_height); 673 else if ((expose->x < out_image->width) && 674 (expose->y < out_image->height)) { 675 if ((out_image->width - expose->x) < expose->width) 676 expose->width = out_image->width - expose->x; 677 if ((out_image->height - expose->y) < expose->height) 678 expose->height = out_image->height - expose->y; 679 putImage(dpy, image_win, gc, out_image, 680 expose->x, expose->y, 681 expose->width, expose->height); 682 } 683 break; 684 } 685 } 686 exit(0); 687} 688 689static void 690putImage(Display *dpy, Window image_win, GC gc, XImage *out_image, 691 int x, int y, int w, int h) 692{ 693#define SPLIT_SIZE 100 694 int t_x, t_y, t_w, t_h; 695 if (split) { 696 for (t_y = y; t_y < y + h; t_y += t_h) { 697 t_h = SPLIT_SIZE; 698 if (t_y + t_h > y + h) 699 t_h = y + h - t_y; 700 for (t_x = x; t_x < x + w; t_x += t_w) { 701 t_w = SPLIT_SIZE; 702 if (t_x + t_w > x + w) 703 t_w = x + w - t_x; 704 XPutImage(dpy, image_win, gc, out_image, 705 t_x, t_y, t_x, t_y, t_w, t_h); 706 } 707 } 708 } else { 709 XPutImage (dpy, image_win, gc, out_image, x, y, x, y, w, h); 710 } 711} 712 713typedef short Position; 714typedef unsigned short Dimension; 715typedef unsigned long Pixel; 716 717#define roundint(x) (int)((x) + 0.5) 718 719typedef struct { 720 Position *x, *y; 721 Dimension *width, *height; 722} Table; 723 724static void 725putScaledImage(Display *display, Drawable d, GC gc, XImage *src_image, 726 int exp_x, int exp_y, 727 unsigned int exp_width, unsigned int exp_height, 728 unsigned int dest_width, unsigned dest_height) 729{ 730 XImage *dest_image; 731 Position x, y, min_y, max_y, exp_max_y, src_x, src_max_x, src_y; 732 Dimension w, h, strip_height; 733 Table table; 734 Pixel pixel; 735 double ratio_x, ratio_y; 736 Bool fast8; 737 738 if (dest_width == src_image->width && dest_height == src_image->height) { 739 /* same for x and y, just send it out */ 740 XPutImage(display, d, gc, src_image, exp_x, exp_y, 741 exp_x, exp_y, exp_width, exp_height); 742 return; 743 } 744 745 ratio_x = (double)dest_width / (double)src_image->width; 746 ratio_y = (double)dest_height / (double)src_image->height; 747 748 src_x = exp_x / ratio_x; 749 if (src_x >= src_image->width) 750 src_x = src_image->width - 1; 751 src_y = exp_y / ratio_y; 752 if (src_y >= src_image->height) 753 src_y = src_image->height - 1; 754 exp_max_y = exp_y + exp_height; 755 src_max_x = roundint((exp_x + exp_width) / ratio_x) + 1; 756 if (src_max_x > src_image->width) 757 src_max_x = src_image->width; 758 759 strip_height = 65536 / roundint(ratio_x * src_image->bytes_per_line); 760 if (strip_height == 0) 761 strip_height = 1; 762 if (strip_height > exp_height) 763 strip_height = exp_height; 764 765 h = strip_height + roundint(ratio_y); 766 dest_image = XCreateImage(display, 767 DefaultVisualOfScreen( 768 DefaultScreenOfDisplay(display)), 769 src_image->depth, src_image->format, 770 0, NULL, 771 dest_width, h, 772 src_image->bitmap_pad, 0); 773 dest_image->data = malloc(dest_image->bytes_per_line * h); 774 fast8 = (src_image->depth == 8 && src_image->bits_per_pixel == 8 && 775 dest_image->bits_per_pixel == 8 && src_image->format == ZPixmap); 776 777 table.x = (Position *) malloc(sizeof(Position) * (src_image->width + 1)); 778 table.y = (Position *) malloc(sizeof(Position) * (src_image->height + 1)); 779 table.width = (Dimension *) malloc(sizeof(Dimension) * src_image->width); 780 table.height = (Dimension *) malloc(sizeof(Dimension)*src_image->height); 781 782 table.x[0] = 0; 783 for (x = 1; x <= src_image->width; x++) { 784 table.x[x] = roundint(ratio_x * x); 785 table.width[x - 1] = table.x[x] - table.x[x - 1]; 786 } 787 788 table.y[0] = 0; 789 for (y = 1; y <= src_image->height; y++) { 790 table.y[y] = roundint(ratio_y * y); 791 table.height[y - 1] = table.y[y] - table.y[y - 1]; 792 } 793 794 for (min_y = table.y[src_y]; min_y < exp_max_y; min_y = table.y[y]) { 795 max_y = min_y + strip_height; 796 if (max_y > exp_max_y) { 797 strip_height = exp_max_y - min_y; 798 max_y = exp_max_y; 799 } 800 for (y = src_y; table.y[y] < max_y; y++) { 801 if (table.y[y] < min_y) 802 continue; 803 if (fast8) { 804 for (x = src_x; x < src_max_x; x++) { 805 pixel = ((unsigned char *)src_image->data) 806 [y * src_image->bytes_per_line + x]; 807 for (h = 0; h < table.height[y]; h++) { 808 memset(dest_image->data + 809 (table.y[y] + h - min_y) * 810 dest_image->bytes_per_line + table.x[x], 811 pixel, table.width[x]); 812 } 813 } 814 } else { 815 for (x = src_x; x < src_max_x; x++) { 816 pixel = XGetPixel(src_image, x, y); 817 for (h = 0; h < table.height[y]; h++) { 818 for (w = 0; w < table.width[x]; w++) 819 XPutPixel(dest_image, 820 table.x[x] + w, 821 table.y[y] + h - min_y, 822 pixel); 823 } 824 } 825 } 826 } 827 XPutImage(display, d, gc, dest_image, exp_x, 0, 828 exp_x, min_y, exp_width, table.y[y] - min_y); 829 if (y >= src_image->height) 830 break; 831 } 832 833 XFree((char *)table.x); 834 XFree((char *)table.y); 835 XFree((char *)table.width); 836 XFree((char *)table.height); 837 838 XDestroyImage(dest_image); 839} 840 841static void 842Latin1Upper(char *s) 843{ 844 unsigned char *str = (unsigned char *)s; 845 unsigned char c; 846 847 for (; (c = *str); str++) 848 { 849 if ((c >= XK_a) && (c <= XK_z)) 850 *str = c - (XK_a - XK_A); 851 else if ((c >= XK_agrave) && (c <= XK_odiaeresis)) 852 *str = c - (XK_agrave - XK_Agrave); 853 else if ((c >= XK_oslash) && (c <= XK_thorn)) 854 *str = c - (XK_oslash - XK_Ooblique); 855 } 856} 857 858static void 859Extract_Plane(XImage *in_image, XImage *out_image, int plane) 860{ 861 register int x, y; 862 863 for (y = 0; y < in_image->height; y++) 864 for (x = 0; x < in_image->width; x++) 865 XPutPixel(out_image, x, y, 866 (XGetPixel(in_image, x, y) >> plane) & 1); 867} 868 869static int 870EffectiveSize(XVisualInfo *vinfo) 871{ 872 if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor)) 873 return (vinfo->red_mask | vinfo->green_mask | vinfo->blue_mask) + 1; 874 else 875 return vinfo->colormap_size; 876} 877 878static int 879VisualRank(int class) 880{ 881 switch (class) { 882 case PseudoColor: 883 return 5; 884 case TrueColor: 885 return 4; 886 case DirectColor: 887 return 3; 888 case StaticColor: 889 return 2; 890 case GrayScale: 891 return 1; 892 case StaticGray: 893 return 0; 894 } 895 /* NOTREACHED */ 896 return -1; 897} 898 899static int 900IsGray(Display *dpy, XStandardColormap *stdmap) 901{ 902 XColor color; 903 904 color.pixel = stdmap->base_pixel + (stdmap->red_max * stdmap->red_mult); 905 XQueryColor(dpy, stdmap->colormap, &color); 906 return (color.green || color.blue); 907} 908 909static void 910Do_StdGray(Display *dpy, XStandardColormap *stdmap, 911 int ncolors, XColor *colors, XImage *in_image, XImage *out_image) 912{ 913 register int i, x, y; 914 register XColor *color; 915 unsigned lim; 916 917 lim = stdmap->red_max + 1; 918 for (i = 0, color = colors; i < ncolors; i++, color++) 919 color->pixel = stdmap->base_pixel + 920 (((((int)(30L * color->red + 921 59L * color->green + 922 11L * color->blue) / 100) 923 * lim) >> 16) * stdmap->red_mult); 924 for (y = 0; y < in_image->height; y++) { 925 for (x = 0; x < in_image->width; x++) { 926 XPutPixel(out_image, x, y, 927 colors[XGetPixel(in_image, x, y)].pixel); 928 } 929 } 930} 931 932#define MapVal(val,lim,mult) ((((val * lim) + 32768) / 65535) * mult) 933 934static void 935Do_StdCol(Display *dpy, XStandardColormap *stdmap, 936 int ncolors, XColor *colors, XImage *in_image, XImage *out_image) 937{ 938 register int i, x, y; 939 register XColor *color; 940 unsigned limr, limg, limb; 941 942 limr = stdmap->red_max; 943 limg = stdmap->green_max; 944 limb = stdmap->blue_max; 945 for (i = 0, color = colors; i < ncolors; i++, color++) 946 color->pixel = stdmap->base_pixel + 947 MapVal(color->red, limr, stdmap->red_mult) + 948 MapVal(color->green, limg, stdmap->green_mult) + 949 MapVal(color->blue, limb, stdmap->blue_mult); 950 for (y = 0; y < in_image->height; y++) { 951 for (x = 0; x < in_image->width; x++) { 952 XPutPixel(out_image, x, y, 953 colors[XGetPixel(in_image, x, y)].pixel); 954 } 955 } 956} 957 958static Colormap 959CopyColormapAndFree(Display *dpy, Colormap colormap) 960{ 961 if (colormap == DefaultColormap(dpy, DefaultScreen(dpy))) 962 return XCopyColormapAndFree(dpy, colormap); 963 Error("Visual type is not large enough to hold all colors of the image."); 964 /*NOTREACHED*/ 965 return (Colormap)0; 966} 967 968static void 969Do_Pseudo(Display *dpy, Colormap *colormap, 970 int ncolors, XColor *colors, XImage *in_image, XImage *out_image) 971{ 972 register int i, x, y; 973 register XColor *color; 974 975 for (i = 0; i < ncolors; i++) 976 colors[i].flags = 0; 977 for (y = 0; y < in_image->height; y++) { 978 for (x = 0; x < in_image->width; x++) { 979 color = &colors[XGetPixel(in_image, x, y)]; 980 if (!color->flags) { 981 color->flags = DoRed | DoGreen | DoBlue; 982 if (!XAllocColor(dpy, *colormap, color)) { 983 *colormap = CopyColormapAndFree(dpy, *colormap); 984 XAllocColor(dpy, *colormap, color); 985 } 986 } 987 XPutPixel(out_image, x, y, color->pixel); 988 } 989 } 990} 991 992static void 993Do_Direct(Display *dpy, XWDFileHeader *header, Colormap *colormap, 994 int ncolors, XColor *colors, XImage *in_image, XImage *out_image, 995 XVisualInfo *vinfo) 996{ 997 register int x, y; 998 XColor color; 999 unsigned long rmask, gmask, bmask; 1000 unsigned long ormask, ogmask, obmask; 1001 unsigned long rshift = 0, gshift = 0, bshift = 0; 1002 unsigned long orshift = 0, ogshift = 0, obshift = 0; 1003 int i; 1004 unsigned long pix, xpix; 1005 unsigned long *pixels, *rpixels; 1006 1007 rmask = header->red_mask; 1008 while (!(rmask & 1)) { 1009 rmask >>= 1; 1010 rshift++; 1011 } 1012 gmask = header->green_mask; 1013 while (!(gmask & 1)) { 1014 gmask >>= 1; 1015 gshift++; 1016 } 1017 bmask = header->blue_mask; 1018 while (!(bmask & 1)) { 1019 bmask >>= 1; 1020 bshift++; 1021 } 1022 if (in_image->depth <= 12) { 1023 pix = 1 << in_image->depth; 1024 pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix); 1025 if (pixels == NULL) 1026 Error("Unable to allocate memory for pixel conversion"); 1027 for (i = 0; i < pix; i++) 1028 pixels[i] = ~0L; 1029 color.flags = DoRed | DoGreen | DoBlue; 1030 for (y = 0; y < in_image->height; y++) { 1031 for (x = 0; x < in_image->width; x++) { 1032 pix = XGetPixel(in_image, x, y); 1033 if ((color.pixel = pixels[pix]) == ~0L) { 1034 color.red = (pix >> rshift) & rmask; 1035 color.green = (pix >> gshift) & gmask; 1036 color.blue = (pix >> bshift) & bmask; 1037 if (ncolors) { 1038 color.red = colors[color.red].red; 1039 color.green = colors[color.green].green; 1040 color.blue = colors[color.blue].blue; 1041 } else { 1042 color.red = (((unsigned long)color.red * 65535) / 1043 rmask); 1044 color.green = (((unsigned long)color.green * 65535) / 1045 gmask); 1046 color.blue = (((unsigned long)color.blue * 65535) / 1047 bmask); 1048 } 1049 if (!XAllocColor(dpy, *colormap, &color)) { 1050 *colormap = CopyColormapAndFree(dpy, *colormap); 1051 XAllocColor(dpy, *colormap, &color); 1052 } 1053 pixels[pix] = color.pixel; 1054 } 1055 XPutPixel(out_image, x, y, color.pixel); 1056 } 1057 } 1058 free(pixels); 1059 } else if (header->visual_class == TrueColor && 1060 vinfo->class == TrueColor) { 1061 ormask = vinfo->red_mask; 1062 while (!(ormask & 1)) { 1063 ormask >>= 1; 1064 orshift++; 1065 } 1066 ogmask = vinfo->green_mask; 1067 while (!(ogmask & 1)) { 1068 ogmask >>= 1; 1069 ogshift++; 1070 } 1071 obmask = vinfo->blue_mask; 1072 while (!(obmask & 1)) { 1073 obmask >>= 1; 1074 obshift++; 1075 } 1076 for (y = 0; y < in_image->height; y++) { 1077 for (x = 0; x < in_image->width; x++) { 1078 pix = XGetPixel(in_image, x, y); 1079 xpix = (((((pix >> rshift) & rmask) * 65535 / rmask) 1080 * ormask / 65535) << orshift) | 1081 (((((pix >> gshift) & gmask) * 65535 / gmask) 1082 * ogmask / 65535) << ogshift) | 1083 (((((pix >> bshift) & bmask) * 65535 / bmask) 1084 * obmask / 65535) << obshift); 1085 XPutPixel(out_image, x, y, xpix); 1086 } 1087 } 1088 } else { 1089 if (header->visual_class == TrueColor) 1090 ncolors = 0; 1091 pix = 1 << 12; 1092 pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix); 1093 rpixels = (unsigned long *)malloc(sizeof(unsigned long) * pix); 1094 if ((pixels == NULL) || (rpixels == NULL)) 1095 Error("Unable to allocate memory for pixel conversion"); 1096 for (i = 0; i < pix; i++) { 1097 pixels[i] = ~0L; 1098 rpixels[i] = ~0L; 1099 } 1100 color.flags = DoRed | DoGreen | DoBlue; 1101 for (y = 0; y < in_image->height; y++) { 1102 for (x = 0; x < in_image->width; x++) { 1103 pix = XGetPixel(in_image, x, y); 1104 xpix = ((pix >> 12) ^ pix) & ((1 << 12) - 1); 1105 if (((color.pixel = pixels[xpix]) == ~0L) || 1106 (rpixels[xpix] != pix)) { 1107 color.red = (pix >> rshift) & rmask; 1108 color.green = (pix >> gshift) & gmask; 1109 color.blue = (pix >> bshift) & bmask; 1110 if (ncolors) { 1111 color.red = colors[color.red].red; 1112 color.green = colors[color.green].green; 1113 color.blue = colors[color.blue].blue; 1114 } else { 1115 color.red = (((unsigned long)color.red * 65535) / 1116 rmask); 1117 color.green = (((unsigned long)color.green * 65535) / 1118 gmask); 1119 color.blue = (((unsigned long)color.blue * 65535) / 1120 bmask); 1121 } 1122 if (!XAllocColor(dpy, *colormap, &color)) { 1123 *colormap = CopyColormapAndFree(dpy, *colormap); 1124 XAllocColor(dpy, *colormap, &color); 1125 } 1126 pixels[xpix] = color.pixel; 1127 rpixels[xpix] = pix; 1128 } 1129 XPutPixel(out_image, x, y, color.pixel); 1130 } 1131 } 1132 free(pixels); 1133 free(rpixels); 1134 } 1135} 1136 1137static unsigned int 1138Image_Size(XImage *image) 1139{ 1140 if (image->format != ZPixmap) 1141 return(image->bytes_per_line * image->height * image->depth); 1142 1143 return((unsigned)image->bytes_per_line * image->height); 1144} 1145 1146static void 1147Error(char *string) 1148{ 1149 fprintf(stderr, "xwud: Error => %s\n", string); 1150 if (errno != 0) { 1151 perror("xwud"); 1152 fprintf(stderr, "\n"); 1153 } 1154 exit(1); 1155} 1156 1157static void 1158_swapshort(char *bp, unsigned int n) 1159{ 1160 register char c; 1161 register char *ep = bp + n; 1162 1163 while (bp < ep) { 1164 c = *bp; 1165 *bp = *(bp + 1); 1166 bp++; 1167 *bp++ = c; 1168 } 1169} 1170 1171static void 1172_swaplong(char *bp, unsigned int n) 1173{ 1174 register char c; 1175 register char *ep = bp + n; 1176 register char *sp; 1177 1178 while (bp < ep) { 1179 sp = bp + 3; 1180 c = *sp; 1181 *sp = *bp; 1182 *bp++ = c; 1183 sp = bp + 1; 1184 c = *sp; 1185 *sp = *bp; 1186 *bp++ = c; 1187 bp += 2; 1188 } 1189} 1190 1191static void 1192DumpHeader(const XWDFileHeader *header, const char *win_name) 1193{ 1194 printf("window name: %s\n", win_name); 1195 printf("sizeof(XWDheader): %d\n", (int)sizeof(*header)); 1196 printf("header size: %d\n", (int)header->header_size); 1197 printf("file version: %d\n", (int)header->file_version); 1198 printf("pixmap format: %d\n", (int)header->pixmap_format); 1199 printf("pixmap depth: %d\n", (int)header->pixmap_depth); 1200 printf("pixmap width: %d\n", (int)header->pixmap_width); 1201 printf("pixmap height: %d\n", (int)header->pixmap_height); 1202 printf("x offset: %d\n", (int)header->xoffset); 1203 printf("byte order: %d\n", (int)header->byte_order); 1204 printf("bitmap unit: %d\n", (int)header->bitmap_unit); 1205 printf("bitmap bit order: %d\n", (int)header->bitmap_bit_order); 1206 printf("bitmap pad: %d\n", (int)header->bitmap_pad); 1207 printf("bits per pixel: %d\n", (int)header->bits_per_pixel); 1208 printf("bytes per line: %d\n", (int)header->bytes_per_line); 1209 printf("visual class: %d\n", (int)header->visual_class); 1210 printf("red mask: %d\n", (int)header->red_mask); 1211 printf("green mask: %d\n", (int)header->green_mask); 1212 printf("blue mask: %d\n", (int)header->blue_mask); 1213 printf("bits per rgb: %d\n", (int)header->bits_per_rgb); 1214 printf("colormap entries: %d\n", (int)header->colormap_entries); 1215 printf("num colors: %d\n", (int)header->ncolors); 1216 printf("window width: %d\n", (int)header->window_width); 1217 printf("window height: %d\n", (int)header->window_height); 1218 printf("window x: %d\n", (int)header->window_x); 1219 printf("window y: %d\n", (int)header->window_y); 1220 printf("border width: %d\n", (int)header->window_bdrwidth); 1221} 1222 1223