🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.postscript
Article #7908

Re: Bitmap decompression in PostScript?

#7908
From: Jim Morris
Date: Tue, 31 Jan 1989 17:46
275 lines
8076 bytes
Here is a program that works for me. It seems to compress a business letter by a
factor of 5 and sometimes the printing time as well. Your mileage may vary...
------------------------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
#include <strings.h>
#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;

main(argc, argv)
int argc;
char **argv;
{
    int j;

    /* get the argument */
    while (--argc > 0 && (*++argv)[0] == '-')
    { while (*++(*argv))
    { switch (**argv)
    {   case 'f': minF = atoi (*argv+1);
        if (minF<6) minF = 6;
        while (*++(*argv)); --(*argv); break;
    default:  fprintf (stderr,
                        "Usage: pssqw [-f<value>] \n");
        exit (1);
    }
    }
    }

    nch = getchar();

    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 )
        {
            printf("%s", pscommand);
            runlength_encode();
        }
        else
        {
            printf("%s\n", line);
            nch = getchar();
        }

    }
}

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 = getchar();
    }
}


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 = getchar();
            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;
            }
        }
    }
    printf("\n");
}

#define PSLength 72

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

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)
    {
        printf("\n");
        tlcount = length;
    }
    printf("%d ", n);
}
Technical Details
Message-ID: <wXtT3ky00hl=I0c0VJ@andrew.cmu.edu>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!rutgers!rochester!pt.cs.cmu.edu!andrew.cmu.edu!jhm+
References: <432@skep2.ATT.COM> <10529@well.UUCP>, <23360@watmath.waterloo.edu>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!rutgers!rochester!pt.cs.cmu.edu!andrew.cmu.edu!jhm+
From: jhm+@andrew.cmu.edu (Jim Morris)
Newsgroups: comp.lang.postscript
Subject: Re: Bitmap decompression in PostScript?
Message-ID: <wXtT3ky00hl=I0c0VJ@andrew.cmu.edu>
Date: 31 Jan 89 17:46:24 GMT
References: <432@skep2.ATT.COM> <10529@well.UUCP>,
 <23360@watmath.waterloo.edu>
Organization: Carnegie Mellon, Pittsburgh, PA
Lines: 275
In-Reply-To: <23360@watmath.waterloo.edu>