|
|
1.1 root 1: #include <X/mit-copyright.h>
2:
3: /* Copyright 1985, 1986, Massachusetts Institute of Technology */
4:
5: /*
6: * xwud.c - MIT Project Athena, X Window system window raster image
7: * undumper.
8: *
9: * This program will read a raster image of a window from stdin or a file
10: * and display it on an X display.
11: *
12: * Author: Tony Della Fera, DEC
13: *
14: * Modified 11/14/86 by William F. Wyatt,
15: * Smithsonian Astrophysical Observatory
16: * allows writing of monochrome XYFormat window dump files on a color
17: * display, using default WhitePixel for 1's and BlackPixel for 0's.
18: *
19: * Modified 11/20/86 WFW
20: * VERSION 6 - same as V5 for monochrome, but expects color map info
21: * in the file for color images. Checks to see if the requested
22: * colors are already in the display's map (e.g. if the window dump
23: * and undump are contemporaneous to the same display). If so,
24: * undump immediately. If not, request new colors, alter the
25: * pixels to the new values, then write the pixmap. Note that
26: * multi-plane XY format undumps don't work if the pixel values
27: * corresponding to the requested colors have to be changed.
28: */
29:
30: #ifndef lint
31: static char *rcsid_xwud_c = "$Header: xwud.c,v 10.10 86/11/25 08:44:25 jg Rel $";
32: #endif
33:
34: #include <X/Xlib.h>
35: #include <stdio.h>
36: #include <strings.h>
37: #include <sys/types.h>
38: extern char *calloc();
39:
40: #include <X/XWDFile.h>
41:
42: typedef enum _bool {FALSE, TRUE} Bool;
43:
44: #define MAX(a, b) (a) > (b) ? (a) : (b)
45: #define MIN(a, b) (a) < (b) ? (a) : (b)
46: #define ABS(a) (a) < 0 ? -(a) : (a)
47:
48: #define FAILURE 0
49:
50: extern int errno;
51:
52: main(argc, argv)
53: int argc;
54: char **argv;
55: {
56: register int i;
57: register int *histbuffer;
58: register u_short *wbuffer;
59: register char *buffer;
60:
61: int j, status;
62: int *cpixels, cplanes;
63: int onebufsize;
64: int planes;
65: int forepixel;
66: int backpixel;
67: unsigned buffer_size, total_buffer_size;
68: int win_name_size;
69: char *str_index;
70: char *file_name;
71: char display[256];
72: char *win_name;
73: Bool standard_in = TRUE;
74: Bool newcolors = FALSE, debug = FALSE, inverse = FALSE;
75:
76: Color *pixcolors, *newpixcolors;
77: Display *dpy;
78: Window image_win;
79: Pixmap image_pixmap;
80: XEvent event;
81: register XExposeEvent *xevent = (XExposeEvent *)&event;
82:
83: XWDFileHeader header;
84:
85: FILE *in_file = stdin;
86:
87: for (i = 1; i < argc; i++) {
88: str_index = (char *)index (argv[i], ':');
89: if(str_index != NULL) {
90: (void) strncpy(display,argv[i],sizeof(display));
91: continue;
92: }
93: str_index = (char *) index (argv [i], '-');
94: if (str_index == NULL) Syntax(argv[0]);
95: if (strncmp(argv[i], "-help", 5) == 0) {
96: Syntax(argv[0]);
97: }
98: if (strncmp(argv[i], "-in", 4) == 0) {
99: if (++i >= argc) Syntax(argv[0]);
100: file_name = argv[i];
101: standard_in = FALSE;
102: continue;
103: }
104: if(strcmp(argv[i], "-inverse") == 0) {
105: inverse = TRUE;
106: continue;
107: }
108: if(strcmp(argv[i], "-debug") == 0) {
109: debug = TRUE;
110: continue;
111: }
112: Syntax(argv[0]);
113: }
114:
115: if (!standard_in) {
116: /*
117: * Open the output file.
118: */
119: in_file = fopen(file_name, "r");
120: if (in_file == NULL) {
121: Error("Can't open output file as specified.");
122: }
123: }
124:
125: /*
126: * Open the display.
127: */
128: if ((dpy = XOpenDisplay(display)) == NULL) {
129: fprintf(stderr, "%s: Can't open display '%s'\n",
130: argv[0], XDisplayName(display));
131: exit(1);
132: }
133:
134: /*
135: * Read in header information.
136: */
137: if(fread((char *)&header, sizeof(header), 1, in_file) != 1)
138: Error("Unable to read dump file header.");
139:
140: /*
141: * check to see if the dump file is in the proper format.
142: */
143: if (header.file_version != XWD_FILE_VERSION) {
144: fprintf(stderr,"xwud: XWD file format version missmatch.");
145: if(header.file_version == 5 && header.display_planes == 1)
146: fprintf(stderr,"\n (monochrome works anyway)\n");
147: else Error("exiting.");
148: }
149:
150: if(DisplayPlanes() < header.display_planes)
151: Error("Windump has more planes than display.");
152:
153: /*
154: * Check to see if we are in the right pixmap format for the
155: * display type.
156: */
157: if ((DisplayPlanes() == 1) && (header.pixmap_format != XYFormat)) {
158: Error(
159: "Windump is in ZFormat which is not valid on a monochrome display.");
160: }
161:
162: /*
163: * Calloc window name.
164: */
165: win_name_size = ABS(header.header_size - sizeof(header));
166: if((win_name = calloc((unsigned) win_name_size, sizeof(char))) == NULL)
167: Error("Can't calloc window name storage.");
168:
169: /*
170: * Read in window name.
171: */
172: if(fread(win_name, sizeof(char), win_name_size, in_file) != win_name_size)
173: Error("Unable to read window name from dump file.");
174: if(debug) fprintf(stderr,"win_name =%s\n", win_name);
175:
176: /*
177: * Determine the pixmap size.
178: */
179: if (header.pixmap_format == XYFormat) {
180: buffer_size =
181: XYPixmapSize(
182: header.pixmap_width,
183: header.pixmap_height,
184: header.display_planes);
185: total_buffer_size =
186: XYPixmapSize(
187: header.pixmap_width,
188: header.pixmap_height,
189: DisplayPlanes() );
190: }
191: else if (header.display_planes < 9) {
192: total_buffer_size = buffer_size = BZPixmapSize(
193: header.pixmap_width,
194: header.pixmap_height
195: );
196: }
197: else if(header.display_planes < 17) {
198: total_buffer_size = buffer_size = WZPixmapSize(
199: header.pixmap_width,
200: header.pixmap_height
201: );
202: }
203: else {
204: Error("Can't undump pixmaps more than 16 bits deep.\n");
205: }
206:
207:
208: /* Calloc the color map buffer.
209: * Read it in, copy it and use the copy to query for the
210: * existing colors at those pixel values.
211: */
212: if(header.window_ncolors) {
213: pixcolors = (Color *)calloc(header.window_ncolors,sizeof(Color));
214: if(fread(pixcolors,sizeof(Color),header.window_ncolors, in_file)
215: != header.window_ncolors)
216: Error("Unable to read color map from dump file.");
217: if(debug)
218: fprintf(stderr,"Read %d colors\n", header.window_ncolors);
219: newpixcolors = (Color *)calloc(header.window_ncolors,sizeof(Color));
220: bcopy(pixcolors, newpixcolors, sizeof(Color)*header.window_ncolors);
221: if(XQueryColors(newpixcolors,header.window_ncolors) == 0)
222: Error("Can't query the color map?");
223: for(i=0; i<header.window_ncolors; i++)
224: if(!ColorEqual(&pixcolors[i], &newpixcolors[i])) {
225: newcolors = TRUE;
226: break;
227: }
228: if(debug) {
229: if(newcolors) fprintf(stderr,"New colors needed\n");
230: else fprintf(stderr,"Old colors match!\n");
231: }
232: }
233:
234: /*
235: * Calloc the pixel buffer.
236: */
237: if((buffer = calloc(total_buffer_size, 1)) == NULL)
238: Error("Can't calloc data buffer.");
239: bzero(buffer,total_buffer_size);
240:
241: /*
242: * Read in the pixmap buffer.
243: */
244: if((status = fread(buffer, sizeof(char), (int)buffer_size, in_file))
245: != buffer_size)
246: Error("Unable to read pixmap from dump file.");
247: /*
248: * Close the input file.
249: */
250: (void) fclose(in_file);
251:
252: /*
253: * If necessary, get and store the new colors, convert the pixels to the
254: * new colors appropriately.
255: */
256: if(newcolors) {
257: cpixels = (int *)calloc(header.window_ncolors+1,sizeof(int));
258: if(XGetColorCells(0, header.window_ncolors, 0, &cplanes, cpixels)
259: == 0)
260: Error("Can't allocate colors.");
261: for(i=0; i<header.window_ncolors; i++) {
262: newpixcolors[i].pixel = cpixels[i];
263: newpixcolors[i].red = pixcolors[i].red;
264: newpixcolors[i].green = pixcolors[i].green;
265: newpixcolors[i].blue = pixcolors[i].blue;
266: if(debug)
267: fprintf(stderr,"Pixel %4d, r = %5d g = %5d b = %5d\n",
268: newpixcolors[i].pixel, newpixcolors[i].red,
269: newpixcolors[i].green, newpixcolors[i].blue);
270: }
271: XStoreColors(header.window_ncolors, newpixcolors);
272:
273: /* now, make a lookup table to convert old pixels into the new ones*/
274: if(header.pixmap_format == ZFormat) {
275: if(header.display_planes < 9) {
276: histbuffer = (int *)calloc(256, sizeof(int));
277: bzero(histbuffer, 256*sizeof(int));
278: for(i=0; i<header.window_ncolors; i++)
279: histbuffer[pixcolors[i].pixel] = newpixcolors[i].pixel;
280: for(i=0; i<buffer_size; i++)
281: buffer[i] = histbuffer[buffer[i]];
282: }
283: else if(header.display_planes < 17) {
284: histbuffer = (int *)calloc(65536, sizeof(int));
285: bzero(histbuffer, 65536*sizeof(int));
286: for(i=0; i<header.window_ncolors; i++)
287: histbuffer[pixcolors[i].pixel] = newpixcolors[i].pixel;
288: wbuffer = (u_short *)buffer;
289: for(i=0; i<(buffer_size/sizeof(u_short)); i++)
290: wbuffer[i] = histbuffer[wbuffer[i]];
291: }
292: else if(header.display_planes > 16) {
293: Error("Unable to handle more than 16 planes at this time");
294: }
295: free(histbuffer);
296: }
297: free(cpixels);
298: bcopy(newpixcolors, pixcolors, sizeof(Color)*header.window_ncolors);
299: free(newpixcolors);
300: }
301:
302:
303: /*
304: * Create the image window.
305: */
306: image_win = XCreateWindow(
307: RootWindow,
308: header.window_x, header.window_y,
309: header.pixmap_width, header.pixmap_height,
310: 0, (Pixmap) 0,
311: (Pixmap) 0
312: );
313: if (image_win == FAILURE) Error("Can't create image window.");
314:
315: /*
316: * Select mouse ButtonPressed on the window, this is how we determine
317: * when to stop displaying the window.
318: */
319: XSelectInput(image_win, (ButtonPressed | ExposeWindow | ExposeRegion));
320:
321: /*
322: * Store the window name string.
323: */
324: XStoreName(image_win, win_name);
325:
326: /*
327: * Map the image window.
328: */
329: XMapWindow(image_win);
330:
331: /*
332: * Set up a while loop to maintain the image.
333: */
334: while (TRUE) {
335: int i, nbytes;
336: /*
337: * Wait on mouse input event to terminate.
338: */
339: XNextEvent(&event);
340: if (event.type == ButtonPressed) break;
341:
342: switch((int)event.type) {
343: case ExposeWindow: /* Copy the data into the window.*/
344: case ExposeRegion: /* simpler to copy from x=0 for full width */
345: if(header.pixmap_format == XYFormat) {
346: onebufsize = /* size of each bitmap */
347: XYPixmapSize(header.pixmap_width,
348: header.pixmap_height, 1);
349: nbytes = BitmapSize(header.pixmap_width,1);
350: if(header.display_planes > 1) {
351: forepixel = -1;
352: backpixel = 0;
353: planes = 1<<(DisplayPlanes()); /* MSB << 1 */
354: }
355: else {
356: forepixel = WhitePixel;
357: backpixel = BlackPixel;
358: planes = AllPlanes;
359: }
360: for(j=0; j<header.display_planes; j++) {
361: if(header.display_planes > 1)
362: planes >>= 1; /* shift down a bit */
363: for(i=0; i<xevent->height; i+=100)
364: if(inverse)
365: XBitmapBitsPut(image_win,
366: 0, i + xevent->y,
367: header.pixmap_width,
368: MIN(100, xevent->height - i),
369: buffer+((i+xevent->y)*nbytes)
370: + (onebufsize * j),
371: backpixel, forepixel,
372: 0, GXcopy, planes);
373: else
374: XBitmapBitsPut(image_win,
375: 0, i + xevent->y,
376: header.pixmap_width,
377: MIN(100, xevent->height - i),
378: buffer+((i+xevent->y)*nbytes)
379: + (onebufsize * j),
380: forepixel, backpixel,
381: 0, GXcopy, planes);
382: }
383: }
384: else if(DisplayPlanes() < 9) {
385: nbytes = BZPixmapSize(header.pixmap_width,1);
386: for(i=0; i<xevent->height; i+=100)
387: XPixmapBitsPutZ(image_win,
388: 0, i + xevent->y,
389: header.pixmap_width,
390: MIN(100, xevent->height - i),
391: buffer+((i+xevent->y)*nbytes),
392: 0, GXcopy, AllPlanes);
393: }
394: else { /* Display Planes > 8 */
395: nbytes = WZPixmapSize(header.pixmap_width, 1);
396: for(i=0; i<xevent->height; i+=100)
397: XPixmapBitsPutZ(image_win,
398: 0, i + xevent->y,
399: header.pixmap_width,
400: MIN(50, xevent->height - i),
401: buffer+((i+xevent->y)*nbytes),
402: 0, GXcopy, AllPlanes);
403: }
404: }
405: }
406:
407: /*
408: * Destroy the image window.
409: */
410: XDestroyWindow(image_win);
411:
412: /*
413: * Free the pixmap buffer.
414: */
415: free(buffer);
416:
417: /*
418: * Free window name string.
419: */
420: free(win_name);
421: exit(0);
422: }
423:
424: /*
425: * test two color map entries for equality
426: */
427: ColorEqual(color1, color2)
428: register Color *color1, *color2;
429: {
430: return(color1->pixel == color2->pixel &&
431: color1->red == color2->red &&
432: color1->green == color2->green &&
433: color1->blue == color2->blue);
434: }
435:
436: /*
437: * Report the syntax for calling xwud.
438: */
439: Syntax(call)
440: char *call;
441: {
442: fprintf( stderr,
443: "xwud: %s [-help][-debug][-inverse][-in <file>][[host]:vs]\n",
444: call
445: );
446: exit(1);
447: }
448:
449:
450: /*
451: * Error - Fatal xwud error.
452: */
453: Error(string)
454: char *string; /* Error description string. */
455: {
456: fprintf(stderr, "xwud: Error => %s\n", string);
457:
458: if (errno != 0) {
459: perror("xwud");
460: fprintf(stderr, "\n");
461: }
462:
463: exit(1);
464: }
465:
466: /* End of xwud.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.