#include <X/mit-copyright.h>
/* Copyright 1985, 1986, Massachusetts Institute of Technology */
* xwud.c - MIT Project Athena, X Window system window raster image
* This program will read a raster image of a window from stdin or a file
* and display it on an X display.
* Author: Tony Della Fera, DEC
* Modified 11/14/86 by William F. Wyatt,
* Smithsonian Astrophysical Observatory
* allows writing of monochrome XYFormat window dump files on a color
* display, using default WhitePixel for 1's and BlackPixel for 0's.
* VERSION 6 - same as V5 for monochrome, but expects color map info
* in the file for color images. Checks to see if the requested
* colors are already in the display's map (e.g. if the window dump
* and undump are contemporaneous to the same display). If so,
* undump immediately. If not, request new colors, alter the
* pixels to the new values, then write the pixmap. Note that
* multi-plane XY format undumps don't work if the pixel values
* corresponding to the requested colors have to be changed.
static char *rcsid_xwud_c
= "$Header: xwud.c,v 10.10 86/11/25 08:44:25 jg Rel $";
typedef enum _bool
{FALSE
, TRUE
} Bool
;
#define MAX(a, b) (a) > (b) ? (a) : (b)
#define MIN(a, b) (a) < (b) ? (a) : (b)
#define ABS(a) (a) < 0 ? -(a) : (a)
register int *histbuffer
;
register u_short
*wbuffer
;
unsigned buffer_size
, total_buffer_size
;
Bool newcolors
= FALSE
, debug
= FALSE
, inverse
= FALSE
;
Color
*pixcolors
, *newpixcolors
;
register XExposeEvent
*xevent
= (XExposeEvent
*)&event
;
for (i
= 1; i
< argc
; i
++) {
str_index
= (char *)index (argv
[i
], ':');
(void) strncpy(display
,argv
[i
],sizeof(display
));
str_index
= (char *) index (argv
[i
], '-');
if (str_index
== NULL
) Syntax(argv
[0]);
if (strncmp(argv
[i
], "-help", 5) == 0) {
if (strncmp(argv
[i
], "-in", 4) == 0) {
if (++i
>= argc
) Syntax(argv
[0]);
if(strcmp(argv
[i
], "-inverse") == 0) {
if(strcmp(argv
[i
], "-debug") == 0) {
in_file
= fopen(file_name
, "r");
Error("Can't open output file as specified.");
if ((dpy
= XOpenDisplay(display
)) == NULL
) {
fprintf(stderr
, "%s: Can't open display '%s'\n",
argv
[0], XDisplayName(display
));
* Read in header information.
if(fread((char *)&header
, sizeof(header
), 1, in_file
) != 1)
Error("Unable to read dump file header.");
* check to see if the dump file is in the proper format.
if (header
.file_version
!= XWD_FILE_VERSION
) {
fprintf(stderr
,"xwud: XWD file format version missmatch.");
if(header
.file_version
== 5 && header
.display_planes
== 1)
fprintf(stderr
,"\n (monochrome works anyway)\n");
if(DisplayPlanes() < header
.display_planes
)
Error("Windump has more planes than display.");
* Check to see if we are in the right pixmap format for the
if ((DisplayPlanes() == 1) && (header
.pixmap_format
!= XYFormat
)) {
"Windump is in ZFormat which is not valid on a monochrome display.");
win_name_size
= ABS(header
.header_size
- sizeof(header
));
if((win_name
= calloc((unsigned) win_name_size
, sizeof(char))) == NULL
)
Error("Can't calloc window name storage.");
if(fread(win_name
, sizeof(char), win_name_size
, in_file
) != win_name_size
)
Error("Unable to read window name from dump file.");
if(debug
) fprintf(stderr
,"win_name =%s\n", win_name
);
* Determine the pixmap size.
if (header
.pixmap_format
== XYFormat
) {
else if (header
.display_planes
< 9) {
total_buffer_size
= buffer_size
= BZPixmapSize(
else if(header
.display_planes
< 17) {
total_buffer_size
= buffer_size
= WZPixmapSize(
Error("Can't undump pixmaps more than 16 bits deep.\n");
/* Calloc the color map buffer.
* Read it in, copy it and use the copy to query for the
* existing colors at those pixel values.
if(header
.window_ncolors
) {
pixcolors
= (Color
*)calloc(header
.window_ncolors
,sizeof(Color
));
if(fread(pixcolors
,sizeof(Color
),header
.window_ncolors
, in_file
)
!= header
.window_ncolors
)
Error("Unable to read color map from dump file.");
fprintf(stderr
,"Read %d colors\n", header
.window_ncolors
);
newpixcolors
= (Color
*)calloc(header
.window_ncolors
,sizeof(Color
));
bcopy(pixcolors
, newpixcolors
, sizeof(Color
)*header
.window_ncolors
);
if(XQueryColors(newpixcolors
,header
.window_ncolors
) == 0)
Error("Can't query the color map?");
for(i
=0; i
<header
.window_ncolors
; i
++)
if(!ColorEqual(&pixcolors
[i
], &newpixcolors
[i
])) {
if(newcolors
) fprintf(stderr
,"New colors needed\n");
else fprintf(stderr
,"Old colors match!\n");
* Calloc the pixel buffer.
if((buffer
= calloc(total_buffer_size
, 1)) == NULL
)
Error("Can't calloc data buffer.");
bzero(buffer
,total_buffer_size
);
* Read in the pixmap buffer.
if((status
= fread(buffer
, sizeof(char), (int)buffer_size
, in_file
))
Error("Unable to read pixmap from dump file.");
* If necessary, get and store the new colors, convert the pixels to the
* new colors appropriately.
cpixels
= (int *)calloc(header
.window_ncolors
+1,sizeof(int));
if(XGetColorCells(0, header
.window_ncolors
, 0, &cplanes
, cpixels
)
Error("Can't allocate colors.");
for(i
=0; i
<header
.window_ncolors
; i
++) {
newpixcolors
[i
].pixel
= cpixels
[i
];
newpixcolors
[i
].red
= pixcolors
[i
].red
;
newpixcolors
[i
].green
= pixcolors
[i
].green
;
newpixcolors
[i
].blue
= pixcolors
[i
].blue
;
fprintf(stderr
,"Pixel %4d, r = %5d g = %5d b = %5d\n",
newpixcolors
[i
].pixel
, newpixcolors
[i
].red
,
newpixcolors
[i
].green
, newpixcolors
[i
].blue
);
XStoreColors(header
.window_ncolors
, newpixcolors
);
/* now, make a lookup table to convert old pixels into the new ones*/
if(header
.pixmap_format
== ZFormat
) {
if(header
.display_planes
< 9) {
histbuffer
= (int *)calloc(256, sizeof(int));
bzero(histbuffer
, 256*sizeof(int));
for(i
=0; i
<header
.window_ncolors
; i
++)
histbuffer
[pixcolors
[i
].pixel
] = newpixcolors
[i
].pixel
;
for(i
=0; i
<buffer_size
; i
++)
buffer
[i
] = histbuffer
[buffer
[i
]];
else if(header
.display_planes
< 17) {
histbuffer
= (int *)calloc(65536, sizeof(int));
bzero(histbuffer
, 65536*sizeof(int));
for(i
=0; i
<header
.window_ncolors
; i
++)
histbuffer
[pixcolors
[i
].pixel
] = newpixcolors
[i
].pixel
;
wbuffer
= (u_short
*)buffer
;
for(i
=0; i
<(buffer_size
/sizeof(u_short
)); i
++)
wbuffer
[i
] = histbuffer
[wbuffer
[i
]];
else if(header
.display_planes
> 16) {
Error("Unable to handle more than 16 planes at this time");
bcopy(newpixcolors
, pixcolors
, sizeof(Color
)*header
.window_ncolors
);
* Create the image window.
image_win
= XCreateWindow(
header
.window_x
, header
.window_y
,
header
.pixmap_width
, header
.pixmap_height
,
if (image_win
== FAILURE
) Error("Can't create image window.");
* Select mouse ButtonPressed on the window, this is how we determine
* when to stop displaying the window.
XSelectInput(image_win
, (ButtonPressed
| ExposeWindow
| ExposeRegion
));
* Store the window name string.
XStoreName(image_win
, win_name
);
* Set up a while loop to maintain the image.
* Wait on mouse input event to terminate.
if (event
.type
== ButtonPressed
) break;
switch((int)event
.type
) {
case ExposeWindow
: /* Copy the data into the window.*/
case ExposeRegion
: /* simpler to copy from x=0 for full width */
if(header
.pixmap_format
== XYFormat
) {
onebufsize
= /* size of each bitmap */
XYPixmapSize(header
.pixmap_width
,
header
.pixmap_height
, 1);
nbytes
= BitmapSize(header
.pixmap_width
,1);
if(header
.display_planes
> 1) {
planes
= 1<<(DisplayPlanes()); /* MSB << 1 */
for(j
=0; j
<header
.display_planes
; j
++) {
if(header
.display_planes
> 1)
planes
>>= 1; /* shift down a bit */
for(i
=0; i
<xevent
->height
; i
+=100)
XBitmapBitsPut(image_win
,
MIN(100, xevent
->height
- i
),
buffer
+((i
+xevent
->y
)*nbytes
)
XBitmapBitsPut(image_win
,
MIN(100, xevent
->height
- i
),
buffer
+((i
+xevent
->y
)*nbytes
)
else if(DisplayPlanes() < 9) {
nbytes
= BZPixmapSize(header
.pixmap_width
,1);
for(i
=0; i
<xevent
->height
; i
+=100)
XPixmapBitsPutZ(image_win
,
MIN(100, xevent
->height
- i
),
buffer
+((i
+xevent
->y
)*nbytes
),
else { /* Display Planes > 8 */
nbytes
= WZPixmapSize(header
.pixmap_width
, 1);
for(i
=0; i
<xevent
->height
; i
+=100)
XPixmapBitsPutZ(image_win
,
MIN(50, xevent
->height
- i
),
buffer
+((i
+xevent
->y
)*nbytes
),
* Destroy the image window.
XDestroyWindow(image_win
);
* Free the pixmap buffer.
* Free window name string.
* test two color map entries for equality
ColorEqual(color1
, color2
)
register Color
*color1
, *color2
;
return(color1
->pixel
== color2
->pixel
&&
color1
->red
== color2
->red
&&
color1
->green
== color2
->green
&&
color1
->blue
== color2
->blue
);
* Report the syntax for calling xwud.
"xwud: %s [-help][-debug][-inverse][-in <file>][[host]:vs]\n",
* Error - Fatal xwud error.
char *string
; /* Error description string. */
fprintf(stderr
, "xwud: Error => %s\n", string
);