V10/cmd/bcp/postlib.c

Compare this file to the similar file:
Show the results in this format:

/* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved.              */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T.                */
/* The copyright notice does not imply actual or intended publication. */
/* AUTHORS:                                            */
/*     T. Thompson - ATT-BL HO - first versions        */
/* Routines for generating PostScript from RLE. */
/* The routines at the bottom of this file, which */
/* do the actual conversion to postscript, were */
/* hacked out of 'sun2ps'.  The original header */
/* giving credit to its authors is there. */

/* The 'binary' version of the output is collected in a */
/* temporary file, which is then fed back to the routines */
/* that generate postscript in a run-length-encoded form. */
/* Ideally it should just convert the original run-length */
/* encoding directly, but the REAL bottleneck is the */
/* PostScript printer, of course.  Printing an 800 by 800 */
/* pixel image takes 5 minutes. */

#include <stdio.h>
#include <math.h>
#include <string.h>
#include "CPU.h"
#include "boole.h"
#include "limits.h"     /* numeric extreme values */
#include "Units.h"
#include "Coord.h"
#include "pic.h"

FILE *Fp, *tmpfile();
int Raswidth;
int Raslength;
int Rasbytes;	/* bytes per row */
int Inv = 0;
int Aspect = 1;		/* if non-zero, retain original aspect ratio */
int Land = 0;		/* if non-zero, print in landscape mode */
char Revbyte[256];
/*  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */
char Revnib[16] = {
    0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
    };
 
void
POST_start(h)
PIC_hdr *h;
{
	int n, v;

	/* build a table of reversed bytes */
	for ( n=0; n<256; n++ )
		Revbyte[n] = Revnib[(n>>4)&0xf] | Revnib[n&0xf]<<4;

	h->bpl = (h->bpl+7)/8;
	Rasbytes = h->bpl;
	Raslength = h->bpl * h->bx.b.y;
	Raswidth = h->bx.b.x;
	postmain(1,NULL,Raswidth,h->bx.b.y);
#if CPU==SUN
	Fp = tmpfile();
#else
	Fp = fopen("tmp.postlib.0","rw");
#endif
}

void
POST_end()
{
	int c;
	rewind(Fp);
	(VOID) Encode(Raslength, Inv);
	PrintPostScriptClosing();
	fclose(Fp);
}

/* write a full line of picture data, returning status:  1 OK, 0 EOF, -1 ERR */
int POST_wline(h,line)
    PIC_hdr *h;
    unsigned char *line;
{   int stat;
        if( (stat=fwrite(line,1,h->bpl,Fp)) == h->bpl) {
                h->seek += h->bpl;
                h->cy++;
                return(1);
                }
        else { /* ERR */
                err("write to fd%d stat%d",fileno(h->fp),stat);
                if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
                else return(-1);
                };
        }

/******************************************************************************
*									      *
*	File:         sun2ps.c						      *
*	Author:       Glenn Boysko					      *
*	Organization: Case Western Reserve University			      *
*	EMail:	      {decvax, sun}!mandrill!boysko			      *
*		      boysko@mandrill.cwru.edu				      *
*	Created:      Wed Mar 23 9:25pm					      *
*	Contents:     Sun Rasterfile to PostScript image (using a run-length  *
*			encoding scheme.)				      *
*									      *
*	(Adapted from "postimage" filter by J. R. Bammi.)		      *
*									      *
*	@(#)sun2ps.c	1.8
******************************************************************************/

/*
 * Usage:
 *  sun2ps [-s sizex sizey] [-t transx transy] [-r rot] [-l] [-i] [-a] file ...
 *
 *	-s sizex sizey   = size of postscript image - default 7.5 x 10 inches.
 *	-t transx transy = translate image - default 0.5 0.5 inches
 *	-r rotate	 = rotate image     - default 0 degress
 *      -l		 = landscape (overrides *all* settings.) 
 *	-i		 = inverse image - default no inverse 
 *				(Inverse enabled implies white on black.)
 *	-a		 = maintain correct aspect ratio - default none.
 *
 */

/* Sun standard raster file format (as obtained by screendump(1)).
 *
 * Header	(8 16-bit quantities)
 * Color Map
 * Image
 *
 */

/* Header Format:
 * 
 * ras_magic		(int)	Raster Magic number 0x59a66a95
 * ras_width		(int)	Width of image in pixels.
 * ras_height		(int)	Height of image in pixels.
 * ras_depth		(int)	Bits per pixel.	Either 1 or 8 bits.
 * ras_length		(int)	Length of image in bytes.
 * ras_type		(int)	Type of file. Assumed to be RT_STANDARD (1) if
 *				produced by a screendump command.
 * ras_maptype		(int)	Type of color map. 
 * ras_maplength	(int)	Length of color map in bytes.
 *
 */

/* Ras_maplength bytes of Color map data. */

/* Ras_length bytes of Image data. */

/* Buffer and Input Modes... */
#define LITERAL	0
#define COPY	1
#define IGNORE	2

/* Transmission Variables. */
int BufCount;

unsigned char Buffer[128],
     	      CurrByte,
     	      NextByte,
     	      *BufferP = Buffer;

/* Diagnostic Variables. */
int	DiagNLongRuns = 0,
     	DiagMaxRunLength = 0,
     	DiagNumRuns = 0;
double	DiagSumRunLength = 0;

postmain(argc,argv,width,height)
int argc;
char **argv;
int width, height;
{
     char      *filename;
     double 	sizex, sizey, transx, transy, rotate;

     extern double atof();
     
     filename = "STDIN";
     sizex = 7.5;
     sizey = 10.0;
     transx = transy = 0.5;
     rotate = 0.0;
     
     while(--argc > 0)
     {
	  ++argv;
	  if((*argv)[0] == '-')
	  {
	       switch((*argv)[1])
	       {
		 case 'l':
		 case 'L':
		    Land = 1;
		    break;
		    
		 case 's':
		 case 'S':
		    sizex = atof(*++argv);
		    sizey = atof(*++argv);
		    argc -= 2;
		    break;
		    
		 case 't':
		 case 'T':
		    transx = atof(*++argv);
		    transy = atof(*++argv);
		    argc -= 2;
		    break;
		    
		 case 'r':
		 case 'R':
		    rotate = atof(*++argv);
		    argc--;
		    break;
		    
		 case 'I':
		 case 'i':
		    Inv = 1;
		    break;
		    
		 case 'A':
		 case 'a':
		    Aspect = 1;
		    break;
		    
		 default:
		    fprintf(stderr,"Illegal switch %c - ignored\n",
			    (*argv)[1]);
	       }
	  }
     }
     if (Land)
     {
	  transx = 8.0;
	  transy = 0.5;
	  sizex  = 10.0;
	  sizey  = 7.5;
	  rotate = 90.0;
     }
	if (Aspect) {
		if ((sizex / width) < (sizey / height)) {
			sizey = sizex * (height * 1.0 / width);
		}
		else {
			sizex = sizey * (width * 1.0 / height);
		}
	}
	PrintPostScriptRoutines(height, width, 1 /*depth*/ ,
			     transx, transy, sizex, sizey, rotate);
}

/******************************************************************************
*	I/O Routines.							      *
******************************************************************************/
int
gb()		/* Get a byte from Fp. */
{
     int byte;
     
     if (!feof(Fp))
	  byte = getc(Fp);
     else
	  Error("Premature EOF.\n");
     if (ferror(Fp))
	  Error("I/O Error.\n");
     return(Revbyte[byte]);
}

SendHex(Byte)		/* Send a Hex char to Stdout. */
unsigned char Byte;
{
     static int LineCount = 0;

     printf("%02x",  0xff & Byte);
     if (++LineCount == Rasbytes)
     {
	  putchar('\n');
	  LineCount = 0;
     }
}
     
int
SendBuffer(Inv)		/* Send a buffer to Stdout. Return BytesSent. */
int Inv;
{
     int i, BytesSent;
     
     if (BufferMode() == LITERAL)
     {
	  SendHex( (unsigned char) 0xff & BufCount );
	  for (i = 0; i < BufCount+1; i++)
	  {
	       SendHex( (Inv) ? Buffer[i] : ~Buffer[i]);
	  }
	  BytesSent = BufCount+2;
     }
     else if (BufferMode() == COPY)
     {
	  SendHex( (unsigned char) 0xff & (0x100 + BufCount) );
	  SendHex( (Inv) ? Buffer[0] : ~Buffer[0]);
	  BytesSent = 2;
	  DiagRecLRun(mag(BufCount)+1);
     }
     return(BytesSent);
}

/******************************************************************************
*	Utility Routines.						      *
******************************************************************************/
int
mag(Byte)	/* Magitude of a signed char. */
int Byte;
{
     if (Byte & 0x80)
     {
	  /* Signed */
	  Byte = ~(--Byte);
     }
     return( 0xff & Byte );
}
	  
/******************************************************************************
*	Buffer Management Routines.					      *
******************************************************************************/
int
InputMode()
{
     if (CurrByte == NextByte)
	  return(COPY);
     return(LITERAL);
}

int
BufferMode()
{
     if (BufCount >= 0 && BufCount <= 127)
	  return(LITERAL);
     else if (BufCount >= -127 && BufCount <= -1)
	  return(COPY);
     return(IGNORE);
}

InitLitMode(NBytes, Inv)
int *NBytes, Inv;
{
     BufferP    = Buffer;
     BufCount   = -1;
     ContLitMode(NBytes, Inv);
}

ContLitMode(NBytes, Inv)
int *NBytes, Inv;
{
     if (BufCount == 127)
     {
	  SendBuffer(Inv);
	  BufferP  = Buffer;
	  BufCount = -1;
     }
     *BufferP++ = CurrByte;
     BufCount++;
     CurrByte   = NextByte;
     NextByte   = (unsigned char) gb();
     (*NBytes)--;
}
     
InitCopyMode(NBytes, Inv)
int *NBytes, Inv;
{
     BufferP    = Buffer;
     *BufferP++ = CurrByte;
     BufCount   = -1;
     CurrByte   = (unsigned char) gb();
     NextByte   = (unsigned char) gb();
     *NBytes   -= 2;
}

ContCopyMode(NBytes, Inv)
int *NBytes, Inv;
{
     if (BufCount == -127)
     {
	  SendBuffer(Inv);
	  InitCopyMode(NBytes, Inv);
	  DiagNLongRuns++;
     }
     BufCount--;
     CurrByte   = NextByte;
     NextByte   = gb();
     (*NBytes)--;
}

/******************************************************************************
*	Encoding Algorithm.						      *
******************************************************************************/
int
Encode(NBytes, Inv)
int NBytes, Inv;
{
     int BytesSent = 0;
     
     /* Initialize Buffer, BufCount, NextByte, CurrByte */
     CurrByte = (unsigned char) gb();
     NextByte = (unsigned char) gb();
     if (InputMode() == LITERAL)
     {
	  InitLitMode(&NBytes, Inv);
     }
     else
     {
	  InitCopyMode(&NBytes, Inv);
     }
     while (NBytes > 3)
     {
	  switch(BufferMode())
	  {
	    case LITERAL:
	       if (InputMode() == COPY)
	       {
		    BytesSent += SendBuffer(Inv);
		    InitCopyMode(&NBytes, Inv);
	       }
	       else
	       {
		    ContLitMode(&NBytes, Inv);
	       }
	       break;
	    case COPY:
	       if (CurrByte == Buffer[0])
	       {
		    ContCopyMode(&NBytes, Inv);
	       }
	       else
	       {
		    BytesSent += SendBuffer(Inv);
		    if (InputMode() == COPY)
		    {
			 InitCopyMode(&NBytes, Inv);
		    }
		    else
		    {
			 InitLitMode(&NBytes, Inv);
		    }
	       }
	       break;
	    default:
	       Error("Bad Buffer Mode... Sorry\n");
	       break;
	  }
     }
     BytesSent += SendBuffer(Inv);
     /* Send out rem'g 2-3 bytes in LITERAL mode. */
     Buffer[0] = CurrByte;
     Buffer[1] = NextByte;
     if (NBytes == 3)
	  Buffer[2] = gb();
     BufCount = NBytes-1;
     BytesSent += SendBuffer(Inv);
     return(BytesSent);
}

/******************************************************************************
*	Diagnostic Routines.						      *
******************************************************************************/
DiagRecLRun(Rlength)
int Rlength;
{
#ifdef DIAGS
     if (Rlength > DiagMaxRunLength)
	  DiagMaxRunLength = Rlength;
     DiagSumRunLength += Rlength;
     DiagNumRuns++;
#endif
}

Diags()
{
#ifdef DIAGS
     fprintf(stderr, "Longest Run (<= 128) = %d\n", DiagMaxRunLength);
     fprintf(stderr, "Number of Runs over 128 = %d\n", DiagNLongRuns);
     fprintf(stderr, "Average Run Length of %d. (%d Runs)\n",
	     (int) DiagSumRunLength / DiagNumRuns, DiagNumRuns);
#endif
}

/******************************************************************************
*	PostScript Output Routines. 					      *
******************************************************************************/
PrintPostScriptRoutines(ras_h, ras_w, ras_d, tx, ty, sx, sy, rot)
int ras_h, ras_w, ras_d;
double tx, ty, sx, sy, rot;
{
     printf("%%!\n/inch {72 mul} def\n");
     printf("/bpp %d def\n", ras_d);
     printf("/scanlines %d def\n", ras_h);
     printf("/scansize %d def\n", ras_w);
     printf("/bitmapx\n{");
     printf(" %d %d %d [%d 0 0 %d 0 %d] ", ras_w, ras_h, ras_d, ras_w, 
	    -ras_h, ras_h);
     printf("{currentfile readrlehexstring pop } image\n} def\n");
     printf("gsave\n");
     printf("%f inch %f inch translate\n",tx, ty);
     printf("%f rotate\n", rot );
     printf("%f inch %f inch scale\n", sx, sy);
     printf("/readrlehexstring\t%% rle_file => decoded_string boolean\n");
     printf("{\n\t/fileptr exch def\n\tfileptr 1 string readhexstring {");
     printf("\n\t\t0 get dup 128 and 0 eq\n");
     printf("\t\t{ 1 add /Buffer exch string def\n");
     printf("\t\t\tfileptr Buffer readhexstring\n\t\t}\n\t\t{");
     printf(" 256 exch sub /BufCount exch def\n");
     printf("\t\t\t/Buffer BufCount 1 add string def\n");
     printf("\t\t\t/RunInt fileptr 1 string readhexstring");
     printf(" pop 0 get def\n");
     printf("\t\t\t0 1 BufCount { RunInt Buffer 3 1 roll put } for\n");
     printf("\t\t\tBuffer true\n\t\t} ifelse\n\t}\n\t{ false } ifelse\n");
     printf("} def\n");
     printf("/clipathx\n{\tnewpath\n\t0 0 moveto\n\t%f inch 0", sx);
     printf(" lineto\n\t%f inch %f inch lineto\n\t0 %f inch lineto\n",
	    sx, sy, sy);
     printf("\tclosepath\n} def\nclipathx clip\n");
     printf("bitmapx\n");
}

PrintPostScriptClosing()
{     
     printf("\ngrestore\n");
     printf("showpage\n");
}

/******************************************************************************
*	Error Routine.							      *
******************************************************************************/
Error(S1, S2, S3)
char *S1, *S2, *S3;
{
     fprintf(stderr, S1, S2, S3);
     exit(-1);
}