xwud.c 36 KB

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