xwud.c revision 7c5f6000
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 45static Atom wm_protocols; 46static Atom wm_delete_window; 47static int split; 48 49static char *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_size < 1) 278 Error("win_name_size"); 279 if((win_name = malloc((unsigned) win_name_size + 6)) == NULL) 280 Error("Can't malloc window name storage."); 281 strcpy(win_name, "xwud: "); 282 283 /* read in window name */ 284 if(!Read(win_name + 6, sizeof(char), win_name_size, in_file)) 285 Error("Unable to read window name from dump file."); 286 (win_name + 6)[win_name_size - 1] = 0; 287 288 if (dump_header) { 289 DumpHeader(&header, win_name); 290 exit(0); 291 } 292 293 /* initialize the input image */ 294 295 in_image = &in_image_struct; 296 in_image->depth = header.pixmap_depth; 297 in_image->format = header.pixmap_format; 298 in_image->xoffset = header.xoffset; 299 in_image->data = NULL; 300 in_image->width = header.pixmap_width; 301 in_image->height = header.pixmap_height; 302 in_image->bitmap_pad = header.bitmap_pad; 303 in_image->bytes_per_line = header.bytes_per_line; 304 in_image->byte_order = header.byte_order; 305 in_image->bitmap_unit = header.bitmap_unit; 306 in_image->bitmap_bit_order = header.bitmap_bit_order; 307 in_image->bits_per_pixel = header.bits_per_pixel; 308 in_image->red_mask = header.red_mask; 309 in_image->green_mask = header.green_mask; 310 in_image->blue_mask = header.blue_mask; 311 if (!XInitImage(in_image)) 312 Error("Invalid input image header data."); 313 314 /* read in the color map buffer */ 315 if((ncolors = header.ncolors)) { 316 colors = (XColor *)malloc((unsigned) ncolors * sizeof(XColor)); 317 if (!colors) 318 Error("Can't malloc color table"); 319 for (i = 0; i < ncolors; i++) { 320 if(!Read((char *) &xwdcolor, SIZEOF(XWDColor), 1, in_file)) 321 Error("Unable to read color map from dump file."); 322 colors[i].pixel = xwdcolor.pixel; 323 colors[i].red = xwdcolor.red; 324 colors[i].green = xwdcolor.green; 325 colors[i].blue = xwdcolor.blue; 326 colors[i].flags = xwdcolor.flags; 327 } 328 if (*(char *) &swaptest) { 329 for (i = 0; i < ncolors; i++) { 330 _swaplong((char *) &colors[i].pixel, sizeof(long)); 331 _swapshort((char *) &colors[i].red, 3 * sizeof(short)); 332 } 333 } 334 } 335 else 336 /* no color map exists, turn on the raw option */ 337 rawbits = True; 338 339 /* alloc the pixel buffer */ 340 buffer_size = Image_Size(in_image); 341 if((buffer = malloc(buffer_size)) == NULL) 342 Error("Can't malloc data buffer."); 343 344 /* read in the image data */ 345 if (!Read(buffer, sizeof(char), (int)buffer_size, in_file)) 346 Error("Unable to read pixmap from dump file."); 347 348 /* close the input file */ 349 (void) fclose(in_file); 350 351 if (plane >= in_image->depth) 352 Error("plane number exceeds image depth"); 353 if ((in_image->format == XYPixmap) && (plane >= 0)) { 354 buffer += in_image->bytes_per_line * in_image->height * 355 (in_image->depth - (plane + 1)); 356 in_image->depth = 1; 357 ncolors = 0; 358 } 359 if (in_image->bits_per_pixel == 1 && in_image->depth == 1) { 360 in_image->format = XYBitmap; 361 newmap = False; 362 rawbits = True; 363 } 364 in_image->data = buffer; 365 366 if (std) { 367 map_name = malloc(strlen(std) + 9); 368 strcpy(map_name, "RGB_"); 369 strcat(map_name, std); 370 strcat(map_name, "_MAP"); 371 Latin1Upper(map_name); 372 map_prop = XInternAtom(dpy, map_name, True); 373 if (!map_prop || !XGetRGBColormaps(dpy, RootWindow(dpy, screen), 374 &stdmaps, &stdcnt, map_prop)) 375 Error("specified standard colormap does not exist"); 376 } 377 vinfo.screen = screen; 378 mask = VisualScreenMask; 379 if (vis) 380 { 381 char *vt; 382 vt = malloc(strlen(vis) + 1); 383 strcpy(vt, vis); 384 Latin1Upper(vt); 385 if (strcmp(vt, "STATICGRAY") == 0) { 386 vinfo.class = StaticGray; 387 mask |= VisualClassMask; 388 } else if (strcmp(vt, "GRAYSCALE") == 0) { 389 vinfo.class = GrayScale; 390 mask |= VisualClassMask; 391 } else if (strcmp(vt, "STATICCOLOR") == 0) { 392 vinfo.class = StaticColor; 393 mask |= VisualClassMask; 394 } else if (strcmp(vt, "PSEUDOCOLOR") == 0) { 395 vinfo.class = PseudoColor; 396 mask |= VisualClassMask; 397 } else if (strcmp(vt, "DIRECTCOLOR") == 0) { 398 vinfo.class = DirectColor; 399 mask |= VisualClassMask; 400 } else if (strcmp(vt, "TRUECOLOR") == 0) { 401 vinfo.class = TrueColor; 402 mask |= VisualClassMask; 403 } else if (strcmp(vt, "MATCH") == 0) { 404 vinfo.class = header.visual_class; 405 mask |= VisualClassMask; 406 } else if (strcmp(vt, "DEFAULT") == 0) { 407 vinfo.visualid= XVisualIDFromVisual(DefaultVisual(dpy, screen)); 408 mask |= VisualIDMask; 409 } else { 410 vinfo.visualid = 0; 411 mask |= VisualIDMask; 412 sscanf(vis, "0x%lx", &vinfo.visualid); 413 if (!vinfo.visualid) 414 sscanf(vis, "%lu", &vinfo.visualid); 415 if (!vinfo.visualid) 416 Error("invalid visual specifier"); 417 } 418 } 419 if (rawbits && (in_image->depth > 1) && (plane < 0)) { 420 vinfo.depth = in_image->depth; 421 mask |= VisualDepthMask; 422 } 423 vinfos = XGetVisualInfo(dpy, mask, &vinfo, &count); 424 if (count == 0) 425 Error("no matching visual found"); 426 427 /* find a workable visual */ 428 if (std) { 429 stdmap = &stdmaps[0]; 430 if (mask & VisualIDMask) { 431 for (i = 0; i < stdcnt; i++) { 432 if (stdmaps[i].visualid == vinfo.visualid) { 433 stdmap = &stdmaps[i]; 434 break; 435 } 436 } 437 if (stdmap->visualid != vinfo.visualid) 438 Error("no standard colormap matching specified visual"); 439 } 440 for (i = 0; i < count; i++) { 441 if (stdmap->visualid == vinfos[i].visualid) { 442 vinfo = vinfos[i]; 443 break; 444 } 445 } 446 } else if ((in_image->depth == 1) || 447 ((in_image->format == ZPixmap) && (plane >= 0)) || 448 rawbits) { 449 vinfo = vinfos[0]; 450 if (!(mask & VisualIDMask)) { 451 for (i = 0; i < count; i++) { 452 if ((vinfos[i].visualid == 453 XVisualIDFromVisual(DefaultVisual(dpy, screen))) && 454 (vinfos[i].depth == DefaultDepth(dpy, screen))) { 455 vinfo = vinfos[i]; 456 break; 457 } 458 } 459 } 460 } else { 461 /* get best visual */ 462 vinfo = vinfos[0]; 463 for (i = 0; i < count; i++) { 464 int z1, z2; 465 z2 = EffectiveSize(&vinfos[i]); 466 if ((z2 >= ncolors) && 467 (vinfos[i].depth == in_image->depth) && 468 (vinfos[i].class == header.visual_class)) 469 { 470 vinfo = vinfos[i]; 471 break; 472 } 473 z1 = EffectiveSize(&vinfo); 474 if ((z2 > z1) || 475 ((z2 == z1) && 476 (VisualRank(vinfos[i].class) >= VisualRank(vinfo.class)))) 477 vinfo = vinfos[i]; 478 } 479 if ((newmap || (vinfo.visual != DefaultVisual(dpy, screen))) && 480 (vinfo.class != StaticGray) && 481 (vinfo.class != StaticColor) && 482 (vinfo.class == header.visual_class) && 483 (vinfo.depth == in_image->depth) && 484 ((vinfo.class == PseudoColor) || 485 (vinfo.class == GrayScale) || 486 ((vinfo.red_mask == header.red_mask) && 487 (vinfo.green_mask == header.green_mask) && 488 (vinfo.blue_mask == header.blue_mask)))) { 489 rawbits = True; 490 newmap = True; 491 } 492 } 493 494 /* get the appropriate colormap */ 495 if (newmap && (vinfo.class & 1) && 496 (vinfo.depth == in_image->depth) && 497 (vinfo.class == header.visual_class) && 498 (vinfo.colormap_size >= ncolors) && 499 (vinfo.red_mask == header.red_mask) && 500 (vinfo.green_mask == header.green_mask) && 501 (vinfo.blue_mask == header.blue_mask)) { 502 colormap = XCreateColormap(dpy, RootWindow(dpy, screen), vinfo.visual, 503 AllocAll); 504 if (ncolors) { 505 for (i = 0; i < ncolors; i++) 506 colors[i].flags = DoRed|DoGreen|DoBlue; 507 XStoreColors(dpy, colormap, colors, ncolors); 508 } 509 } else if (std) { 510 colormap = stdmap->colormap; 511 } else { 512 if (!newmap && (vinfo.visual == DefaultVisual(dpy, screen))) 513 colormap = DefaultColormap(dpy, screen); 514 else 515 colormap = XCreateColormap(dpy, RootWindow(dpy, screen), 516 vinfo.visual, AllocNone); 517 newmap = False; 518 } 519 520 /* create the output image */ 521 if ((in_image->format == ZPixmap) && (plane >= 0)) { 522 out_image = XCreateImage(dpy, vinfo.visual, 1, 523 XYBitmap, 0, NULL, 524 in_image->width, in_image->height, 525 XBitmapPad(dpy), 0); 526 out_image->data = malloc(Image_Size(out_image)); 527 Extract_Plane(in_image, out_image, plane); 528 ncolors = 0; 529 } else if (rawbits || newmap) { 530 out_image = in_image; 531 } else { 532 out_image = XCreateImage(dpy, vinfo.visual, vinfo.depth, 533 (vinfo.depth == 1) ? XYBitmap : 534 in_image->format, 535 in_image->xoffset, NULL, 536 in_image->width, in_image->height, 537 XBitmapPad(dpy), 0); 538 out_image->data = malloc(Image_Size(out_image)); 539 if (std) { 540 if (!stdmap->green_max && !stdmap->blue_max && IsGray(dpy, stdmap)) 541 Do_StdGray(dpy, stdmap, ncolors, colors, in_image, out_image); 542 else 543 Do_StdCol(dpy, stdmap, ncolors, colors, in_image, out_image); 544 } else if ((header.visual_class == TrueColor) || 545 (header.visual_class == DirectColor)) 546 Do_Direct(dpy, &header, &colormap, ncolors, colors, 547 in_image, out_image, &vinfo); 548 else 549 Do_Pseudo(dpy, &colormap, ncolors, colors, in_image, out_image); 550 } 551 552 if (out_image->depth == 1) { 553 if (fgname && 554 XAllocNamedColor(dpy, colormap, fgname, &color, &igncolor)) 555 gc_val.foreground = color.pixel; 556 else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[1])) 557 gc_val.foreground = colors[1].pixel; 558 else 559 gc_val.foreground = BlackPixel (dpy, screen); 560 if (bgname && 561 XAllocNamedColor(dpy, colormap, bgname, &color, &igncolor)) 562 gc_val.background = color.pixel; 563 else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[0])) 564 gc_val.background = colors[0].pixel; 565 else 566 gc_val.background = WhitePixel (dpy, screen); 567 if (inverse) { 568 unsigned long tmp; 569 tmp = gc_val.foreground; 570 gc_val.foreground = gc_val.background; 571 gc_val.background = tmp; 572 } 573 } else { 574 gc_val.background = XGetPixel(out_image, 0, 0); 575 gc_val.foreground = 0; 576 } 577 578 attributes.background_pixel = gc_val.background; 579 attributes.border_pixel = gc_val.background; 580 if (scale) 581 attributes.bit_gravity = ForgetGravity; 582 else 583 attributes.bit_gravity = NorthWestGravity; 584 attributes.event_mask = ButtonPressMask|ButtonReleaseMask|KeyPressMask| 585 ExposureMask; 586 if (scale) 587 attributes.event_mask |= StructureNotifyMask; 588 attributes.colormap = colormap; 589 590 hints.x = header.window_x; 591 hints.y = header.window_y; 592 hints.width = out_image->width; 593 hints.height = out_image->height; 594 if (geom) 595 gbits = XParseGeometry(geom, &hints.x, &hints.y, 596 (unsigned int *)&hints.width, 597 (unsigned int *)&hints.height); 598 hints.flags = ((gbits & (XValue|YValue)) ? USPosition : 0) | 599 ((gbits & (HeightValue|WidthValue)) ? USSize : PSize); 600 if (!scale) { 601 hints.flags |= PMaxSize; 602 hints.max_width = (hints.width > out_image->width) ? 603 hints.width : out_image->width; 604 hints.max_height = (hints.height > out_image->height) ? 605 hints.height : out_image->height; 606 } 607 if ((gbits & XValue) && (gbits & XNegative)) 608 hints.x += DisplayWidth(dpy, screen) - hints.width; 609 if ((gbits & YValue) && (gbits & YNegative)) 610 hints.y += DisplayHeight(dpy, screen) - hints.height; 611 612 /* create the image window */ 613 image_win = XCreateWindow(dpy, RootWindow(dpy, screen), 614 hints.x, hints.y, hints.width, hints.height, 615 0, vinfo.depth, InputOutput, vinfo.visual, 616 CWBorderPixel|CWBackPixel|CWColormap|CWEventMask|CWBitGravity, 617 &attributes); 618 win_width = hints.width; 619 win_height = hints.height; 620 621 /* Setup for ICCCM delete window. */ 622 wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); 623 wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 624 (void) XSetWMProtocols (dpy, image_win, &wm_delete_window, 1); 625 626 textprop.value = (unsigned char *) win_name; 627 textprop.encoding = XA_STRING; 628 textprop.format = 8; 629 textprop.nitems = strlen(win_name); 630 class_hint.res_name = (char *)NULL; 631 class_hint.res_class = "Xwud"; 632 /* set standard properties */ 633 XSetWMProperties(dpy, image_win, &textprop, (XTextProperty *)NULL, 634 argv, argc, &hints, (XWMHints *)NULL, &class_hint); 635 636 /* map the image window */ 637 XMapWindow(dpy, image_win); 638 639 gc = XCreateGC (dpy, image_win, GCForeground|GCBackground, &gc_val); 640 641 while (1) { 642 /* wait on mouse input event to terminate */ 643 XNextEvent(dpy, &event); 644 switch(event.type) { 645 case ClientMessage: 646 if (event.xclient.message_type == wm_protocols && 647 event.xclient.data.l[0] == wm_delete_window) { 648 XCloseDisplay(dpy); 649 exit(0); /* ICCCM delete window */ 650 } 651 break; 652 case ButtonPress: 653 break; 654 case ButtonRelease: 655 if (onclick) { 656 XCloseDisplay(dpy); 657 exit(0); 658 } 659 break; 660 case KeyPress: 661 i = XLookupString(&event.xkey, &c, 1, NULL, NULL); 662 if ((i == 1) && ((c == 'q') || (c == 'Q') || (c == '\03'))) { 663 XCloseDisplay(dpy); 664 exit(0); 665 } 666 break; 667 case ConfigureNotify: 668 win_width = event.xconfigure.width; 669 win_height = event.xconfigure.height; 670 break; 671 case Expose: 672 if (scale) 673 putScaledImage(dpy, image_win, gc, out_image, 674 expose->x, expose->y, 675 expose->width, expose->height, 676 win_width, win_height); 677 else if ((expose->x < out_image->width) && 678 (expose->y < out_image->height)) { 679 if ((out_image->width - expose->x) < expose->width) 680 expose->width = out_image->width - expose->x; 681 if ((out_image->height - expose->y) < expose->height) 682 expose->height = out_image->height - expose->y; 683 putImage(dpy, image_win, gc, out_image, 684 expose->x, expose->y, 685 expose->width, expose->height); 686 } 687 break; 688 } 689 } 690 exit(0); 691} 692 693static void 694putImage(Display *dpy, Window image_win, GC gc, XImage *out_image, 695 int x, int y, int w, int h) 696{ 697#define SPLIT_SIZE 100 698 int t_x, t_y, t_w, t_h; 699 if (split) { 700 for (t_y = y; t_y < y + h; t_y += t_h) { 701 t_h = SPLIT_SIZE; 702 if (t_y + t_h > y + h) 703 t_h = y + h - t_y; 704 for (t_x = x; t_x < x + w; t_x += t_w) { 705 t_w = SPLIT_SIZE; 706 if (t_x + t_w > x + w) 707 t_w = x + w - t_x; 708 XPutImage(dpy, image_win, gc, out_image, 709 t_x, t_y, t_x, t_y, t_w, t_h); 710 } 711 } 712 } else { 713 XPutImage (dpy, image_win, gc, out_image, x, y, x, y, w, h); 714 } 715} 716 717typedef short Position; 718typedef unsigned short Dimension; 719typedef unsigned long Pixel; 720 721#define roundint(x) (int)((x) + 0.5) 722 723typedef struct { 724 Position *x, *y; 725 Dimension *width, *height; 726} Table; 727 728static void 729putScaledImage(Display *display, Drawable d, GC gc, XImage *src_image, 730 int exp_x, int exp_y, 731 unsigned int exp_width, unsigned int exp_height, 732 unsigned int dest_width, unsigned dest_height) 733{ 734 XImage *dest_image; 735 Position x, y, min_y, max_y, exp_max_y, src_x, src_max_x, src_y; 736 Dimension w, h, strip_height; 737 Table table; 738 Pixel pixel; 739 double ratio_x, ratio_y; 740 Bool fast8; 741 742 if (dest_width == src_image->width && dest_height == src_image->height) { 743 /* same for x and y, just send it out */ 744 XPutImage(display, d, gc, src_image, exp_x, exp_y, 745 exp_x, exp_y, exp_width, exp_height); 746 return; 747 } 748 749 ratio_x = (double)dest_width / (double)src_image->width; 750 ratio_y = (double)dest_height / (double)src_image->height; 751 752 src_x = exp_x / ratio_x; 753 if (src_x >= src_image->width) 754 src_x = src_image->width - 1; 755 src_y = exp_y / ratio_y; 756 if (src_y >= src_image->height) 757 src_y = src_image->height - 1; 758 exp_max_y = exp_y + exp_height; 759 src_max_x = roundint((exp_x + exp_width) / ratio_x) + 1; 760 if (src_max_x > src_image->width) 761 src_max_x = src_image->width; 762 763 strip_height = 65536 / roundint(ratio_x * src_image->bytes_per_line); 764 if (strip_height == 0) 765 strip_height = 1; 766 if (strip_height > exp_height) 767 strip_height = exp_height; 768 769 h = strip_height + roundint(ratio_y); 770 dest_image = XCreateImage(display, 771 DefaultVisualOfScreen( 772 DefaultScreenOfDisplay(display)), 773 src_image->depth, src_image->format, 774 0, NULL, 775 dest_width, h, 776 src_image->bitmap_pad, 0); 777 dest_image->data = malloc(dest_image->bytes_per_line * h); 778 fast8 = (src_image->depth == 8 && src_image->bits_per_pixel == 8 && 779 dest_image->bits_per_pixel == 8 && src_image->format == ZPixmap); 780 781 table.x = (Position *) malloc(sizeof(Position) * (src_image->width + 1)); 782 table.y = (Position *) malloc(sizeof(Position) * (src_image->height + 1)); 783 table.width = (Dimension *) malloc(sizeof(Dimension) * src_image->width); 784 table.height = (Dimension *) malloc(sizeof(Dimension)*src_image->height); 785 786 table.x[0] = 0; 787 for (x = 1; x <= src_image->width; x++) { 788 table.x[x] = roundint(ratio_x * x); 789 table.width[x - 1] = table.x[x] - table.x[x - 1]; 790 } 791 792 table.y[0] = 0; 793 for (y = 1; y <= src_image->height; y++) { 794 table.y[y] = roundint(ratio_y * y); 795 table.height[y - 1] = table.y[y] - table.y[y - 1]; 796 } 797 798 for (min_y = table.y[src_y]; min_y < exp_max_y; min_y = table.y[y]) { 799 max_y = min_y + strip_height; 800 if (max_y > exp_max_y) { 801 strip_height = exp_max_y - min_y; 802 max_y = exp_max_y; 803 } 804 for (y = src_y; table.y[y] < max_y; y++) { 805 if (table.y[y] < min_y) 806 continue; 807 if (fast8) { 808 for (x = src_x; x < src_max_x; x++) { 809 pixel = ((unsigned char *)src_image->data) 810 [y * src_image->bytes_per_line + x]; 811 for (h = 0; h < table.height[y]; h++) { 812 memset(dest_image->data + 813 (table.y[y] + h - min_y) * 814 dest_image->bytes_per_line + table.x[x], 815 pixel, table.width[x]); 816 } 817 } 818 } else { 819 for (x = src_x; x < src_max_x; x++) { 820 pixel = XGetPixel(src_image, x, y); 821 for (h = 0; h < table.height[y]; h++) { 822 for (w = 0; w < table.width[x]; w++) 823 XPutPixel(dest_image, 824 table.x[x] + w, 825 table.y[y] + h - min_y, 826 pixel); 827 } 828 } 829 } 830 } 831 XPutImage(display, d, gc, dest_image, exp_x, 0, 832 exp_x, min_y, exp_width, table.y[y] - min_y); 833 if (y >= src_image->height) 834 break; 835 } 836 837 XFree((char *)table.x); 838 XFree((char *)table.y); 839 XFree((char *)table.width); 840 XFree((char *)table.height); 841 842 XDestroyImage(dest_image); 843} 844 845static void 846Latin1Upper(char *s) 847{ 848 unsigned char *str = (unsigned char *)s; 849 unsigned char c; 850 851 for (; (c = *str); str++) 852 { 853 if ((c >= XK_a) && (c <= XK_z)) 854 *str = c - (XK_a - XK_A); 855 else if ((c >= XK_agrave) && (c <= XK_odiaeresis)) 856 *str = c - (XK_agrave - XK_Agrave); 857 else if ((c >= XK_oslash) && (c <= XK_thorn)) 858 *str = c - (XK_oslash - XK_Ooblique); 859 } 860} 861 862static void 863Extract_Plane(XImage *in_image, XImage *out_image, int plane) 864{ 865 register int x, y; 866 867 for (y = 0; y < in_image->height; y++) 868 for (x = 0; x < in_image->width; x++) 869 XPutPixel(out_image, x, y, 870 (XGetPixel(in_image, x, y) >> plane) & 1); 871} 872 873static int 874EffectiveSize(XVisualInfo *vinfo) 875{ 876 if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor)) 877 return (vinfo->red_mask | vinfo->green_mask | vinfo->blue_mask) + 1; 878 else 879 return vinfo->colormap_size; 880} 881 882static int 883VisualRank(int class) 884{ 885 switch (class) { 886 case PseudoColor: 887 return 5; 888 case TrueColor: 889 return 4; 890 case DirectColor: 891 return 3; 892 case StaticColor: 893 return 2; 894 case GrayScale: 895 return 1; 896 case StaticGray: 897 return 0; 898 } 899 /* NOTREACHED */ 900 return -1; 901} 902 903static int 904IsGray(Display *dpy, XStandardColormap *stdmap) 905{ 906 XColor color; 907 908 color.pixel = stdmap->base_pixel + (stdmap->red_max * stdmap->red_mult); 909 XQueryColor(dpy, stdmap->colormap, &color); 910 return (color.green || color.blue); 911} 912 913static void 914Do_StdGray(Display *dpy, XStandardColormap *stdmap, 915 int ncolors, XColor *colors, XImage *in_image, XImage *out_image) 916{ 917 register int i, x, y; 918 register XColor *color; 919 unsigned lim; 920 921 lim = stdmap->red_max + 1; 922 for (i = 0, color = colors; i < ncolors; i++, color++) 923 color->pixel = stdmap->base_pixel + 924 (((((int)(30L * color->red + 925 59L * color->green + 926 11L * color->blue) / 100) 927 * lim) >> 16) * stdmap->red_mult); 928 for (y = 0; y < in_image->height; y++) { 929 for (x = 0; x < in_image->width; x++) { 930 XPutPixel(out_image, x, y, 931 colors[XGetPixel(in_image, x, y)].pixel); 932 } 933 } 934} 935 936#define MapVal(val,lim,mult) ((((val * lim) + 32768) / 65535) * mult) 937 938static void 939Do_StdCol(Display *dpy, XStandardColormap *stdmap, 940 int ncolors, XColor *colors, XImage *in_image, XImage *out_image) 941{ 942 register int i, x, y; 943 register XColor *color; 944 unsigned limr, limg, limb; 945 946 limr = stdmap->red_max; 947 limg = stdmap->green_max; 948 limb = stdmap->blue_max; 949 for (i = 0, color = colors; i < ncolors; i++, color++) 950 color->pixel = stdmap->base_pixel + 951 MapVal(color->red, limr, stdmap->red_mult) + 952 MapVal(color->green, limg, stdmap->green_mult) + 953 MapVal(color->blue, limb, stdmap->blue_mult); 954 for (y = 0; y < in_image->height; y++) { 955 for (x = 0; x < in_image->width; x++) { 956 XPutPixel(out_image, x, y, 957 colors[XGetPixel(in_image, x, y)].pixel); 958 } 959 } 960} 961 962static Colormap 963CopyColormapAndFree(Display *dpy, Colormap colormap) 964{ 965 if (colormap == DefaultColormap(dpy, DefaultScreen(dpy))) 966 return XCopyColormapAndFree(dpy, colormap); 967 Error("Visual type is not large enough to hold all colors of the image."); 968 /*NOTREACHED*/ 969 return (Colormap)0; 970} 971 972static void 973Do_Pseudo(Display *dpy, Colormap *colormap, 974 int ncolors, XColor *colors, XImage *in_image, XImage *out_image) 975{ 976 register int i, x, y; 977 register XColor *color; 978 979 for (i = 0; i < ncolors; i++) 980 colors[i].flags = 0; 981 for (y = 0; y < in_image->height; y++) { 982 for (x = 0; x < in_image->width; x++) { 983 color = &colors[XGetPixel(in_image, x, y)]; 984 if (!color->flags) { 985 color->flags = DoRed | DoGreen | DoBlue; 986 if (!XAllocColor(dpy, *colormap, color)) { 987 *colormap = CopyColormapAndFree(dpy, *colormap); 988 XAllocColor(dpy, *colormap, color); 989 } 990 } 991 XPutPixel(out_image, x, y, color->pixel); 992 } 993 } 994} 995 996static void 997Do_Direct(Display *dpy, XWDFileHeader *header, Colormap *colormap, 998 int ncolors, XColor *colors, XImage *in_image, XImage *out_image, 999 XVisualInfo *vinfo) 1000{ 1001 register int x, y; 1002 XColor color; 1003 unsigned long rmask, gmask, bmask; 1004 unsigned long ormask, ogmask, obmask; 1005 unsigned long rshift = 0, gshift = 0, bshift = 0; 1006 unsigned long orshift = 0, ogshift = 0, obshift = 0; 1007 int i; 1008 unsigned long pix, xpix; 1009 unsigned long *pixels, *rpixels; 1010 1011 rmask = header->red_mask; 1012 while (!(rmask & 1)) { 1013 rmask >>= 1; 1014 rshift++; 1015 } 1016 gmask = header->green_mask; 1017 while (!(gmask & 1)) { 1018 gmask >>= 1; 1019 gshift++; 1020 } 1021 bmask = header->blue_mask; 1022 while (!(bmask & 1)) { 1023 bmask >>= 1; 1024 bshift++; 1025 } 1026 if (in_image->depth <= 12) { 1027 pix = 1 << in_image->depth; 1028 pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix); 1029 if (pixels == NULL) 1030 Error("Unable to allocate memory for pixel conversion"); 1031 for (i = 0; i < pix; i++) 1032 pixels[i] = ~0L; 1033 color.flags = DoRed | DoGreen | DoBlue; 1034 for (y = 0; y < in_image->height; y++) { 1035 for (x = 0; x < in_image->width; x++) { 1036 pix = XGetPixel(in_image, x, y); 1037 if ((color.pixel = pixels[pix]) == ~0L) { 1038 color.red = (pix >> rshift) & rmask; 1039 color.green = (pix >> gshift) & gmask; 1040 color.blue = (pix >> bshift) & bmask; 1041 if (ncolors) { 1042 color.red = colors[color.red].red; 1043 color.green = colors[color.green].green; 1044 color.blue = colors[color.blue].blue; 1045 } else { 1046 color.red = (((unsigned long)color.red * 65535) / 1047 rmask); 1048 color.green = (((unsigned long)color.green * 65535) / 1049 gmask); 1050 color.blue = (((unsigned long)color.blue * 65535) / 1051 bmask); 1052 } 1053 if (!XAllocColor(dpy, *colormap, &color)) { 1054 *colormap = CopyColormapAndFree(dpy, *colormap); 1055 XAllocColor(dpy, *colormap, &color); 1056 } 1057 pixels[pix] = color.pixel; 1058 } 1059 XPutPixel(out_image, x, y, color.pixel); 1060 } 1061 } 1062 free(pixels); 1063 } else if (header->visual_class == TrueColor && 1064 vinfo->class == TrueColor) { 1065 ormask = vinfo->red_mask; 1066 while (!(ormask & 1)) { 1067 ormask >>= 1; 1068 orshift++; 1069 } 1070 ogmask = vinfo->green_mask; 1071 while (!(ogmask & 1)) { 1072 ogmask >>= 1; 1073 ogshift++; 1074 } 1075 obmask = vinfo->blue_mask; 1076 while (!(obmask & 1)) { 1077 obmask >>= 1; 1078 obshift++; 1079 } 1080 for (y = 0; y < in_image->height; y++) { 1081 for (x = 0; x < in_image->width; x++) { 1082 pix = XGetPixel(in_image, x, y); 1083 xpix = (((((pix >> rshift) & rmask) * 65535 / rmask) 1084 * ormask / 65535) << orshift) | 1085 (((((pix >> gshift) & gmask) * 65535 / gmask) 1086 * ogmask / 65535) << ogshift) | 1087 (((((pix >> bshift) & bmask) * 65535 / bmask) 1088 * obmask / 65535) << obshift); 1089 XPutPixel(out_image, x, y, xpix); 1090 } 1091 } 1092 } else { 1093 if (header->visual_class == TrueColor) 1094 ncolors = 0; 1095 pix = 1 << 12; 1096 pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix); 1097 rpixels = (unsigned long *)malloc(sizeof(unsigned long) * pix); 1098 if ((pixels == NULL) || (rpixels == NULL)) 1099 Error("Unable to allocate memory for pixel conversion"); 1100 for (i = 0; i < pix; i++) { 1101 pixels[i] = ~0L; 1102 rpixels[i] = ~0L; 1103 } 1104 color.flags = DoRed | DoGreen | DoBlue; 1105 for (y = 0; y < in_image->height; y++) { 1106 for (x = 0; x < in_image->width; x++) { 1107 pix = XGetPixel(in_image, x, y); 1108 xpix = ((pix >> 12) ^ pix) & ((1 << 12) - 1); 1109 if (((color.pixel = pixels[xpix]) == ~0L) || 1110 (rpixels[xpix] != pix)) { 1111 color.red = (pix >> rshift) & rmask; 1112 color.green = (pix >> gshift) & gmask; 1113 color.blue = (pix >> bshift) & bmask; 1114 if (ncolors) { 1115 color.red = colors[color.red].red; 1116 color.green = colors[color.green].green; 1117 color.blue = colors[color.blue].blue; 1118 } else { 1119 color.red = (((unsigned long)color.red * 65535) / 1120 rmask); 1121 color.green = (((unsigned long)color.green * 65535) / 1122 gmask); 1123 color.blue = (((unsigned long)color.blue * 65535) / 1124 bmask); 1125 } 1126 if (!XAllocColor(dpy, *colormap, &color)) { 1127 *colormap = CopyColormapAndFree(dpy, *colormap); 1128 XAllocColor(dpy, *colormap, &color); 1129 } 1130 pixels[xpix] = color.pixel; 1131 rpixels[xpix] = pix; 1132 } 1133 XPutPixel(out_image, x, y, color.pixel); 1134 } 1135 } 1136 free(pixels); 1137 free(rpixels); 1138 } 1139} 1140 1141static unsigned int 1142Image_Size(XImage *image) 1143{ 1144 if (image->format != ZPixmap) 1145 return(image->bytes_per_line * image->height * image->depth); 1146 1147 return((unsigned)image->bytes_per_line * image->height); 1148} 1149 1150static void 1151Error(char *string) 1152{ 1153 fprintf(stderr, "xwud: Error => %s\n", string); 1154 if (errno != 0) { 1155 perror("xwud"); 1156 fprintf(stderr, "\n"); 1157 } 1158 exit(1); 1159} 1160 1161static void 1162_swapshort(char *bp, unsigned int n) 1163{ 1164 register char c; 1165 register char *ep = bp + n; 1166 1167 while (bp < ep) { 1168 c = *bp; 1169 *bp = *(bp + 1); 1170 bp++; 1171 *bp++ = c; 1172 } 1173} 1174 1175static void 1176_swaplong(char *bp, unsigned int n) 1177{ 1178 register char c; 1179 register char *ep = bp + n; 1180 register char *sp; 1181 1182 while (bp < ep) { 1183 sp = bp + 3; 1184 c = *sp; 1185 *sp = *bp; 1186 *bp++ = c; 1187 sp = bp + 1; 1188 c = *sp; 1189 *sp = *bp; 1190 *bp++ = c; 1191 bp += 2; 1192 } 1193} 1194 1195static void 1196DumpHeader(const XWDFileHeader *header, const char *win_name) 1197{ 1198 printf("window name: %s\n", win_name); 1199 printf("sizeof(XWDheader): %d\n", (int)sizeof(*header)); 1200 printf("header size: %d\n", (int)header->header_size); 1201 printf("file version: %d\n", (int)header->file_version); 1202 printf("pixmap format: %d\n", (int)header->pixmap_format); 1203 printf("pixmap depth: %d\n", (int)header->pixmap_depth); 1204 printf("pixmap width: %d\n", (int)header->pixmap_width); 1205 printf("pixmap height: %d\n", (int)header->pixmap_height); 1206 printf("x offset: %d\n", (int)header->xoffset); 1207 printf("byte order: %d\n", (int)header->byte_order); 1208 printf("bitmap unit: %d\n", (int)header->bitmap_unit); 1209 printf("bitmap bit order: %d\n", (int)header->bitmap_bit_order); 1210 printf("bitmap pad: %d\n", (int)header->bitmap_pad); 1211 printf("bits per pixel: %d\n", (int)header->bits_per_pixel); 1212 printf("bytes per line: %d\n", (int)header->bytes_per_line); 1213 printf("visual class: %d\n", (int)header->visual_class); 1214 printf("red mask: %d\n", (int)header->red_mask); 1215 printf("green mask: %d\n", (int)header->green_mask); 1216 printf("blue mask: %d\n", (int)header->blue_mask); 1217 printf("bits per rgb: %d\n", (int)header->bits_per_rgb); 1218 printf("colormap entries: %d\n", (int)header->colormap_entries); 1219 printf("num colors: %d\n", (int)header->ncolors); 1220 printf("window width: %d\n", (int)header->window_width); 1221 printf("window height: %d\n", (int)header->window_height); 1222 printf("window x: %d\n", (int)header->window_x); 1223 printf("window y: %d\n", (int)header->window_y); 1224 printf("border width: %d\n", (int)header->window_bdrwidth); 1225} 1226 1227