AWARE SYSTEMS
TIFF and LibTiff Mail List Archive

1994.08.05 17:28 "Here is help for printing tiff with level 2 postscript", by Bill Cattey

As part of a collaboration on display and printing of document images, this program was circulated. I have the permission of the author to redistribute it.

I thought readers of the tiff mailing list might find it useful. (Particularly for the folks wondering about quick and dirty print methodologies.

-wdc

========== cut here ==========

/*
 * A quick filter to change a 300 dpi monochrome tiff image into a Level 2 
 * Postscript file that is decoded on the printer. The resulting output
data is 
 * about 1.25 times size of the original TIF image. To minimize the size
 * of the postscript file, I have used Ascii Base 85 encoding.
 *
 * Note the TIFF header is assumed to be constant length and just truncated.
 *
 * USAGE:  cat <tulip_tif_file> | thisfilter | lpr
 *
 * -- Brad Greer  10.22.93
 */

/*
 * Modified to work with cropped tiff images also (datasets 15+).
 *   - no longer makes assumptions about image sizes.
 *   - works with tiff files of various heights, widths, and headerlengths.
 *   - computes new aspect ratio.
 *   - also modified to take an optional filename as an argument.
 *
 * USAGE:  thisfilter tiffile | lpr
 *    or   cat tiffile | thisfilter | lpr
 *
 * -- Greg Peters (camber@umich.edu), Ken Alexander (kalex@umich.edu) 2/16/94
 */

#include<stdio.h>
#include<strings.h>

main(argc, argv)
  int argc;
  char *argv[];
{
  int ch,  i, tuplecount;
  unsigned char b[4], c[5] ;
  unsigned long q;
  FILE *infp;
  int off, j, key, content, datastart, datawidth, datalength;
  int ifd[12];
  float scaleheight, scalewidth, scale;

  if (argc < 2) {
     infp = stdin;
  } else if ((infp = fopen(argv[1], "r")) == NULL) {
     fprintf(stderr, "cannot open input file %s\n", argv[1]);
     exit(1);
  }

  for (off = 0; off < 9; off++)
     ch = getc(infp);    /* save the number of IFDs */
  getc(infp); off++;
  while (ch--) {         /* process the IFDs in the tiff header */
     for (j = 0; j < 12; j++)       /* read an IFD */
        ifd[j] = getc(infp);
     key = ifd[1] * 256 + ifd[0];         /* IFD field tag */
     content = ifd[9] * 256 + ifd[8];     /* IFD field value */
     switch (key) {
        case 0x0111:
           datastart = content;     /* offset of the start of image data */
           break;
        case 0x0100:
           datawidth = content;     /* width of the image */
           break;
        case 0x0101:
           datalength = content;    /* length (height) of the image */
           break;
     }
     off += 12;
  }
  for (; off < datastart; off++)    /* skip to the beginning of the data */
     getc(infp);

  fprintf(stderr, "data offset is  %d %x\n", datastart, datastart);
  fprintf(stderr, "image width is  %d %x\n", datawidth, datawidth);
  fprintf(stderr, "image height is %d %x\n", datalength, datalength);

  /* compute the scale factor for a proper aspect ratio */

  scaleheight = datalength/ 3149.0;
  scalewidth  = datawidth / 2249.0;
  scale = scaleheight > scalewidth ? scaleheight : scalewidth;
  fprintf(stderr, "scale factor is %f\n", scale);

  /* build the Postscript Header */

  printf( "%%!PS-Adobe-\n");
  printf( "0.245 0.245 scale\nerasepage\n");

  printf( "150 -50 translate \n%d %d scale \n0 rotate \n",
              (int)(datawidth / scale), (int)(datalength / scale));

  printf( "/filterfile currentfile /ASCII85Decode filter\n<< " );
  printf( "/K -1 /Blacks1 true /EndOfBlock false /Columns %d /Rows %d ",
                 datawidth, datalength);
  printf(">> /CCITTFaxDecode filter def %d %d 1 [%d 0 0 -%d 0 %d] ",
            datawidth, datalength, datawidth, datalength, datalength);
  printf("\nfilterfile\nimage" );

  /* process the image data */

  i=0; tuplecount=0 ;
  while ( (ch = getc(infp)) != EOF) {
    b[i] = ch & 0x00FF; i++;
    if (i==4) /* convert to base85 and print */ {

      if (tuplecount%15==0) printf("\n");  /* break up the image data */
       tuplecount++ ;

      /* encode and print the 4 bytes into 5 */
      q = (((b[0]*256)+b[1])*256+b[2])*256+b[3]  ;
      if (q==0)
        printf("z");
      else {
        for (i=4; i>=0; i--) {  c[i]=q%85 ; q=(q-c[i])/85; }
        printf("%c%c%c%c%c", c[0]+33, c[1]+33, c[2]+33, c[3]+33, c[4]+33);
      }
      i=0;
    }
  }

  /* if bytes left over, encode them by prepending 00's */
  switch (i) {
  case 1: b[3]=b[0]; b[2]=0;    b[1]=0;     b[0]=0;
          q = (((b[0]*256)+b[1])*256+b[2])*256+b[3]  ;
          for (i=4; i>=0; i--) { c[i]=q%85 ; q=q/85; }
          printf("%c%c", c[3]+33, c[4]+33);
          break ;
  case 2: b[3]=b[1]; b[2]=b[0]; b[1]=0;     b[0]=0;
          q = (((b[0]*256)+b[1])*256+b[2])*256+b[3]  ;
          for (i=4; i>=0; i--) { c[i]=q%85 ; q=q/85; }
          printf("%c%c%c", c[2]+33, c[3]+33, c[4]+33);
          break ;
  case 3: b[3]=b[2]; b[2]=b[1]; b[1]=b[0] ; b[0]=0;
          q = (((b[0]*256)+b[1])*256+b[2])*256+b[3]  ;
          for (i=4; i>=0; i--) { c[i]=q%85 ; q=q/85; }
          printf("%c%c%c%c", c[1]+33, c[2]+33, c[3]+33, c[4]+33);
          break ;

  default: break;
  }

  /* tack on the EOD and showpage command */

  printf("\n~>\nshowpage");
}