home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume8 / xgrabsc / part01 next >
Internet Message Format  |  1990-08-20  |  58KB

  1. Path: uunet!decwrl!sun-barr!newstop!sun!SLC.COM
  2. From: bruce@SLC.COM (Bruce Schuchardt)
  3. Newsgroups: comp.sources.x
  4. Subject: v08i075: xgrabsc -- make images of portions of the screen, Part01/02
  5. Message-ID: <140952@sun.Eng.Sun.COM>
  6. Date: 20 Aug 90 17:52:43 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 2007
  9. Approved: argv@sun.com
  10.  
  11. Submitted-by: bruce@SLC.COM (Bruce Schuchardt)
  12. Posting-number: Volume 8, Issue 75
  13. Archive-name: xgrabsc/part01
  14.  
  15. There are a number of programs available for getting X-Windows
  16. screen dumps (e.g., xwd, xwps and DEC's session manager), but they
  17. all either write their output in an unusable format, or are restricted
  18. to dumps of single shell windows.  I wrote xgrabsc in an effort to get
  19. around these restrictions.
  20.  
  21. The main contribution of this program is its use of root-window
  22. rubberbanding to allow capture of arbitrary portions of the screen,
  23. and its multiple output formats (x-bitmap, x-pixmap, xwd, Postscript
  24. and puzzle formats).
  25.  
  26. The Postscript dumps will use run-length encoding if it results in
  27. any savings in size.  A typical xterm window dump on a mono system
  28. runs around 40K bytes.  An xwd dump on the same screen will be around
  29. 650K bytes.
  30.  
  31. The program should build easily enough.  If you don't have imake,
  32. use simple.mak (i.e., make -f simple.mak).  For building, you 
  33. should only have to alter the makefiles if your include files or 
  34. libraries are in a non-standard location (/usr/include/X11, /usr/
  35. lib).
  36.  
  37. The makefiles will install xgrabsc in /usr/bin/X11 and the man page in
  38. /usr/man/man1.  Change the makefile before installing if you don't like
  39. these locations.
  40.  
  41.  
  42. Please send comments, bugs and enhancements to bruce@slc.com.
  43.  
  44.  
  45.    File Name        Archive #    Description
  46. -----------------------------------------------------------
  47.  Imakefile                  1            imake makefile
  48.  README                     1            this stuff
  49.  cpyright.h                 1            copyright notice
  50.  patchlevel.h               2            current patch level
  51.  simple.mak                 2            simple 'make' makefile
  52.  xgrabsc.c                  1            program source
  53.  xgrabsc.man                1            man page for xgrabsc
  54.  
  55. -----------------CUT HERE---------------------
  56. #! /bin/sh
  57. # This is a shell archive.  Remove anything before this line, then unpack
  58. # it by saving it into a file and typing "sh file".  To overwrite existing
  59. # files, type "sh file -c".  You can also feed this as standard input via
  60. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  61. # will see the following message at the end:
  62. #        "End of archive 1 (of 2)."
  63. # Contents:  README Imakefile cpyright.h xgrabsc.c xgrabsc.man
  64. # Wrapped by owner@spruce on Mon Aug 20 10:03:02 1990
  65. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  66. if test -f 'README' -a "${1}" != "-c" ; then 
  67.   echo shar: Will not clobber existing file \"'README'\"
  68. else
  69. echo shar: Extracting \"'README'\" \(2167 characters\)
  70. sed "s/^X//" >'README' <<'END_OF_FILE'
  71. X*========================================================================
  72. X*
  73. X* Name - README
  74. X*
  75. X* Version:    1.3
  76. X*
  77. X* ccsid:    @(#)README    1.3 - 8/20/90 09:55:04
  78. X* from:     ccs/s.README
  79. X* date:     8/20/90 09:55:59
  80. X*
  81. X* Copyright (C) 1990, Bruce Schuchardt
  82. X* See either the man page or the file cpyright.h for full copyright
  83. X* information.
  84. X*  
  85. X* Description:  README for xgrabsc
  86. X*
  87. X*========================================================================
  88. X
  89. XThere are a number of programs available for getting X-Windows
  90. Xscreen dumps (e.g., xwd, xwps and DEC's session manager), but they
  91. Xall either write their output in an unusable format, or are restricted
  92. Xto dumps of single shell windows.  I wrote xgrabsc in an effort to get
  93. Xaround these restrictions.
  94. X
  95. XThe main contribution of this program is its use of root-window
  96. Xrubberbanding to allow capture of arbitrary portions of the screen,
  97. Xand its multiple output formats (x-bitmap, x-pixmap, xwd, Postscript
  98. Xand puzzle formats).
  99. X
  100. XThe Postscript dumps will use run-length encoding if it results in
  101. Xany savings in size.  A typical xterm window dump on a mono system
  102. Xruns around 40K bytes.  An xwd dump on the same screen will be around
  103. X650K bytes.
  104. X
  105. XThe program should build easily enough.  If you don't have imake,
  106. Xuse simple.mak (i.e., make -f simple.mak).  For building, you 
  107. Xshould only have to alter the makefiles if your include files or 
  108. Xlibraries are in a non-standard location (/usr/include/X11, /usr/
  109. Xlib).
  110. X
  111. XThe makefiles will install xgrabsc in /usr/bin/X11 and the man page in
  112. X/usr/man/man1.  Change the makefile before installing if you don't like
  113. Xthese locations.
  114. X
  115. X
  116. XPlease send comments, bugs and enhancements to bruce@slc.com.
  117. X
  118. X
  119. XManifest
  120. X--------
  121. XREADME              this file
  122. X
  123. XImakefile           Input for "imake" program
  124. Xsimple.mak          Simpler input for standard "make"
  125. X
  126. Xcpyright.h          Copyright notice for this software (READ IT)
  127. Xpatchlevel.h        Current patch level
  128. Xxgrabsc.c           Program source
  129. X
  130. Xxgrabsc.man         Man page for xgrabsc
  131. X
  132. X
  133. X
  134. X+----------------------------+
  135. X|     Bruce Schuchardt       |
  136. X|    Servio Corporation      |
  137. X|      bruce@slc.com         |
  138. X+----------------------------+
  139. X
  140. END_OF_FILE
  141. if test 2167 -ne `wc -c <'README'`; then
  142.     echo shar: \"'README'\" unpacked with wrong size!
  143. fi
  144. # end of 'README'
  145. fi
  146. if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  147.   echo shar: Will not clobber existing file \"'Imakefile'\"
  148. else
  149. echo shar: Extracting \"'Imakefile'\" \(944 characters\)
  150. sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
  151. X/*========================================================================
  152. X *
  153. X * Name - Imakefile
  154. X *
  155. X * Version:    1.3
  156. X *
  157. X * ccsid:    @(#)Imakefile    1.3 - 8/20/90 09:54:45
  158. X * from:     ccs/s.Imakefile
  159. X * date:     8/20/90 09:55:58
  160. X *
  161. X * Description: imake file to build xgrabsc.  Use simple.mak if you
  162. X *              don't have imake.
  163. X *
  164. X *========================================================================
  165. X */
  166. X
  167. X/* change INSTALL_PATH to the directory in which you want xgrabsc installed */
  168. XINSTALL_PATH    = /usr/bin/X11
  169. X
  170. X/* change MAN_PATH to point to your man page top directory */
  171. XMAN_PATH        = /usr/man
  172. X/* change MAN_EXT to the section for xgrabsc */
  173. XMAN_EXT         = 1
  174. X
  175. X/* if you trust your optimizer, change 'g' to 'O' */
  176. XCDEBUGFLAGS     = -g
  177. XLOCAL_LIBRARIES = $(XLIB)
  178. X
  179. XSimpleProgramTarget(xgrabsc)
  180. X
  181. Xinstall::
  182. X    $(INSTALL) -c -s xgrabsc $(INSTALL_PATH)
  183. X    $(INSTALL) -c -m 644 xgrabsc.man \
  184. X        $(MAN_PATH)/man$(MAN_EXT)/xgrabsc.$(MAN_EXT)X
  185. END_OF_FILE
  186. if test 944 -ne `wc -c <'Imakefile'`; then
  187.     echo shar: \"'Imakefile'\" unpacked with wrong size!
  188. fi
  189. # end of 'Imakefile'
  190. fi
  191. if test -f 'cpyright.h' -a "${1}" != "-c" ; then 
  192.   echo shar: Will not clobber existing file \"'cpyright.h'\"
  193. else
  194. echo shar: Extracting \"'cpyright.h'\" \(1576 characters\)
  195. sed "s/^X//" >'cpyright.h' <<'END_OF_FILE'
  196. X#ifndef _COPYRIGHT_
  197. X#define _COPYRIGHT_
  198. X/*========================================================================
  199. X*
  200. X* Name - cpyright.h
  201. X*
  202. X* Version:    1.1
  203. X*
  204. X* ccsid:    @(#)cpyright.h    1.1 - 8/16/90 09:12:34
  205. X* from:     ccs/s.cpyright.h
  206. X* date:     8/20/90 09:56:00
  207. X*
  208. X* Description: copyright information for xgrabsc
  209. X*
  210. X*========================================================================
  211. X*
  212. X* Dithering and Halftoning code:
  213. X* Copyright 1989, 1990 Jim Frost
  214. X*
  215. X* All other code:
  216. X* Copyright (C) 1990 Bruce Schuchardt
  217. X*
  218. X* Permission to use, copy, modify, distribute, and sell this software
  219. X* and its documentation for any purpose is hereby granted without fee,
  220. X* provided that the above copyright notice appear in all copies and
  221. X* that both that copyright notice and this permission notice appear
  222. X* in supporting documentation.  The author makes no representations
  223. X* about the suitability of this software for any purpose.  It is
  224. X* provided "as is" without express or implied warranty.
  225. X*
  226. X* THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  227. X* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
  228. X* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  229. X* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  230. X* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  231. X* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
  232. X* USE OR PERFORMANCE OF THIS SOFTWARE.
  233. X*/
  234. X
  235. Xstatic char *XLoadImage_Copyright= "Copyright (C) 1989 Jim Frost";
  236. Xstatic char *Copyright = "Copyright (C) 1990 Bruce Schuchardt";
  237. X#endif
  238. X
  239. END_OF_FILE
  240. if test 1576 -ne `wc -c <'cpyright.h'`; then
  241.     echo shar: \"'cpyright.h'\" unpacked with wrong size!
  242. fi
  243. # end of 'cpyright.h'
  244. fi
  245. if test -f 'xgrabsc.c' -a "${1}" != "-c" ; then 
  246.   echo shar: Will not clobber existing file \"'xgrabsc.c'\"
  247. else
  248. echo shar: Extracting \"'xgrabsc.c'\" \(38224 characters\)
  249. sed "s/^X//" >'xgrabsc.c' <<'END_OF_FILE'
  250. X/*========================================================================
  251. X *
  252. X * Name - xgrabsc.c
  253. X *
  254. X * Version:    1.4
  255. X *
  256. X * ccsid:    @(#)xgrabsc.c    1.4 - 8/20/90 09:55:19
  257. X * from:     ccs/s.xgrabsc.c
  258. X * date:     8/20/90 09:56:02
  259. X *
  260. X * Copyright (c) 1990 Bruce Schuchardt.
  261. X * Read the file cpyright.h for full copyright information.
  262. X *  
  263. X *
  264. X * Description: 
  265. X *
  266. X * xgrabsc - grab screen images and store in files
  267. X *
  268. X *========================================================================
  269. X */
  270. X
  271. X#include "cpyright.h"
  272. X#include "patchlevel.h"
  273. X
  274. X#include <stdio.h>
  275. X
  276. X#include <X11/Xos.h>
  277. X#include <X11/Xlib.h>
  278. X#include <X11/Xutil.h>
  279. X#include <X11/cursorfont.h>
  280. X#include <X11/Xatom.h>
  281. X#include <X11/XWDFile.h>
  282. X#ifndef CARD32
  283. X#include <X11/Xmd.h>
  284. X#endif
  285. X
  286. X#define MAX_CELLS  256
  287. X#define TRUE  1
  288. X#define FALSE 0
  289. X
  290. Xtypedef unsigned char byte;
  291. Xtypedef unsigned long dw;
  292. Xtypedef unsigned int  word;
  293. X
  294. X
  295. X
  296. Xtypedef struct {
  297. X  XImage *ximage;
  298. X  word numcells;
  299. X  word red[MAX_CELLS], green[MAX_CELLS], blue[MAX_CELLS];
  300. X  byte used[MAX_CELLS];
  301. X} imageInfo;
  302. X
  303. X
  304. XDisplay *hDisplay;
  305. Xint      hScreen;
  306. XWindow   hRoot;
  307. Xint      displayCells;
  308. Xchar    *programName;
  309. Xchar    *imageName;
  310. X
  311. Xint      patchLevel = XGRABSC_PATCHLEVEL;
  312. Xint      verbose;
  313. X
  314. Xword nr[MAX_CELLS], ng[MAX_CELLS], nb[MAX_CELLS];
  315. X
  316. X
  317. X
  318. X
  319. X
  320. X
  321. X/*
  322. X * Alter colors by setting or clearing bits in rgb values.
  323. X * This effectively reduces the depth of the image, causing the
  324. X * number of colors used to be reduced.  Equivalent colors are
  325. X * merged in the image, and the used flags of remapped colors are
  326. X * cleared.
  327. X *
  328. X * The number of eliminated colormap entries is returned.  The colormap
  329. X * is not compressed.
  330. X */
  331. XalterPlanes(image, modeIsAnd, bits)
  332. X  imageInfo *image;
  333. X  int modeIsAnd;      /* if TRUE, combine mask with AND; if FALSE, use OR */
  334. X  unsigned int bits;
  335. X{
  336. X  int nc, cidx, ridx, h, w;
  337. X  long p;
  338. X  XImage *ximage = image->ximage;
  339. X  long map[MAX_CELLS];
  340. X  int remapCount;
  341. X  word mask;
  342. X  
  343. X  if (ximage->depth <= 1)
  344. X    return 0;
  345. X
  346. X  mask = 0xFFFF ^ ((1 << (bits+8)) - 1);
  347. X  if (!modeIsAnd)
  348. X    mask = ~mask & 0xFFFF;
  349. X
  350. X  if (verbose) {
  351. X    fprintf(stderr, "%s: %s color with mask %x...", programName,
  352. X            modeIsAnd? "ANDing" : "ORing", mask);
  353. X    fflush(stderr);
  354. X  }
  355. X
  356. X  nc = image->numcells;
  357. X  if (modeIsAnd)
  358. X    for (cidx=0; cidx<nc; cidx++) {
  359. X      nr[cidx] = image->red[cidx]   & mask;
  360. X      ng[cidx] = image->green[cidx] & mask;
  361. X      nb[cidx] = image->blue[cidx]  & mask;
  362. X    }
  363. X  else
  364. X    for (cidx=0; cidx<nc; cidx++) {
  365. X      nr[cidx] = image->red[cidx]   | mask;
  366. X      ng[cidx] = image->green[cidx] | mask;
  367. X      nb[cidx] = image->blue[cidx]  | mask;
  368. X    }
  369. X
  370. X  /* now eliminate redundant colors */
  371. X  for (cidx=0; cidx<nc; cidx++)
  372. X    map[cidx] = cidx;
  373. X  remapCount = 0;
  374. X  for (cidx=0; cidx<nc; cidx++)
  375. X    if (image->used[cidx])
  376. X      for (ridx=cidx+1; ridx<nc; ridx++)
  377. X        if (image->used[ridx]  &&
  378. X            nr[cidx]==nr[ridx] &&
  379. X            ng[cidx]==ng[ridx] &&
  380. X            nb[cidx]==nb[ridx]) {
  381. X          /* the colors match - remap this pixel to the one we're scanning with */
  382. X          map[ridx] = cidx;
  383. X          image->used[ridx] = FALSE;
  384. X          remapCount++;
  385. X        }
  386. X
  387. X  memcpy(image->red,   nr, nc*sizeof(word));
  388. X  memcpy(image->green, ng, nc*sizeof(word));
  389. X  memcpy(image->blue,  nb, nc*sizeof(word));
  390. X
  391. X  /* remap redundant pixels in the image */
  392. X  if (remapCount)
  393. X    for (h=0; h<ximage->height; h++)
  394. X      for (w=0; w<ximage->width; w++) {
  395. X        p = XGetPixel(ximage, w, h);
  396. X        if (p != map[p])
  397. X          XPutPixel(ximage, w, h, map[p]);
  398. X      }
  399. X
  400. X  if (verbose)
  401. X    fprintf(stderr, "  %d colors remapped\n", remapCount, nc);
  402. X  return remapCount;
  403. X}
  404. X
  405. X
  406. X
  407. X
  408. X
  409. X/* Brighten or darken colors in the image by the given amount ('percent').
  410. X * The amount is an integer that, if less than 100 will darken the image
  411. X * and if greater than 100 will brighten the image.  After modifying
  412. X * colors equivalent colors are merged (as in alterPlanes).  The number
  413. X * of eliminated colors is returned.
  414. X */
  415. XbrightenColors(image, percent)
  416. X  imageInfo *image;
  417. X  int percent;
  418. X{
  419. X  int nc, cidx, ridx, h, w;
  420. X  long p;
  421. X  XImage *ximage = image->ximage;
  422. X  float  adjustment;
  423. X  long map[MAX_CELLS];
  424. X  int remapCount;
  425. X  dw new;
  426. X
  427. X  if (ximage->depth <= 1)
  428. X    return 0;
  429. X
  430. X  if (verbose) {
  431. X    fprintf(stderr, "%s: adjusting intensity by %d...", programName, percent);
  432. X    fflush(stderr);
  433. X  }
  434. X
  435. X  adjustment = (float)percent / 100.0;
  436. X  nc = image->numcells;
  437. X  for (cidx=0; cidx<nc; cidx++) {
  438. X    new = image->red[cidx] * adjustment;
  439. X    if (new > (dw)0xFFFF) new = (dw)0xFFFF;
  440. X    nr[cidx] = new;
  441. X    new = image->green[cidx] * adjustment;
  442. X    if (new > (dw)0xFFFF) new = (dw)0xFFFF;
  443. X    ng[cidx] = new;
  444. X    new = image->blue[cidx] * adjustment;
  445. X    if (new > (dw)0xFFFF) new = (dw)0xFFFF;
  446. X    nb[cidx] = new;
  447. X  }
  448. X
  449. X  /* now eliminate redundant colors */
  450. X  for (cidx=0; cidx<nc; cidx++)
  451. X    map[cidx] = cidx;
  452. X  remapCount = 0;
  453. X  for (cidx=0; cidx<nc; cidx++)
  454. X    if (image->used[cidx])
  455. X      for (ridx=cidx+1; ridx<nc; ridx++)
  456. X        if (image->used[ridx]  &&
  457. X            nr[cidx]==nr[ridx] &&
  458. X            ng[cidx]==ng[ridx] &&
  459. X            nb[cidx]==nb[ridx]) {
  460. X          map[ridx] = cidx;
  461. X          image->used[ridx] = FALSE;
  462. X          remapCount++;
  463. X        }
  464. X
  465. X  memcpy(image->red,   nr, nc*sizeof(word));
  466. X  memcpy(image->green, ng, nc*sizeof(word));
  467. X  memcpy(image->blue,  nb, nc*sizeof(word));
  468. X
  469. X  /* remap redundant pixels in the image */
  470. X  if (remapCount)
  471. X    for (h=0; h<ximage->height; h++)
  472. X      for (w=0; w<ximage->width; w++) {
  473. X        p = XGetPixel(ximage, w, h);
  474. X        if (p != map[p])
  475. X          XPutPixel(ximage, w, h, map[p]);
  476. X      }
  477. X
  478. X
  479. X  if (verbose)
  480. X    fprintf(stderr, "  %d colors remapped\n", remapCount, nc);
  481. X
  482. X  return remapCount;
  483. X}
  484. X
  485. X
  486. X
  487. X
  488. X
  489. X/*
  490. X * Compress the colors used in an XImage so that all pixel values are
  491. X * adjacent.  Alters the rgb color tables and the XImage data values.
  492. X */
  493. XcompressColormap(image)
  494. X  imageInfo *image;
  495. X{
  496. X  XImage *ximage = image->ximage;
  497. X  long map[MAX_CELLS];
  498. X  int  ncolors, w, h, m;
  499. X  long p;
  500. X  
  501. X  if (ximage->depth <= 1  ||  image->numcells > MAX_CELLS)
  502. X    return;
  503. X
  504. X  if (verbose) {
  505. X    fprintf(stderr, "%s: compressing colormap...", programName);
  506. X    fflush(stderr);
  507. X  }
  508. X  ncolors = 0;
  509. X  /* map[] is indexed by old pixel values.  It delivers new, compressed,
  510. X   * pixel values. */
  511. X  for (m=0; m<MAX_CELLS; m++) map[m] = MAX_CELLS+1;
  512. X  /* bludgeon through the whole image and remap each pixel value */
  513. X  for (h=0; h<ximage->height; h++) {
  514. X    for (w=0; w<ximage->width; w++) {
  515. X      /* Get the pixel index and see if it has been used or not.
  516. X       * Then remap the pixel */
  517. X      p = XGetPixel(ximage, w, h);
  518. X      if (map[p] == MAX_CELLS+1) {
  519. X        map[p] = ncolors;
  520. X        ncolors++;
  521. X      }
  522. X      if (p != map[p])
  523. X        XPutPixel(ximage, w, h, map[p]);
  524. X    }
  525. X  }
  526. X  /* now compress the color table */
  527. X  memset(image->used, 0, MAX_CELLS);
  528. X  for (m=0; m<MAX_CELLS; m++) {
  529. X    if (map[m] != MAX_CELLS+1) {
  530. X      p = map[m];
  531. X      nr[p] = image->red[m];
  532. X      ng[p] = image->green[m];
  533. X      nb[p] = image->blue[m];
  534. X      image->used[p] = TRUE;
  535. X    }
  536. X  }
  537. X  memcpy(image->red,   nr, ncolors*sizeof(word));
  538. X  memcpy(image->green, ng, ncolors*sizeof(word));
  539. X  memcpy(image->blue,  nb, ncolors*sizeof(word));
  540. X  image->numcells = ncolors;
  541. X  if (verbose)
  542. X    fprintf(stderr, "  %d colors used\n", ncolors);
  543. X}
  544. X
  545. X
  546. X
  547. X
  548. X
  549. X/*
  550. X * Get the image bounded by the given rectangle.
  551. X * The associated colormap information is also extracted and returned.
  552. X * TRUE is returned if an image was successfully grabbed, and FALSE
  553. X * otherwise.
  554. X */
  555. XgetImage(xrect, image)
  556. X  XRectangle *xrect;
  557. X  imageInfo *image;
  558. X{
  559. X  XImage *ximage;
  560. X  int depth, ncolors, cmapSize, numCmaps;
  561. X  int h, w;
  562. X  long i;
  563. X  XColor colors[MAX_CELLS];
  564. X  Colormap *cmaps, cmap;
  565. X
  566. X  if (xrect->width == 0  || xrect->height == 0)
  567. X    return FALSE;
  568. X
  569. X  depth  = DefaultDepth(hDisplay, hScreen);
  570. X  ximage = XGetImage(hDisplay, hRoot,
  571. X            xrect->x, xrect->y, xrect->width, xrect->height, AllPlanes,
  572. X            depth==1 ? XYPixmap : ZPixmap);
  573. X  image->ximage = ximage;
  574. X
  575. X  /* get the colormap info too */
  576. X
  577. X  cmaps = XListInstalledColormaps(hDisplay, hRoot, &numCmaps);
  578. X  if (numCmaps == 0)
  579. X    cmap = DefaultColormap(hDisplay, hScreen);
  580. X  else {
  581. X    cmap = *cmaps;
  582. X    if (numCmaps > 1)
  583. X      printf(stderr,
  584. X        "%s: more than one colormap found - using first encountered",
  585. X        programName);
  586. X  }
  587. X  XFree(cmaps);
  588. X
  589. X  ncolors = DisplayCells(hDisplay, hScreen);
  590. X  /* this won't cut the mustard for DirectColor */
  591. X  for (i=0; i<ncolors; i++)
  592. X    colors[i].pixel = i;
  593. X      
  594. X  XQueryColors(hDisplay, cmap, colors, ncolors);
  595. X  for (i=0; i<ncolors; i++) {
  596. X    image->red[i]   = colors[i].red;
  597. X    image->green[i] = colors[i].green;
  598. X    image->blue[i]  = colors[i].blue;
  599. X  }
  600. X
  601. X  /* figure out which colormap entries are actually used by the image */
  602. X  ncolors = cmapSize = 0;
  603. X  memset(image->used, 0, MAX_CELLS);
  604. X  for (h=0; h<ximage->height; h++)
  605. X    for (w=0; w<ximage->width; w++) {
  606. X      i = XGetPixel(ximage, w, h);
  607. X      if (!image->used[i]) {
  608. X        image->used[i] = TRUE;
  609. X        if (i+1 > cmapSize)      /* keep track of colormap size */
  610. X          cmapSize = i+1;
  611. X        ncolors++;
  612. X      }
  613. X    }
  614. X  image->numcells = cmapSize;
  615. X  if (verbose)
  616. X    fprintf(stderr, "%s: image has %d colors\n", programName, ncolors);
  617. X
  618. X  return TRUE;
  619. X}
  620. X
  621. X
  622. X
  623. X/*
  624. X * Let the user stretch a rectangle on the screen and return its values.
  625. X * It may be wise to grab the server before calling this routine.  If the
  626. X * screen is allowed to change during XOR drawing video droppings may result.
  627. X */
  628. XgetRectangle(xrect)
  629. X  XRectangle *xrect;
  630. X{
  631. X  XEvent event;
  632. X  unsigned int mask, x, y, rootx, rooty;
  633. X  GC gc;
  634. X  Cursor pointer;
  635. X  int boxDrawn = False;
  636. X  int rx, ry, rw, rh;
  637. X  Window root, child;
  638. X  int discarded;
  639. X  
  640. X  /* get some cursors for rectangle formation */
  641. X  pointer = XCreateFontCursor(hDisplay, XC_crosshair);
  642. X
  643. X  /* grab the pointer */
  644. X  if (GrabSuccess != XGrabPointer(hDisplay, hRoot, False, ButtonPressMask,
  645. X        GrabModeAsync, GrabModeAsync, hRoot, pointer, CurrentTime)) {
  646. X    fprintf(stderr,"%s - could not grab pointer!\n", programName);
  647. X    exit(3);
  648. X  }
  649. X
  650. X  /* create a graphics context to draw with */
  651. X  gc = XCreateGC(hDisplay, hRoot, 0, NULL);
  652. X  if (!gc) {
  653. X    fprintf(stderr,"%s - could not get drawing resources\n", programName);
  654. X    exit(3);
  655. X  }
  656. X  XSetSubwindowMode(hDisplay, gc, IncludeInferiors);
  657. X  XSetForeground(hDisplay, gc, 255);
  658. X  XSetFunction(hDisplay, gc, GXxor);
  659. X
  660. X  /* get a button-press and pull out the root location */
  661. X  XMaskEvent(hDisplay, ButtonPressMask, &event);
  662. X  rootx = rx = event.xbutton.x_root;
  663. X  rooty = ry = event.xbutton.y_root;
  664. X  
  665. X  /* get pointer motion events */
  666. X  XChangeActivePointerGrab(hDisplay, ButtonMotionMask | ButtonReleaseMask,
  667. X        pointer, CurrentTime);
  668. X
  669. X
  670. X  /* MAKE_RECT converts the original root coordinates and the event root
  671. X   * coordinates into a rectangle in xrect */
  672. X#define MAKE_RECT(etype) \
  673. X  x = event.etype.x_root;       \
  674. X  y = event.etype.y_root;       \
  675. X  rw  = x - rootx;              \
  676. X  if (rw  < 0) rw  = -rw;       \
  677. X  rh  = y - rooty;              \
  678. X  if (rh  < 0) rh  = -rh;       \
  679. X  rx = x < rootx ? x : rootx;   \
  680. X  ry = y < rooty ? y : rooty
  681. X
  682. X  /* loop to let the user drag a rectangle */
  683. X  while (TRUE) {
  684. X    XNextEvent(hDisplay, &event);
  685. X    switch(event.type) {
  686. X      case ButtonRelease:
  687. X        if (boxDrawn) {
  688. X          XDrawRectangle(hDisplay, hRoot, gc, rx, ry, rw, rh);
  689. X          boxDrawn = False;
  690. X        }
  691. X        XFlush(hDisplay);
  692. X        /* record the final location */
  693. X        MAKE_RECT(xbutton);
  694. X        /* release resources */
  695. X        XFreeGC(hDisplay, gc);
  696. X        XFreeCursor(hDisplay, pointer);
  697. X        xrect->x      = rx;
  698. X        xrect->y      = ry;
  699. X        xrect->width  = rw;
  700. X        xrect->height = rh;
  701. X        XUngrabPointer(hDisplay, CurrentTime);
  702. X        if (verbose)
  703. X          fprintf(stderr, "%s: rectangle is %d@%d,  %dx%d\n", programName,
  704. X              xrect->x, xrect->y, xrect->width, xrect->height);
  705. X        return True;
  706. X      case MotionNotify:
  707. X        if (boxDrawn) {
  708. X          XDrawRectangle(hDisplay, hRoot, gc, rx, ry, rw, rh);
  709. X          boxDrawn = False;
  710. X        }
  711. X        /* discard incoming motion notifies while we handle this one */
  712. X        discarded = False;
  713. X        while (XCheckTypedEvent(hDisplay, MotionNotify, &event))
  714. X          {}
  715. X        MAKE_RECT(xmotion);
  716. X        XDrawRectangle(hDisplay, hRoot, gc, rx, ry, rw, rh);
  717. X        boxDrawn = True;
  718. X        break;
  719. X    }
  720. X  }
  721. X}
  722. X
  723. X
  724. X
  725. X
  726. X/*
  727. X * convert a pixmap image into a bitmap image
  728. X */
  729. Xpixmap2bitmap(image)
  730. X  imageInfo *image;
  731. X{
  732. X  XImage *ximage = image->ximage;
  733. X  int x, y;
  734. X  word v, black, mid;
  735. X  dw total, blackrgb, midrgb, lowDelta, l;
  736. X  XImage *newImage;
  737. X  byte *newBytes;
  738. X  int usedCount;
  739. X  
  740. X  if (ximage->bits_per_pixel == 1  ||  image->numcells < 1)
  741. X    return;
  742. X
  743. X  /* get the darkest color */
  744. X  blackrgb = 0x2FFFD;  /* 3 * 0xFFFF == white */
  745. X  usedCount = total = 0;
  746. X  for (x=0; x<image->numcells; x++) {
  747. X    if (image->used[x]) {
  748. X      l = (unsigned)image->red[x]
  749. X          +(unsigned)image->green[x]
  750. X          +(unsigned)image->blue[x];
  751. X      if (l <= blackrgb) {
  752. X        black = x;
  753. X        blackrgb = l;
  754. X      }
  755. X      total += l;
  756. X      usedCount++;
  757. X    }
  758. X  }
  759. X  /* now find the mid color and use it as the cut-off for black */
  760. X  midrgb = total / usedCount;
  761. X  lowDelta = 0x2FFFD;
  762. X  for (x=0; x<image->numcells; x++) {
  763. X    if (image->used[x]) {
  764. X      l = (unsigned)image->red[x]
  765. X          +(unsigned)image->green[x]
  766. X          +(unsigned)image->blue[x];
  767. X      l -= midrgb;
  768. X      if (l < lowDelta) {
  769. X        mid = x;
  770. X        lowDelta = l;
  771. X      }
  772. X    }
  773. X  }
  774. X  midrgb = (unsigned)image->red[mid]
  775. X           +(unsigned)image->green[mid]
  776. X           +(unsigned)image->blue[mid];
  777. X    
  778. X  /* create a bitmap image */
  779. X  x = (ximage->width + 7) / 8;
  780. X  newBytes = (byte *)malloc(x * ximage->height);
  781. X  memset(newBytes, 0, x * ximage->height);
  782. X  newImage = XCreateImage(hDisplay, DefaultVisual(hDisplay, hScreen),
  783. X                1, XYBitmap, 0, newBytes, ximage->width, ximage->height,
  784. X                0, x);
  785. X  if (!newImage) {
  786. X    fprintf(stderr, "%s: unable to create bitmap for conversion\n",
  787. X      programName);
  788. X    XCloseDisplay(hDisplay);
  789. X    exit(3);
  790. X  }
  791. X  /* pound the pixels into it */
  792. X  for (y = 0; y < ximage->height; y++) {
  793. X    for (x = 0; x < ximage->width; x++) {
  794. X      v = XGetPixel(ximage, x, y);
  795. X      l = (dw)image->red[v]+(dw)image->green[v]+(dw)image->blue[v];
  796. X      XPutPixel(newImage, x, y, l<midrgb? 1 : 0);
  797. X    }
  798. X  }
  799. X  free(ximage->data);
  800. X  memcpy(ximage, newImage, sizeof(XImage));
  801. X  free(newImage);
  802. X
  803. X  image->numcells = 0;
  804. X}
  805. X
  806. X
  807. X
  808. X
  809. X
  810. X
  811. X
  812. X#define GRAYS    17 /* ((4 * 4) + 1) patterns for a good dither */
  813. X#define GRAYSTEP ((dw)(65536 * 3) / GRAYS)
  814. X
  815. Xstatic byte DitherBits[GRAYS][4] = {
  816. X  0xf, 0xf, 0xf, 0xf,
  817. X  0xe, 0xf, 0xf, 0xf,
  818. X  0xe, 0xf, 0xb, 0xf,
  819. X  0xa, 0xf, 0xb, 0xf,
  820. X  0xa, 0xf, 0xa, 0xf,
  821. X  0xa, 0xd, 0xa, 0xf,
  822. X  0xa, 0xd, 0xa, 0x7,
  823. X  0xa, 0x5, 0xa, 0x7,
  824. X  0xa, 0x5, 0xa, 0x5,
  825. X  0x8, 0x5, 0xa, 0x5,
  826. X  0x8, 0x5, 0x2, 0x5,
  827. X  0x0, 0x5, 0x2, 0x5,
  828. X  0x0, 0x5, 0x0, 0x5,
  829. X  0x0, 0x4, 0x0, 0x5,
  830. X  0x0, 0x4, 0x0, 0x1,
  831. X  0x0, 0x0, 0x0, 0x1,
  832. X  0x0, 0x0, 0x0, 0x0
  833. X};
  834. X
  835. Xstatic byte DitherRevBits[GRAYS][4] = {  /* DitherBits with LSBFirst */
  836. X  0xf, 0xf, 0xf, 0xf,
  837. X  0x7, 0xf, 0xf, 0xf,
  838. X  0x7, 0xf, 0xd, 0xf,
  839. X  0x5, 0xf, 0xd, 0xf,
  840. X  0x5, 0xf, 0x5, 0xf,
  841. X  0x5, 0xb, 0x5, 0xf,
  842. X  0x5, 0xb, 0x5, 0xe,
  843. X  0x5, 0xa, 0x5, 0xe,
  844. X  0x5, 0xa, 0x5, 0xa,
  845. X  0x1, 0xa, 0x5, 0xa,
  846. X  0x1, 0xa, 0x4, 0xa,
  847. X  0x0, 0xa, 0x4, 0xa,
  848. X  0x0, 0xa, 0x0, 0xa,
  849. X  0x0, 0x2, 0x0, 0xa,
  850. X  0x0, 0x2, 0x0, 0x8,
  851. X  0x0, 0x0, 0x0, 0x8,
  852. X  0x0, 0x0, 0x0, 0x0
  853. X};
  854. X
  855. X/* halftone or dither a color image, changing it into a monochrome
  856. X * image
  857. X */
  858. Xpixmap2halftone(image, dither)
  859. X  imageInfo *image;
  860. X  int dither;           /* if TRUE, dither instead of halftone */
  861. X{
  862. X  XImage *ximage = image->ximage;
  863. X  XImage *newImage;
  864. X  byte   *newBytes, *dp, *ditherBits;
  865. X  word   dindex;  /* index into dither array */
  866. X  dw     color;   /* pixel color */
  867. X  word  *index;   /* index into dither array for a given pixel */
  868. X  word   x, y;    /* random counters */
  869. X  word   x4, y4;
  870. X  word   w, h;
  871. X  int    reversed;
  872. X  register byte *dp2;
  873. X  register byte  bits;
  874. X
  875. X  if (verbose) {
  876. X    fprintf(stderr, "%s: %sing image...", programName,
  877. X        dither? "dither" : "halfton");
  878. X    fflush(stderr);
  879. X  }
  880. X
  881. X  /* create a bitmap image */
  882. X  w = (ximage->width + 7) / 8;
  883. X  if (!dither) w *= 4;
  884. X  h = dither? ximage->height : ximage->height * 4;
  885. X  newBytes = (byte *)malloc(w * h);
  886. X  memset(newBytes, 0, w * h);
  887. X  newImage = XCreateImage(hDisplay, DefaultVisual(hDisplay, hScreen),
  888. X                1, XYBitmap, 0, newBytes,
  889. X                ximage->width * (dither? 1 : 4),
  890. X                ximage->height * (dither? 1 : 4),
  891. X                0, w);
  892. X  if (!newImage) {
  893. X    fprintf(stderr, "%s: unable to create bitmap for conversion\n",
  894. X      programName);
  895. X    XCloseDisplay(hDisplay);
  896. X    exit(3);
  897. X  }
  898. X
  899. X
  900. X  /* if the number of possible pixels isn't very large, build an array
  901. X   * which we index by the pixel value to find the dither array index
  902. X   * by color brightness.  we do this in advance so we don't have to do
  903. X   * it for each pixel.  things will break if a pixel value is greater
  904. X   * than (1 << depth), which is bogus anyway.  this calculation is done
  905. X   * on a per-pixel basis if the colormap is too big.
  906. X   */
  907. X
  908. X  if (ximage->depth <= 16) {
  909. X    index= (word *)malloc(sizeof(word) * MAX_CELLS);
  910. X    if (index)
  911. X      for (x= 0; x < image->numcells; x++) {
  912. X        index[x] =
  913. X          ((dw)(image->red[x])
  914. X           + (dw)(image->green[x])
  915. X           + (dw)(image->blue[x])  ) / GRAYSTEP;
  916. X        if (index[x] >= GRAYS)
  917. X          index[x] = GRAYS - 1;
  918. X      }
  919. X  }
  920. X  else
  921. X    index= NULL;
  922. X
  923. X  /* dither each pixel
  924. X   */
  925. X  reversed = newImage->bitmap_bit_order == LSBFirst;
  926. X  for (y= 0; y < ximage->height; y++) {
  927. X    for (x= 0; x < ximage->width; x++) {
  928. X      color = XGetPixel(ximage, x, y);
  929. X      if (index)
  930. X    dindex= index[color];
  931. X      else {
  932. X    dindex= ((dw)image->red[color]
  933. X         +(dw)image->green[color]
  934. X         +(dw)image->blue[color] ) / GRAYSTEP;
  935. X        if (dindex >= GRAYS)  /* catch rounding errors */
  936. X      dindex= GRAYS - 1;
  937. X      }
  938. X      if (dither) {
  939. X        if (DitherBits[dindex][y & 3] & (1 << (x & 3)))
  940. X           XPutPixel(newImage, x, y, 1);
  941. X      }
  942. X      else { /* halftone */
  943. X        /* loop for the four Y bits in the dither pattern, putting all
  944. X         * four X bits in at once.  if you think this would be hard to
  945. X         * change to be an NxN dithering array, you're right, since we're
  946. X         * banking on the fact that we need only shift the mask based on
  947. X         * whether x is odd or not.  an 8x8 array wouldn't even need that,
  948. X         * but blowing an image up by 64x is probably not a feature.
  949. X         */
  950. X        ditherBits = reversed? &(DitherRevBits[dindex][0])
  951. X                             : &(DitherBits[dindex][0]);
  952. X        x4 = x * 4;
  953. X        y4 = y * 4;
  954. X        for (h= 0; h < 4; h++) {
  955. X          bits = ditherBits[h];
  956. X          for (w=0; w < 4; w++)
  957. X            XPutPixel(newImage, x4+w, y4+h, (bits >> 0) & 1);
  958. X        }
  959. X      }
  960. X    }
  961. X    if (dither)
  962. X      dp += newImage->bytes_per_line;
  963. X    else
  964. X      dp += 4 * newImage->bytes_per_line;
  965. X  }
  966. X  if (verbose)
  967. X    fputc('\n', stderr);
  968. X
  969. X  free(ximage->data);
  970. X  memcpy(ximage, newImage, sizeof(XImage));
  971. X  free(newImage);
  972. X  if (index)
  973. X    free(index);
  974. X
  975. X  image->numcells = 0;
  976. X}
  977. X
  978. X
  979. X
  980. X
  981. X
  982. X/* swap the bits in a byte */
  983. Xswapbits(b)
  984. X  byte b;
  985. X{
  986. X  byte b2;
  987. X  
  988. X  b2 = 0;
  989. X  b2 |= (b & 0x01) << 7;
  990. X  b2 |= (b & 0x02) << 5;
  991. X  b2 |= (b & 0x04) << 3;
  992. X  b2 |= (b & 0x08) << 1;
  993. X  b2 |= (b & 0x10) >> 1;
  994. X  b2 |= (b & 0x20) >> 3;
  995. X  b2 |= (b & 0x40) >> 5;
  996. X  b2 |= (b & 0x80) >> 7;
  997. X  return b2;
  998. X}
  999. X
  1000. X
  1001. X
  1002. X  
  1003. X/* swap the bytes in a long int */
  1004. Xswapbytes(pDblw)
  1005. X  dw *pDblw;
  1006. X  {
  1007. X  union {
  1008. X    dw  dbl;
  1009. X    byte bytes[4];
  1010. X    } cnv;
  1011. X  byte aByte;
  1012. X  
  1013. X  cnv.dbl = *pDblw;
  1014. X  aByte = cnv.bytes[0];
  1015. X  cnv.bytes[0] = cnv.bytes[3];
  1016. X  cnv.bytes[3] = aByte;
  1017. X  aByte = cnv.bytes[1];
  1018. X  cnv.bytes[1] = cnv.bytes[2];
  1019. X  cnv.bytes[2] = aByte;
  1020. X  *pDblw = cnv.dbl;
  1021. X  }
  1022. X
  1023. X
  1024. X
  1025. X/* swap some long ints */
  1026. Xswapdws (bp, n)
  1027. X  register char *bp;
  1028. X  register unsigned n;
  1029. X{
  1030. X  register char c;
  1031. X  register char *ep = bp + n;
  1032. X  register char *sp;
  1033. X
  1034. X  while (bp < ep) {
  1035. X    sp = bp + 3;
  1036. X    c = *sp;
  1037. X    *sp = *bp;
  1038. X    *bp++ = c;
  1039. X    sp = bp + 1;
  1040. X    c = *sp;
  1041. X    *sp = *bp;
  1042. X    *bp++ = c;
  1043. X    bp += 2;
  1044. X  }
  1045. X}
  1046. X
  1047. X
  1048. X
  1049. X/* swap some short ints */
  1050. Xswapwords (bp, n)
  1051. X  register char *bp;
  1052. X  register unsigned n;
  1053. X{
  1054. X  register char c;
  1055. X  register char *ep = bp + n;
  1056. X
  1057. X  while (bp < ep) {
  1058. X    c = *bp;
  1059. X    *bp = *(bp + 1);
  1060. X    bp++;
  1061. X    *bp++ = c;
  1062. X  }
  1063. X}
  1064. X
  1065. X
  1066. X
  1067. X
  1068. X
  1069. X/*
  1070. X * Write an image in Postscript format
  1071. X */
  1072. XwritePostscript(image, outfile)
  1073. X  imageInfo *image;
  1074. X{
  1075. X  XImage *ximage = image->ximage;
  1076. X  XImage *psimage;
  1077. X  double xdpi, ydpi, xscale, yscale;
  1078. X  byte b, *ptr, lmax;
  1079. X  int lm3;
  1080. X  int x, y, i;
  1081. X  int depth, bpl, spb;
  1082. X  int reverse;
  1083. X  int rle, firstrle;
  1084. X  byte rlecount, rlebyte;
  1085. X  dw  rletotal;
  1086. X  long p;
  1087. X  
  1088. X  if (verbose)
  1089. X    fprintf(stderr, "%s: formatting Postscript output\n", programName);
  1090. X
  1091. X  /* use depth as the number of bits in output samples */
  1092. X  depth = ximage->depth;
  1093. X  /* postscript only supports 1, 2, 4, or 8 */
  1094. X  if (depth > 8) depth = 8;     /* max postscript bits/sample */
  1095. X  if (depth < 8 && depth > 4) depth = 8;
  1096. X  if (depth == 3) depth = 4;
  1097. X
  1098. X  bpl = ((ximage->width * depth) + 7) / 8;
  1099. X
  1100. X  if (depth == 1)
  1101. X    psimage = ximage;
  1102. X  else {
  1103. X    /* colors have to be changed to luminescence */
  1104. X    ptr = (byte *)malloc(ximage->height * bpl);
  1105. X    psimage = XCreateImage(hDisplay, DefaultVisual(hDisplay, hScreen),
  1106. X                  depth, depth>1? ZPixmap : XYPixmap,
  1107. X                  0, ptr,
  1108. X                  ximage->width, ximage->height,
  1109. X                  0, bpl);
  1110. X    if (!psimage) {
  1111. X      fprintf(stderr, "%s: could not create image for Postscript conversion\n",
  1112. X        programName);
  1113. X      exit(3);
  1114. X    }
  1115. X  }
  1116. X  
  1117. X  spb = 8 / psimage->bits_per_pixel;    /* samples per byte */
  1118. X
  1119. X  if (depth > 1) {
  1120. X    /* translate colors into luminescence */
  1121. X    lmax = (1 << psimage->bits_per_pixel) - 1;
  1122. X    lm3   = 3 * lmax;
  1123. X    for (y = 0; y < ximage->height; y++) {
  1124. X      for (x = 0; x < ximage->width; x++) {
  1125. X        p = XGetPixel(ximage, x, y);
  1126. X        i = (dw)image->red[p]+(dw)image->green[p]+(dw)image->blue[p];
  1127. X        i = (i * lmax) / lm3;
  1128. X        XPutPixel(psimage, x, y, i);
  1129. X      }
  1130. X    }
  1131. X  }
  1132. X  
  1133. X  /* see if the image will benefit from run-length encoding */
  1134. X  rlecount = 0xff;
  1135. X  rletotal = 0;
  1136. X  for (y=0; y<psimage->height; y++) {
  1137. X    for (x=0, ptr=(byte *)(psimage->data+(y * psimage->bytes_per_line));
  1138. X         x<psimage->width;
  1139. X         x+=spb, ptr++) {
  1140. X      b = *ptr;
  1141. X      if (b != rlebyte || rlecount == 0xff) {
  1142. X        rletotal += 2;
  1143. X        rlecount = 0;
  1144. X        rlebyte  = b;
  1145. X      }
  1146. X      else
  1147. X        rlecount++;
  1148. X    }
  1149. X  }
  1150. X  rle = rletotal < psimage->height * bpl;
  1151. X
  1152. X  fprintf(outfile, "%%!\n");
  1153. X  fprintf(outfile, "%%\n");
  1154. X  fprintf(outfile, "%% Xgrabsc Postscript dump of image '%s'\n", imageName);
  1155. X  fprintf(outfile, "%%\n");
  1156. X  fprintf(outfile, "%%\n");
  1157. X
  1158. X  if (rle) {
  1159. X    fprintf(outfile, "%% run-length encoded.  Savings = %d bytes\n",
  1160. X            (psimage->height * bpl - rletotal) * 2);
  1161. X    fprintf(outfile, "%%\n");
  1162. X    fprintf(outfile, "%%\n");
  1163. X  }
  1164. X
  1165. X  /* standard inch procedure */
  1166. X  fputs("/inch {72 mul} def\n", outfile);
  1167. X
  1168. X  /* define a string to hold image lines */
  1169. X  fprintf(outfile, "/picstr %d string def\n", bpl);
  1170. X  
  1171. X  /* define a string to hold run-length-encoded pairs */
  1172. X  if (rle)
  1173. X    fputs("/rlebuffer 2 string def\n", outfile);
  1174. X
  1175. X  /* define the image plotting procedure */
  1176. X  fputs("/plotimage\n", outfile);
  1177. X
  1178. X    /* parameters for the standard image procedure */
  1179. X    fprintf(outfile, "  {%d %d %d [%d 0 0 -%d 0 %d]\n",
  1180. X          psimage->width, psimage->height, psimage->bits_per_pixel,
  1181. X          psimage->width, psimage->height, psimage->height);
  1182. X  
  1183. X    /* line reading function  */
  1184. X    if (rle) {
  1185. X      fputs("  { currentfile rlebuffer readhexstring pop pop\n", outfile);
  1186. X      fputs("    /nsamples rlebuffer 0 get 1 add store\n", outfile);
  1187. X      fputs("    /lum      rlebuffer 1 get store\n", outfile);
  1188. X      fputs("    /samples  nsamples string store\n", outfile);
  1189. X      fputs("    0 1 nsamples -1 add { samples exch lum put } for\n",
  1190. X            outfile);
  1191. X      fputs("    samples\n", outfile);
  1192. X      fputs("  }\n", outfile);
  1193. X    }
  1194. X    else
  1195. X      fputs("  {currentfile picstr readhexstring pop}\n", outfile);
  1196. X  
  1197. X  fputs("  image\n} def\n", outfile);
  1198. X  
  1199. X
  1200. X  /* save context and move to a nice origin */
  1201. X  fputs("gsave\n", outfile);
  1202. X  
  1203. X
  1204. X  /* scale the image */
  1205. X  xdpi = (((double)DisplayWidth(hDisplay,hScreen)) * 25.4) /
  1206. X          ((double)DisplayWidthMM(hDisplay,hScreen));
  1207. X  ydpi = (((double)DisplayHeight(hDisplay,hScreen)) * 25.4) /
  1208. X          ((double)DisplayHeightMM(hDisplay,hScreen));
  1209. X  xscale = ((double)psimage->width) / xdpi;
  1210. X  yscale = ((double)psimage->height) / ydpi;
  1211. X  if (xscale > 7.5) {
  1212. X    yscale *= 7.5 / xscale;
  1213. X    xscale = 7.5;
  1214. X  }
  1215. X  else if (yscale > 10.0) {
  1216. X    xscale *= 10.0 / yscale;
  1217. X    yscale = 10.0;
  1218. X  }
  1219. X  fprintf(outfile, "%1.2g inch %1.2g inch translate\n",
  1220. X                (8.5 - xscale) / 2.0, (11.0 - yscale) / 2.0);
  1221. X  fprintf(outfile, "%1.2g inch %1.2g inch scale\n", xscale, yscale);
  1222. X  
  1223. X  fputs("plotimage\n", outfile);
  1224. X  
  1225. X
  1226. X  reverse = depth == 1? BlackPixel(hDisplay,hScreen)==1 : FALSE;
  1227. X  rletotal = 0;
  1228. X  rlecount = 0xff;
  1229. X  for (y=0; y<psimage->height; y++) {
  1230. X    for (x=0, ptr=(byte *)(psimage->data+(y * psimage->bytes_per_line));
  1231. X         x<psimage->width;
  1232. X         x+=spb, ptr++) {
  1233. X      b = *ptr;
  1234. X      if (reverse) b = ~b;
  1235. X      if (depth == 1  &&  psimage->bitmap_bit_order == LSBFirst)
  1236. X        b = swapbits(b);
  1237. X      if (rle) {
  1238. X        if (b != rlebyte  ||  rlecount == 0xff) {
  1239. X          if (rletotal)  /* == 0 first time through main loop */
  1240. X            fprintf(outfile, "%02x%02x", rlecount, rlebyte);
  1241. X          rletotal += 2;
  1242. X          if (rletotal % 200 == 0)
  1243. X            fputs("\n", outfile);
  1244. X          rlecount = 0;
  1245. X          rlebyte  = b;
  1246. X        }
  1247. X        else
  1248. X          rlecount++;
  1249. X      }
  1250. X      else
  1251. X        fprintf(outfile, "%02x", b);
  1252. X    }
  1253. X    if (!rle)
  1254. X      fputs("\n", outfile);
  1255. X  }
  1256. X  if (rle  &&  rletotal)
  1257. X    fprintf(outfile, "%02x%02x\n", rlecount, rlebyte);
  1258. X
  1259. X  fputs("\n\n\ngrestore\nshowpage\n", outfile);
  1260. X
  1261. X
  1262. X  if (psimage != ximage) {
  1263. X    free(psimage->data);
  1264. X    free(psimage);
  1265. X  }
  1266. X}
  1267. X
  1268. X
  1269. X
  1270. X
  1271. X
  1272. X
  1273. X
  1274. X
  1275. X
  1276. X/*
  1277. X * Write an image in 'puzzle' format, suitable for loading with
  1278. X * "puzzle -picture".
  1279. X */
  1280. XwritePuzzle(image, outfile)
  1281. X  imageInfo *image;
  1282. X  FILE *outfile;
  1283. X{
  1284. X  XImage *ximage = image->ximage;
  1285. X  int nc, width, height, w, h, cidx;
  1286. X  dw swaptest = 1;
  1287. X
  1288. X  if (verbose)
  1289. X    fprintf(stderr, "%s: formatting Puzzle output\n", programName);
  1290. X
  1291. X  if (ximage->depth > 8) {
  1292. X    fprintf(stderr, "%s: Puzzle converter can't handle depth > 8 yet\n",
  1293. X            programName);
  1294. X    return;
  1295. X  }
  1296. X
  1297. X  nc     = image->numcells;
  1298. X  width  = ximage->width;
  1299. X  height = ximage->height;
  1300. X  if (*(char *)&swaptest) {
  1301. X    swapbytes(&width);
  1302. X    swapbytes(&height);
  1303. X  }
  1304. X  fwrite(&width, 4, 1, outfile);
  1305. X  fwrite(&height, 4, 1, outfile);
  1306. X  fputc(nc, outfile);
  1307. X  for (cidx=0; cidx<nc; cidx++) {
  1308. X    fputc(image->red[cidx]>>8,   outfile);
  1309. X    fputc(image->green[cidx]>>8, outfile);
  1310. X    fputc(image->blue[cidx]>>8,  outfile);
  1311. X  }
  1312. X  for (h=0; h<ximage->height; h++)
  1313. X    if (ximage->bits_per_pixel == 8)
  1314. X      fwrite(ximage->data+(h*ximage->bytes_per_line),ximage->width,1,outfile);
  1315. X    else
  1316. X      /* this won't work if depth > 8 */
  1317. X      for (w=0; w<ximage->width; w++)
  1318. X        fputc(XGetPixel(ximage, w, h), outfile);
  1319. X}
  1320. X
  1321. X
  1322. X
  1323. X
  1324. X
  1325. X
  1326. X
  1327. XwriteXWD(image, outfile)
  1328. X  imageInfo *image;
  1329. X  FILE *outfile;
  1330. X{
  1331. X  XImage   *ximage = image->ximage;
  1332. X  XWDFileHeader header;
  1333. X  Visual   *visual = DefaultVisual(hDisplay, hScreen);
  1334. X  XColor    color;
  1335. X  dw        visMask = (visual->red_mask
  1336. X                      | visual->green_mask
  1337. X                      | visual->blue_mask);
  1338. X  dw        swaptest = 1;
  1339. X  int       i;
  1340. X
  1341. X  if (verbose)
  1342. X    fprintf(stderr, "%s: formatting xwd output\n", programName);
  1343. X
  1344. X  header.header_size    = (CARD32)(sizeof(header)+strlen(imageName)+1);
  1345. X  header.file_version   = (CARD32) XWD_FILE_VERSION;
  1346. X  header.pixmap_format  = (CARD32)(ximage->depth>1? ZPixmap : XYPixmap);
  1347. X  header.pixmap_depth   = (CARD32) ximage->depth;
  1348. X  header.pixmap_width   = (CARD32) ximage->width;
  1349. X  header.pixmap_height  = (CARD32) ximage->height;
  1350. X  header.xoffset        = (CARD32) ximage->xoffset;
  1351. X  header.byte_order     = (CARD32) ximage->byte_order;
  1352. X  header.bitmap_unit    = (CARD32) ximage->bitmap_unit;
  1353. X  header.bitmap_bit_order = (CARD32) ximage->bitmap_bit_order;
  1354. X  header.bitmap_pad     = (CARD32) ximage->bitmap_pad;
  1355. X  header.bits_per_pixel = (CARD32) ximage->bits_per_pixel;
  1356. X  header.bytes_per_line = (CARD32) ximage->bytes_per_line;
  1357. X  header.visual_class   = (CARD32)visual->class;
  1358. X  header.red_mask       = (CARD32)visual->red_mask;
  1359. X  header.green_mask     = (CARD32)visual->green_mask;
  1360. X  header.blue_mask      = (CARD32)visual->blue_mask;
  1361. X  header.bits_per_rgb   = (CARD32)visual->bits_per_rgb;
  1362. X  header.colormap_entries = (CARD32)visual->map_entries;
  1363. X  header.ncolors        = image->numcells;
  1364. X  header.window_width   = (CARD32)ximage->width;
  1365. X  header.window_height  = (CARD32)ximage->height;
  1366. X  header.window_x       = 0;
  1367. X  header.window_y       = 0;
  1368. X  header.window_bdrwidth = 0;
  1369. X
  1370. X  if (*(char *) &swaptest)
  1371. X    swapdws(&header, sizeof(header));
  1372. X
  1373. X  fwrite(&header, sizeof(header), 1, outfile);
  1374. X  fwrite(imageName, 1, strlen(imageName)+1, outfile);
  1375. X
  1376. X  for (i=0; i<image->numcells; i++) {
  1377. X    color.pixel = i;
  1378. X    color.red   = image->red[i];
  1379. X    color.green = image->green[i];
  1380. X    color.blue  = image->blue[i];
  1381. X    color.flags = visMask;
  1382. X    color.pad   = 0;
  1383. X    if (*(char *) &swaptest)
  1384. X      swapwords(&color, sizeof(XColor));
  1385. X    fwrite(&color, sizeof(XColor), 1, outfile);
  1386. X  }
  1387. X
  1388. X  fwrite(ximage->data, ximage->height * ximage->bytes_per_line, 1, outfile);
  1389. X}
  1390. X
  1391. X
  1392. X
  1393. X
  1394. X
  1395. X/*
  1396. X * Write a monochrome image out in Bitmap format.  XWriteBitmapToFile
  1397. X * requires a Pixmap as input & we'd have to invent one before we could
  1398. X * use it.
  1399. X */
  1400. X
  1401. XwriteXYPixmap(image, outfile)
  1402. X  imageInfo *image;
  1403. X  FILE *outfile;
  1404. X{
  1405. X  XImage *ximage = image->ximage;
  1406. X  int w, h;
  1407. X  byte b, *line;
  1408. X  int lcount;
  1409. X  int reverse = BlackPixel(hDisplay, hScreen) == 0;
  1410. X  int swap    = ximage->bitmap_bit_order != LSBFirst;
  1411. X
  1412. X  if (verbose)
  1413. X    fprintf(stderr, "%s: formatting Bitmap output\n", programName);
  1414. X
  1415. X  if (ximage->depth != 1) {
  1416. X    fprintf(stderr, "%s: can't write polychrome images in XY bitmap format\n",
  1417. X      programName);
  1418. X    return;
  1419. X  }
  1420. X
  1421. X  fprintf(outfile, "#define %s_width %d\n",  imageName, ximage->width);
  1422. X  fprintf(outfile, "#define %s_height %d\n", imageName, ximage->height);
  1423. X  fprintf(outfile, "#define %s_x_hot 0\n",   imageName);
  1424. X  fprintf(outfile, "#define %s_y_hot 0\n",   imageName);
  1425. X  fprintf(outfile, "static char %s_bits[] = {\n", imageName);
  1426. X  lcount = 0;
  1427. X  fputs("  ", outfile);
  1428. X  for (h=0; h<ximage->height; h++) {
  1429. X    line = (byte *)(ximage->data + (h * ximage->bytes_per_line));
  1430. X    for (w=0; w<ximage->width; w+=8) {
  1431. X      b = line[w/8];
  1432. X      if (reverse) b = ~b;
  1433. X      if (swap)    b = swapbits(b);
  1434. X      fprintf(outfile, " 0x%02x", b);
  1435. X      if (h<ximage->height || w+8<ximage->width)
  1436. X        fputc(',', outfile);
  1437. X      lcount++;
  1438. X      if (lcount >= 12) {
  1439. X        fputs("\n  ", outfile);
  1440. X        lcount = 0;
  1441. X      }
  1442. X    }
  1443. X  }
  1444. X  fputs("  };\n", outfile);
  1445. X}
  1446. X
  1447. X
  1448. X
  1449. X
  1450. X
  1451. X
  1452. X
  1453. X
  1454. X/*
  1455. X * Write a color image out in Pixmap format, suitable for loading with
  1456. X * "xpd" or "xloadimage".  Note that "xpd" usually fails miserably if
  1457. X * the image is wider than 255 characters in the output file.
  1458. X */
  1459. XwriteZPixmap(image, outfile)
  1460. X  imageInfo *image;
  1461. X  FILE *outfile;
  1462. X{
  1463. X  XImage *ximage = image->ximage;
  1464. X  int nc, width, height, w, h, cidx, cpp;
  1465. X  char mne[MAX_CELLS][3];
  1466. X
  1467. X  if (verbose)
  1468. X    fprintf(stderr, "%s: formatting Pixmap output\n", programName);
  1469. X
  1470. X  nc  = image->numcells;
  1471. X  cpp = image->numcells <= 26? 1 : 2;
  1472. X  fprintf(outfile, "#define %s_format 1\n",   imageName);
  1473. X  fprintf(outfile, "#define %s_width %d\n",   imageName, ximage->width);
  1474. X  fprintf(outfile, "#define %s_height %d\n",  imageName, ximage->height);
  1475. X  fprintf(outfile, "#define %s_ncolors %d\n", imageName, image->numcells);
  1476. X  fprintf(outfile, "#define %s_chars_per_pixel %d\n",     imageName, cpp);
  1477. X  fprintf(outfile, "static char * %s_colors[] = {\n", imageName);
  1478. X  for (cidx=0; cidx<image->numcells; cidx++) {
  1479. X    if (cpp > 1) {
  1480. X      mne[cidx][0] = (char)(cidx / 10) + 'a';
  1481. X      mne[cidx][1] = (char)(cidx % 10) + '0';
  1482. X      mne[cidx][2] = '\0';
  1483. X    }
  1484. X    else {
  1485. X      mne[cidx][0] = (char)cidx + (cidx? 'A' : ' ');
  1486. X      mne[cidx][1] = '\0';
  1487. X    }
  1488. X    fprintf(outfile, "\"%s\", \"#%4.4x%4.4x%4.4x\"\n", mne[cidx],
  1489. X                image->red[cidx], image->green[cidx], image->blue[cidx]);
  1490. X  }
  1491. X  fputs("} ;\n", outfile);
  1492. X  fprintf(outfile, "static char * %s_pixels[] = {\n", imageName);
  1493. X  for (h=0; h<ximage->height; h++) {
  1494. X    fputs("\"", outfile);
  1495. X    for (w=0; w<ximage->width; w++)
  1496. X      fputs(mne[XGetPixel(ximage, w, h)], outfile);
  1497. X    fputs("\",\n", outfile);
  1498. X  }
  1499. X  fputs("} ;\n", outfile);
  1500. X}
  1501. X
  1502. X
  1503. X
  1504. X
  1505. X
  1506. X
  1507. X
  1508. X
  1509. Xmain(argc, argv)
  1510. X  int argc;
  1511. X  char *argv[];
  1512. X{
  1513. X  FILE *outfile;
  1514. X  char *outfileName;
  1515. X  XRectangle xrect;
  1516. X  imageInfo image;
  1517. X  int doAnd, doOr, depth;
  1518. X  int puzzle, xWD, brighten, postscript;
  1519. X  int forceBitmap, grabServer;
  1520. X  int dither, halftone;
  1521. X  int sleepSeconds;
  1522. X  int andBits, orBits;
  1523. X  char c;
  1524. X  char *ptr;
  1525. X  char *display;
  1526. X  int i, nr, nc;
  1527. X  extern char *optarg;
  1528. X  int brightenFactor;
  1529. X  
  1530. X  outfile     = stdout;
  1531. X  outfileName = NULL;
  1532. X  programName = argv[0];
  1533. X  puzzle      = FALSE;
  1534. X  xWD         = FALSE;
  1535. X  brighten    = FALSE;
  1536. X  forceBitmap = FALSE;
  1537. X  halftone    = FALSE;
  1538. X  dither      = FALSE;
  1539. X  grabServer  = TRUE;
  1540. X  postscript  = FALSE;
  1541. X  doAnd       = FALSE;
  1542. X  doOr        = FALSE;
  1543. X  sleepSeconds= 0;
  1544. X  display     = NULL;
  1545. X  verbose     = FALSE;
  1546. X  
  1547. X  while ((c = getopt(argc, argv, "d:no:s:v b:A:BDHO: PWZ")) != EOF)
  1548. X    switch (c) {
  1549. X      case 'd':
  1550. X        display = optarg;
  1551. X        break;
  1552. X      case 'n':
  1553. X        grabServer = FALSE;
  1554. X        break;
  1555. X      case 'o':
  1556. X        outfileName = optarg;
  1557. X        break;
  1558. X      case 's':
  1559. X        sleepSeconds = atoi(optarg);
  1560. X        if (sleepSeconds < 0) sleepSeconds = 0;
  1561. X        break;
  1562. X      case 'v':
  1563. X        verbose = TRUE;
  1564. X        break;
  1565. X
  1566. X
  1567. X
  1568. X
  1569. X      case 'A':
  1570. X        andBits = atoi(optarg);
  1571. X        doAnd = TRUE;
  1572. X        break;
  1573. X      case 'b':
  1574. X        brightenFactor = atoi(optarg);
  1575. X        if (brightenFactor <= 0) {
  1576. X          fprintf(stderr, "%s: brightening factor must be a positive number\n",
  1577. X            programName);
  1578. X          exit(3);
  1579. X        }
  1580. X        brighten = TRUE;
  1581. X        break;
  1582. X      case 'B':
  1583. X        forceBitmap = TRUE;
  1584. X        break;
  1585. X      case 'D':
  1586. X        dither = TRUE;
  1587. X        if (halftone) {
  1588. X          fprintf(stderr,
  1589. X            "%s: both dither and halftone requested.  Ignoring halftone.",
  1590. X            programName);
  1591. X          halftone = FALSE;
  1592. X        }
  1593. X        break;
  1594. X      case 'H':
  1595. X        halftone = TRUE;
  1596. X        if (dither) {
  1597. X          fprintf(stderr,
  1598. X            "%s: both dither and halftone requested.  Ignoring halftone.",
  1599. X            programName);
  1600. X          halftone = FALSE;
  1601. X        }
  1602. X        break;
  1603. X      case 'O':
  1604. X        orBits = atoi(optarg);
  1605. X        doOr = TRUE;
  1606. X        break;
  1607. X
  1608. X
  1609. X
  1610. X
  1611. X      case 'P':
  1612. X        postscript = TRUE;
  1613. X        if (xWD | puzzle) {
  1614. X          fprintf(stderr,
  1615. X            "%s: only one output format allowed.  Using postscript.\n",
  1616. X            programName);
  1617. X          xWD = puzzle = FALSE;
  1618. X        }
  1619. X        break;
  1620. X      case 'W':
  1621. X        xWD = TRUE;
  1622. X        if (puzzle | postscript) {
  1623. X          fprintf(stderr,
  1624. X            "%s: can't do both puzzle and XWD output.  Using XWD.\n",
  1625. X            programName);
  1626. X          puzzle = postscript = FALSE;
  1627. X        }
  1628. X        break;
  1629. X      case 'Z':
  1630. X        puzzle = TRUE;
  1631. X        if (xWD | postscript) {
  1632. X          fprintf(stderr,
  1633. X            "%s: only one output format allowed.  Using puzzle.\n",
  1634. X            programName);
  1635. X          xWD = postscript = FALSE;
  1636. X        }
  1637. X        break;
  1638. X    }
  1639. X
  1640. X  if (!display) display = (char *)getenv("DISPLAY");
  1641. X  hDisplay = XOpenDisplay(display);
  1642. X  if (!hDisplay) {
  1643. X    fprintf(stderr, "%s: could not open X display\n", programName);
  1644. X    exit(3);
  1645. X  }
  1646. X  hScreen  = DefaultScreen(hDisplay);
  1647. X  hRoot    = DefaultRootWindow(hDisplay);
  1648. X
  1649. X  depth  = DefaultDepth(hDisplay, hScreen);
  1650. X  if (DisplayCells(hDisplay, hScreen) > MAX_CELLS) {
  1651. X    fprintf(stderr, "%s: color table is too big for this program\n",
  1652. X      programName);
  1653. X    XCloseDisplay(hDisplay);
  1654. X    exit(3);
  1655. X  }
  1656. X  
  1657. X  /* sleep if asked to do so */
  1658. X  if (sleepSeconds)
  1659. X    sleep(sleepSeconds);
  1660. X  
  1661. X  /* grab the screen if asked to do so */
  1662. X  if (grabServer)
  1663. X    XGrabServer(hDisplay);
  1664. X
  1665. X  /* let the user drag out a rectangle on the screen */
  1666. X  if (!getRectangle(&xrect)) {
  1667. X    XCloseDisplay(hDisplay);
  1668. X    exit(3);
  1669. X  }
  1670. X  
  1671. X  /* get the image bounded by the rectangle */
  1672. X  if (!getImage(&xrect, &image)) {
  1673. X    XCloseDisplay(hDisplay);
  1674. X    exit(3);
  1675. X  }
  1676. X
  1677. X  if (grabServer) {
  1678. X    XUngrabServer(hDisplay);
  1679. X    XFlush(hDisplay);
  1680. X  }
  1681. X
  1682. X  /* do color image processing/conversions */
  1683. X  if (depth >= 2) {
  1684. X    if (brighten)
  1685. X      brightenColors(&image, brightenFactor);
  1686. X    if (doAnd)
  1687. X      alterPlanes(&image, TRUE, andBits);
  1688. X    if (doOr)
  1689. X      alterPlanes(&image, FALSE, orBits);
  1690. X
  1691. X    if (forceBitmap) {
  1692. X      pixmap2bitmap(&image);
  1693. X      depth = 1;
  1694. X    }
  1695. X    else if (halftone | dither)
  1696. X      pixmap2halftone(&image, dither);
  1697. X    else
  1698. X      compressColormap(&image);
  1699. X  }
  1700. X
  1701. X
  1702. X  /* open the output stream */
  1703. X  if (outfileName) {
  1704. X    outfile = fopen(outfileName, "w");
  1705. X    if (!outfile) {
  1706. X      fprintf(stderr, "%s: ", programName);
  1707. X      perror(outfileName);
  1708. X      exit(3);
  1709. X    }
  1710. X    ptr = rindex(outfileName, '.');
  1711. X    if (ptr) *ptr = '\0';
  1712. X    imageName = rindex(outfileName, '/');
  1713. X    if (imageName) imageName++;
  1714. X    else imageName = outfileName;
  1715. X  }
  1716. X  else
  1717. X    imageName = "unnamed";   /* default for image names */
  1718. X
  1719. X
  1720. X  /* garbage in --> garbage out */
  1721. X  if (postscript)
  1722. X    writePostscript(&image, outfile);
  1723. X  else if (xWD)
  1724. X    writeXWD(&image, outfile);
  1725. X  else if (puzzle)
  1726. X    writePuzzle(&image, outfile);
  1727. X  else if (image.ximage->depth <= 1)
  1728. X    writeXYPixmap(&image, outfile);
  1729. X  else
  1730. X    writeZPixmap(&image, outfile);
  1731. X
  1732. X  XDestroyImage(image.ximage);
  1733. X  XCloseDisplay(hDisplay);
  1734. X  if (outfileName)
  1735. X    fclose(outfile);
  1736. X
  1737. X  exit(0);
  1738. X}
  1739. X
  1740. END_OF_FILE
  1741. if test 38224 -ne `wc -c <'xgrabsc.c'`; then
  1742.     echo shar: \"'xgrabsc.c'\" unpacked with wrong size!
  1743. fi
  1744. # end of 'xgrabsc.c'
  1745. fi
  1746. if test -f 'xgrabsc.man' -a "${1}" != "-c" ; then 
  1747.   echo shar: Will not clobber existing file \"'xgrabsc.man'\"
  1748. else
  1749. echo shar: Extracting \"'xgrabsc.man'\" \(7589 characters\)
  1750. sed "s/^X//" >'xgrabsc.man' <<'END_OF_FILE'
  1751. X.\"========================================================================
  1752. X.\"
  1753. X.\" Name - xgrabsc.man
  1754. X.\"
  1755. X.\" Version:    1.2
  1756. X.\"
  1757. X.\" ccsid:    @(#)xgrabsc.man    1.2 - 8/17/90 09:07:01
  1758. X.\" from:     ccs/s.xgrabsc.man
  1759. X.\" date:     8/20/90 09:56:03
  1760. X.\"
  1761. X.\" Copyright (C) 1990, Bruce Schuchardt
  1762. X.\" See the end of this document for full copyright information.
  1763. X.\"
  1764. X.\" Description:  Man page for xgrabsc
  1765. X.\"
  1766. X.\"========================================================================
  1767. X.\"
  1768. X.TH XGRABSC 1X
  1769. X.\"
  1770. X.SH NAME
  1771. Xxgrabsc \- grab rectangular screen images and store in files
  1772. X.\"
  1773. X.SH SYNTAX
  1774. X\fIxgrabsc\fR \ [options]
  1775. X.\"
  1776. X.SH DESCRIPTION
  1777. X\fIxgrabsc\fR lets you grab arbitrary rectangular images from an
  1778. XX server and writes them to standard output in a variety of formats.
  1779. X.PP
  1780. XCommand line options also allow reduction of colormaps, halftoning
  1781. Xand dithering of color images, and direct mapping of color images
  1782. Xto monochrome.
  1783. X.PP
  1784. XThe default output formats are X Pixmap for color images and X Bitmap for
  1785. Xmonochrome bitmaps.
  1786. X.SH OPTIONS
  1787. X.TP 8
  1788. X-d \fIdisplayName\fP
  1789. XUse an alternate display.
  1790. X.TP
  1791. X-n
  1792. XInhibit server grabs.  Normally xgrabsc will "grab" the server so
  1793. Xthat the screen is frozen while a rectangle is selected and the image
  1794. Xis extracted.  If the screen is not frozen, rubber-banding may cause
  1795. Xvideo droppings on portions of the screen that are changing.
  1796. X.TP
  1797. X-o \fIoutput-file\fP
  1798. XWrite output to \fIoutput-file\fP instead of standard output.
  1799. X.TP
  1800. X-s \fIseconds\fP
  1801. XSleep for \fIseconds\fP seconds before commencing operation.  This
  1802. Xshould be used if you need some time to get the target image ready.
  1803. X.TP
  1804. X-v
  1805. XDisplay processing information on standard error output (stderr).
  1806. X.sp 3
  1807. X.TP
  1808. X-b \fIpercent\fR
  1809. Xbrighten or darken the image by \fIpercent\fR.  Percentages are given
  1810. Xas integers.  As in \fIxloadimage\fR, 100 is the base and a larger
  1811. Xnumber will brighten the image while a smaller number will darken the
  1812. Ximage.
  1813. X.TP
  1814. X-A \fIandBits\fR
  1815. XClear all colormap bits up to the given plane.  This has the effect of
  1816. Xdarkening the image somewhat and shrinking the apparent depth of the image
  1817. X(and, consequently, the size of the color table).  \fIAndBits\fR should
  1818. Xbe in the range [1-8] inclusive.
  1819. X.TP
  1820. X-O \fIorBits\fR
  1821. XSet all colormap bits up to the given plane.  This brightens the image
  1822. Xsomewhat and also shrinks the apparent depth of the image.  When
  1823. Xboth \-A and \-O are specified, ANDing will occur before ORing.
  1824. X.TP
  1825. X-B
  1826. XConvert the source color image to a monochrome bitmap.  All colors
  1827. Xfalling below the average color intensity are mapped to black.  Others
  1828. Xare mapped to white.
  1829. X.TP
  1830. X-D
  1831. XConvert the source color image to a dithered monochrome bitmap.
  1832. XThis is like halftoning, but resolution is sacrificed to keep the
  1833. Xresulting image the same size as the original.
  1834. X.TP
  1835. X-H
  1836. XConvert the source color image to a halftoned monchrome bitmap.
  1837. XResolution is maintained by increasing the size of the image by
  1838. Xa factor of four on both axes.
  1839. X.sp 3
  1840. X.TP
  1841. X-P
  1842. XWrite output in \fIPostscript\fP format.  Output will be run-length-encoded
  1843. Xif encoding will result in any savings.  The number of bits per
  1844. XPostscript sample is determined by the depth of the image.
  1845. X.TP
  1846. X-W
  1847. XWrite output in \fIxwd\fP format.
  1848. X.TP
  1849. X-Z
  1850. XWrite output in a format suitable for loading into the \fIpuzzle\fP
  1851. Xprogram (see example below).
  1852. X.sp 2
  1853. X.SH PROCESSING ORDER
  1854. XIt is helpful to know the order of processing when multiple processing
  1855. Xoptions are given on the command line.
  1856. X.PP
  1857. XProcessing is done in five phases:  1) set up, 2) obtain image,
  1858. X3) process colors, 4) poly->monochrome conversions, and 5) output conversion.
  1859. X.PP
  1860. XThe set-up phase includes processing command-line options, sleeping,
  1861. Xconnecting to X-Windows, freezing the screen and grabbing the mouse.
  1862. X.PP
  1863. XAfter the mouse is grabbed, rubber-banding occurs until a mouse button
  1864. Xis released.  The image is then pulled from the screen and the mouse
  1865. Xand screen are released.
  1866. X.PP
  1867. XIf the image is not monochrome, the color manipulation functions are
  1868. Xthen applied in this order: brighten, AND, and OR.
  1869. X.PP
  1870. XOnly one polychrome to monochrome conversion is allowed.  If none of
  1871. Xthese is chosen, the color table of a polychrome image is compressed
  1872. Xin preparation for output conversion.
  1873. X.PP
  1874. XThe output stream is then opened and the image is written in the selected
  1875. Xoutput format.
  1876. X.sp 2
  1877. X.SH EXAMPLES
  1878. XThe simplest form of use, giving X11 Bitmap or Pixmap output,  is
  1879. X.sp
  1880. X.ti +5
  1881. Xxgrabsc >outfile.xpm
  1882. X.sp
  1883. X.PP
  1884. XTo write output in \fIPostscript\fP format and send to the printer,
  1885. Xuse
  1886. X.sp
  1887. X.ti +5
  1888. Xxgrabsc -P | lpr
  1889. X.sp
  1890. XIt is sometimes helpful to brighten an image somewhat before it is
  1891. Xformatted for Postscript output.  E.g., to brighten by 30%
  1892. X.sp
  1893. X.ti +5
  1894. Xxgrabsc -Pb 130 | lpr
  1895. X.sp
  1896. X.PP
  1897. XTo write output in \fIpuzzle\fP format and read into the puzzle
  1898. Xprogram, use the commands
  1899. X.sp
  1900. X.ti +5
  1901. Xxgrabsc -Z >outfile.pzl
  1902. X.br
  1903. X.ti +5
  1904. Xpuzzle -picture outfile.pzl
  1905. X.sp
  1906. X.PP
  1907. XTo have xgrabsc sleep for three seconds before rubber-banding, display
  1908. Xprocessing information, and have the result displayed with xwud,
  1909. X.sp
  1910. X.ti +5
  1911. Xxgrabsc -Wvs3 | xwud
  1912. X.sp
  1913. X.PP
  1914. XTo grab an image from another server and then reduce the colormap
  1915. Xto three bits by ANDing, use
  1916. X.sp
  1917. X.ti +5
  1918. Xxgrabsc -dother:0.0 -A5 >outfile.xpm
  1919. X.sp
  1920. XYou will, of course, have to go to the other machine to select the
  1921. Ximage with that machine's mouse.
  1922. X.sp 2
  1923. X.SH LIMITATIONS
  1924. XColormaps larger than 256 entries are not currently supported.
  1925. X.PP
  1926. XThe default screen visual is used as the visual for the image.
  1927. XVisuals are associated with particular windows, and xgrabsc pretends
  1928. Xignorance about any windows but the root.
  1929. X.PP
  1930. XThis software has been tested with StaticGray and 8-plane PseudoColor
  1931. Xon DECStations (using both UWS 2.2 and X11 Release 4).  It has also
  1932. Xbeen tested with 8-plane PseudoColor
  1933. Xon Sun SparcStations using X11 Release 4.
  1934. X.PP
  1935. XX11 Pixmap format is rather verbose.
  1936. XYou may want to run large images through the \fIcompress\fP utility
  1937. Xbefore storing them in a file.  E.g.,
  1938. X.sp
  1939. X.ti +5
  1940. Xxgrabsc | compress >outfile.xpm.Z
  1941. X.sp
  1942. X.SH AUTHOR
  1943. X.nf
  1944. X+----------------------------+
  1945. X|     Bruce Schuchardt       |
  1946. X|    Servio Corporation      |
  1947. X|      bruce@slc.com         |
  1948. X+----------------------------+
  1949. X.fi
  1950. X.sp 2
  1951. X.SH ACKNOWLEGEMENTS
  1952. X.PP
  1953. XSome of the source code for xgrabsc came from
  1954. Xthe xloadimage project by Jim Frost (jimf@saber.com) and others.  Jim's
  1955. Xcopyright has been included both here and in the source code.
  1956. X.PP
  1957. XThe idea for using run-length encoding for Postscript output came from
  1958. Xthe xwd2ps project by Robert Tatar and Craig A. McGowan.
  1959. X.sp 2
  1960. X.SH COPYRIGHT
  1961. XCopyright (c) 1990 Bruce Schuchardt
  1962. X.sp
  1963. XHalftoning and Dithering code 
  1964. XCopyright (c) 1989, 1990 Jim Frost and others.
  1965. X.PP
  1966. X\fIXgrabsc\fR is copywritten material with a very loose copyright
  1967. Xallowing unlimited modification and distribution if the copyright
  1968. Xnotices are left intact.  Various portions are copywritten by various
  1969. Xpeople, but all use a modification of the MIT copyright notice.
  1970. XPlease check the source for complete copyright information.  The
  1971. Xintent is to keep the source free, not to stifle its distribution, so
  1972. Xplease write to me if you have any questions.
  1973. X.pp
  1974. XTHE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  1975. XINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
  1976. XNO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  1977. XCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  1978. XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  1979. XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
  1980. XUSE OR PERFORMANCE OF THIS SOFTWARE.
  1981. X.s 2
  1982. X.SH SEE ALSO
  1983. XX(1X), xwud(1X), xwd2ps(1X), xloadimage(1X), xpm(1X), puzzle(1X),
  1984. Xcompress(1), uncompress(1)
  1985. END_OF_FILE
  1986. if test 7589 -ne `wc -c <'xgrabsc.man'`; then
  1987.     echo shar: \"'xgrabsc.man'\" unpacked with wrong size!
  1988. fi
  1989. # end of 'xgrabsc.man'
  1990. fi
  1991. echo shar: End of archive 1 \(of 2\).
  1992. cp /dev/null ark1isdone
  1993. MISSING=""
  1994. for I in 1 2 ; do
  1995.     if test ! -f ark${I}isdone ; then
  1996.     MISSING="${MISSING} ${I}"
  1997.     fi
  1998. done
  1999. if test "${MISSING}" = "" ; then
  2000.     echo You have unpacked both archives.
  2001.     rm -f ark[1-9]isdone
  2002. else
  2003.     echo You still need to unpack the following archives:
  2004.     echo "        " ${MISSING}
  2005. fi
  2006. ##  End of shell archive.
  2007. exit 0
  2008.  
  2009. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2010.   Bruce Schuchardt          Ph: (503) 629-8383
  2011.   Servio Logic              bruce@servio.SLC.COM
  2012.   Beaverton, OR             uunet!servio!bruce
  2013.  
  2014. dan
  2015. ----------------------------------------------------
  2016. O'Reilly && Associates   argv@sun.com / argv@ora.com
  2017. Opinions expressed reflect those of the author only.
  2018.