[comp.lang.postscript] G3 Fax <-->

galen@hoptoad.uucp (Galen Wolf) (02/16/90)

I'm interested to find any hardware or software which allows translating
electronically between G3 Fax and either plain or encapsulated PostScript.
An example would be receiving into a computer an (E)PS file for display
with something like Display PostScript a document which had originated
on someone else's FAX machine, received with an internal FAX modem.  Also
it would be nice to be able to take the PostScript output of any program
and send it out via the built-in FAX modem to somebody else's FAX machine.
This would of course allow remote scanning of documents into your computer
via a FAX machine, and remote printing of PostScript documents.

			Galen
-- 
galen@toad.com (Galen Wolf 415-469-6409)
{amdahl,lll-crg,nsc,pacbell,pyramid,sun,ucsfcgl,uunet,well}!hoptoad!galen

vac@sam.cs.cmu.edu (Vincent Cate) (02/17/90)

>galen@hoptoad.UUCP (Galen Wolf)
>I'm interested to find any hardware or software which allows translating
>electronically between G3 Fax and either plain or encapsulated PostScript.

I also am interested in this.  Here is what I have found so far.
There is a package called pbmplus that can convert many bitmap formats
into other formats.  Among these is a pbmtog3 and g3topbm.  These handle 
only one-dimensional group III FAX.  PBM stands for "Portable BitMap".  
There is also a pgmtops which can take pbm files, so you can do a:

cat file.g3 | g3topbm | pgmtops | lpr

And it works just fine.  You can FTP pbmplus from:

expo.lcs.mit.edu:contrib/pbmplus.tar.Z

There is also a faxtopbm and pbmtofax in the ISO Development package
(ISODE-6.0) that also does two dimensional encoding.  The whole package 
(something like 4 MB) can be FTPed from:

nisc.nyser.net:pub/isode/isode-6.tar.Z

And the files are in isode-6.0/others/quipu/photo.  However, they are
a little tied to the rest of the package.  I have the pbmtofax
working and am probably going to pull faxtopbm out of the package
(anyone else already done this?).  You can FTP just these files
from me at

sam.cs.cmu.edu:/afs/cs/user/vac/photo.tar.Z


Also, pgmtops can do run length encoding so that the postscript file
is smaller (for my file it was about a factor of 4) but the printer
was so slow at decompressing that it was better to send the file
without this even with a 1 KB/second serial link to the printer.

Below is the head of the file that "pgmtops -rle" produced.  Are 
there any postscript hackers than can recode the "readrlestring"
so that it runs faster?  


      Vince Cate
      vac@cs.cmu.edu


%!PS-Adobe-2.0 EPSF-2.0
%%Creator: pgmtops
%%Title: r240.ps
%%Pages: 1
%%BoundingBox: -7 -9 619 801
%%EndComments
%%EndProlog
/rlestr1 1 string def
/rlestr 128 string def
/readrlestring {
  currentfile rlestr1 readhexstring pop  0 get
  dup 127 le {
    currentfile rlestr 0  4 3 roll  1 add  getinterval
    readhexstring  pop
  } {
    256 exch sub  dup
    currentfile rlestr1 readhexstring pop  0 get
    exch 0 exch 1 exch 1 sub { rlestr exch 2 index put } for
    pop  rlestr exch 0 exch getinterval
  } ifelse
} bind def
%%EndProlog
%%Page 1 1
gsave
-7.59399 -9.90759 translate
627.188 811.815 scale
2040 2641 1
[ 2040 0 0 -2641 0 2641 ]
{ readrlestring }
image
00f88000820000f88000820000f88000820000f88000820000f880008200
00fc8000820000f88000820000f88000820000f88000820000f880008200
00f88000820000f88000820000f88000820000f88000820000f880008200
00fc8000820000fc8000820000f88000820000f88000820000f880008200
00f88000820000f88000820000f88000820000f88000820000f880008200
00f88000820000f88000820000f88000820000f88000820000f88f000e04
40510000001101f7d40400040014820000f8ad000415001d1541f7001541
7000000004000051c444400000004157ffffdf51c5faff03577ffffff600
023d0404900000f8bf000545fffd404010f9000205515ff8ff0675500000
0145dff2ff01d71deeff07fc5400041001177ffbff015940930000f0bf00

jhm+@andrew.cmu.edu (Jim Morris) (02/17/90)

>galen@hoptoad.UUCP (Galen Wolf)
>I'm interested to find any hardware or software which allows translating
>electronically between G3 Fax and either plain or encapsulated PostScript.

1. According to some quotes in the trade press, I thinkAdobe is working
on such a thing.

2. One of the PostScript clones, GhostScript I think, offers the feature
in one direction: it will produce a raster from PostScript at whatever
resolution you ask -- so ask for 200 by 200. [I've heard all this second
hand.]


 >Are there any postscript hackers than can recode the
>"readrlestring"so that it runs faster?  

Not quite, but here is a program that re-encodes the uncompressed input
to the image operator and usually makes it faster.
-------------CUT HERE-----------------------------
/*	pssqw.c	Compression of postscript image files
              just  squeezes the white space    */

/*  Written Jim Morris (james.morris@andrew.cmu.edu) 7/19/88
        derived from a version (pscomp.c) by 
     Ganapathy Krishnan (krishnan@cs.buffalo.edu) (716-636-3197)
  Morris's work was supported by the NSF EXPRES project.
   */


#include <stdio.h>
#ifdef VMS
#include <string.h>
#else
#ifdef MSDOS
#include <string.h>
#else /* #ifdef MSDOS */
#include <strings.h>
#endif /* #ifdef MSDOS */
#endif
#define BSIZE 10000    /* PS internal buffer size */
#define PSLineSize 72  /* Limit on output lines */
#define LINEBUF 300
#define MinimunF 22    /*default shortest run of f's to encode */
                       /*  This number seems to minimize processing time
on a Laserwriter
                                       If your printer is different,
hopefully faster,
                                       revising this number may improve
performance. */

#define dig(c) ((c) >= '0' && (c) <= '9' )
#define hdig(c) (((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))
#define hexdig(c) ( dig(c) || hdig (c))
#define white(c) (c == ' ' || c == '\n' || c=='\t')
/*
  Usage   pssqw < file.ps | lpr 

  cc pssqw.c  -o pssqw

      This program accepts a PostScript file and writes out a new one
      in which all the image commands have been altered to use compressed
      rasters. Each image command  must appear on a line by itself and
      the image data can contain only hex digits and white space. It is
possible
      for the program to malfunction either by missing an image command or
      mistaking some innocent text for one. If the next command after the
      image data starts with a hex digit, e.g. endpage, put a PS comment
     before it, e.g. %end of image
     
      Here is an example of the kind of input expected:

      %!  To be embedded, delete the '!'
      %  Bits are stored left-to-right, bottom-to-top;  1=white, 0=black 
       /width 1016 def  /height 1321 def		% dimensions in pixels
      /xScale 0.60 def /yScale 0.60 def	% scaling factors
      width xScale mul height yScale mul scale	% set scaling
      /picstr width 7 add 8 idiv string def  	% define place to read lines
      % the  "image" operator has five parameters:
      width height 1			% dimensions
      [width    0    0    height    0    0]	% transform matrix
      {currentfile picstr readhexstring pop}	% bits source
	image					% PRINT IT
	fff fff fffff   ffff
	fffff ffffffff
	aab034  f09b
             .......
             showpage

 Here is the PS program that replaces image:

  pop % discard standard proc
 /bz 10000 def % co-ordinate with BSIZE above
 /bf bz string def %place to build lines
 /ff bz string def
 ff 0 255 put
 /hbz bz 1 add 2 idiv def
 /i 1 def
 %fill ff with 255
 {
   % [0...i) contains 255, i < bz
   ff i  % start putting at i
   ff 0  % start taking from 0
   i  hbz ge
     {bz i sub getinterval putinterval exit}
     {i getinterval putinterval
     /i i i add def
     }
   ifelse
 } loop
  
{ % new proc
   /len currentfile token pop def
   len 0 lt
    {ff 0 len neg getinterval}
    {currentfile bf 0 len getinterval readhexstring pop}
   ifelse
  } bind
image

A squeezed version appears immediately below.

	*/

static char pscommand[] = {
"pop/bz 10000 def/bf bz string def/ff bz string def ff 0 255 put /hbz\n\
bz 1 add 2 idiv def/i 1 def{ff i ff 0 i hbz ge{bz i sub getinterval\n\
putinterval exit}{i getinterval putinterval/i i i add def}ifelse}loop\n\
{/len currentfile token pop def  len 0 lt{ff 0 len neg getinterval}\n\
{currentfile bf 0 len getinterval readhexstring pop}ifelse}bind image\n"
};

static char line[LINEBUF];
static int nch; /* next character from file */
static int minF = MinimunF;
static FILE *infile, *outfile;

extern int optind;
extern char *optarg;

main(argc, argv)
int argc;
char **argv;
{
    int flag;
    int j;
    char *outfname = NULL;

    optind = 1;

    /* get the argument */
    while ((flag = getopt(argc, argv, "f:o:x")) != EOF) {
	switch (flag)
	  {
	  case 'f':
	      minF = atoi (optarg);
	      if (minF<6) minF = 6;
	      break;
	      
	  case 'o':
	      outfname = optarg;
	      break;

	  case 'x':
	  default:
	      fprintf (stderr,
			"Usage: pssqw [-f <value>] [-o outfile] [file]\n");
	      exit (1);
	  }
    }

    if (optind + 1 < argc) {
	fprintf(stderr, "pssqw: can only handle one input file.\n");
	exit(1);
    }

    if (optind < argc) {
	infile = fopen(argv[optind], "r");
	if (!infile) {
	    perror(argv[optind]);
	    exit(1);
	}
    }
    else {
	infile = stdin;
    }
    
    if (outfname) {
	outfile = fopen(outfname, "w");
	if (!outfile) {
	    perror(outfname);
	    exit(1);
	}
    }
    else {
	outfile = stdout;
    }

    nch = getc(infile);

    for(; ;)
    {
	if (nch == EOF) exit(0);

	readline();

	/* look for line starting with "image" */
	for (j=0; white(line[j]); j++) ;
	if (strncmp(&(line[j]), "image", 5) == 0 )
	{
	    fprintf(outfile, "%s", pscommand);
	    runlength_encode();
	}
	else
	{
	    fprintf(outfile, "%s\n", line);
	    nch = getc(infile);
	}
    }
}

readline()
{
    int i;
    i=0;
    /* nch contains the next item of input */
    for (;;)
    {
	if (i>=LINEBUF)
	{
	    fprintf(stderr, "Line buffer length exceeded\n");
	    exit(1);
	}
	if(nch =='\n' || nch == EOF)
	{
	    line[i] = '\0';
	    return(i);
	}
	line[i++] = nch;
	nch = getc(infile);
    }
}


runlength_encode()
{   char duffer[2*BSIZE]; /* double sized buffer */
    int size = 2*BSIZE;
    int done = 0;
    int i, j, lout;
    for(;!done;)
    {
	/* read in a buffer's worth */
	for (size=0;size!=2*BSIZE ;)
	{
	    nch = getc(infile);
	    if white(nch) continue;
	    
	    if (hexdig(nch)) duffer[size++] = nch;
	    else {done = 1; break; }

	}

	/* write out  duffer[0...size) */

	size = (size/2)*2; /* ignore odd character */

	for(lout=0;lout!=size;)
	{
	    /* duffer[0...lout) has been put out */
	    /* find a string of ff's */

	    for (i=lout; i!=size; i+=2) 
	    {
		/* duffer[lout..i) contains non F-string */
		if(duffer[i] != 'f' && duffer[i] != 'F') continue;
		for (j=i+1; j!=size; j++)
		{
		    if (duffer[j] != 'f' && duffer[j] != 'F') break;
		}

		/* duffer[i...j) are f's */
		j = (j/2)*2; /* must be even */

		if(j-i >= minF) break; 
	    }

	    /* duffer[lout...i) is non-F stuff */
	    /* duffer[i...j) are f's if i!=size */

	    if(i>lout)
	    {
		PNum((i-lout)/2);
		for (;lout!=i; lout++) PC(duffer[lout]);
	    }

	    if (lout!=size)
	    {
		PNum(-(j-i)/2);
		lout = j;
	    }
	}
    }
    putc('\n', outfile);
}

#define PSLength 72

static  int tlcount = 0;
/* there are tlcount chars sent since the last cr */
PC(c)
char c;
{
    if (++tlcount >= PSLength)
    {
	putc('\n', outfile);
	tlcount = 1;
    }
    putc(c, outfile);
}

PNum(n)
int n;
{
    int an = n;
    int length = 0;
    if (n<0) {an = -n; length = 1; }
    length += (an>9999) ? 6 :
      (an>999) ? 5 :
      (an>99) ? 4 :
      (an>9) ? 3 :
      2;
    if( (tlcount += length) >= PSLength)
    {
	putc('\n', outfile);
	tlcount = length;
    }
    fprintf(outfile, "%d ", n);
}

geof@aurora.com (Geoffrey H. Cooper) (02/17/90)

GammaLink of Palo Alto, CA sells a Fax board that interprets PostScript
and prints it on a remote Fax machine.

- Geof
-- 
geof@aurora.com / aurora!geof@decwrl.dec.com / geof%aurora.com@decwrl.dec.com

eli@spdcc.COM (Steve Elias) (02/21/90)

 geof@aurora.UUCP (Geoffrey H. Cooper) writes:
>GammaLink of Palo Alto, CA sells a Fax board that interprets PostScript
>and prints it on a remote Fax machine.

i believe that GammaLink products do not yet run under unix...
they'll figure it out one of these days, though.

-- 
/* eli@spdcc.com ; 617-932-5598 */   
/* Plan B from Outer Space      */