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