📄 postmd.c
字号:
/* * * postmd - matrix display program for PostScript printers. * * A simple program that can be used to display a matrix as a gray scale image on * a PostScript printer using the image operator. Much of the code was borrowed * from postdmd, the bitmap display program DMD screen dumps. May help if you have * a large matix (of floating point numbers) and want a simple way to look for * patterns. * * Matrix elements are a series of floating point numbers arranged in the input * file in row major order. The actual matrix elements can be preceeded by a simple * header that sets things like the matrix dimensions, interval list, and possibly * a window into the matrix that we'll use for display. The dimension statement is * perhaps the most important. If present it determines the number of rows and * columns in the matrix. For example, either of the following defines a 50x50 * matrix, * * dimension 50 * dimension 50x50 * * If no dimension statement appears in the input file, the matrix is assumed to * be square, and the number of rows (and columns) is set to the square root of * the number of elements in the input file. * * Each matrix element is mapped into an integer in the range 0 to 255 (actually * 254) and PostScript's image operator then maps that number into a gray scale * appropriate for the particular printer. The mapping from the floating point * matrix elements to integers is accomplished using an interval list that can be * set using the -i option. The format of the interval string is, * * num1,num2,num3,...,numn * * where each num is a floating point number. The list must be given in increasing * numerical order. A list of n numbers partitions the real line into 2n+1 regions * given as, * * region1 element < num1 * region2 element = num1 * region3 element < num2 * region4 element = num2 * . * . * . * region2n element = numn * region2n+1 element > numn * * Every number in a region is mapped one integer in the range 0 to 254, and that * number, when displayed on a printer using the image operator, prints as a square * filled with a gray shade that reflects the integer that was chosen. 0 maps to * black and 255 maps to white (which by default will not be used). * * The default gray scale gets darker as the region number increases, but can be * changed by supplying a gray scale list with the -g option or in the optional * matrix header. The color map is again a comman or space separated list that * looks like, * * color1,color2, ... ,color2n+1 * * where color1 applies to region 1 and color2n+1 applies to region2n+1. Each * number in the list should be an integer between 0 and 255. If less than 2n+1 * colors are given default assignments will be used for missing regions. * * The size of the matrix that we can display reasonably well is a function of the * number of elements in the interval list, paper size, and printer resolution. * For example a 300dpi printer using 8.5x11 inch paper gives us an image area of * about 2400x2400 pixels. An interval list of two numbers generates five separate * regions and will therefore need that many different shades of gray. Since we're * not using white we'll need to partion our image area into 4x4 pixel squares, * and that means a 600x600 matrix is about as big as we can go. In practice that's * optimistic, but the argument illustrates some of the limitations. * * A submatrix can be selected to display by windowing into the matrix. The window * list can be given using the -w option or can be set in the optional header that * can preceed each matrix. The list should be a comma or space separated list * that looks like, * * lower-column, lower-row, upper-column, upper-row * * where each element in the list must be a positive integer. Rows and columns in * the input matrix start at 1. The dimension of the displayed window will be from * lower-column to upper-column and from lower-row to upper-row inclusive. * * The encoding produced by the program is essentially identical to what's done * by postdmd. See the comments at the beginning of that program if you need more * details. The prologue also shares much of the same code. * * The PostScript prologue is copied from *prologue before any of the input files * are translated. The program expects that the following PostScript procedures * are defined in that file: * * setup * * mark ... setup - * * Handles special initialization stuff that depends on how this program * was called. Expects to find a mark followed by key/value pairs on the * stack. The def operator is applied to each pair up to the mark, then * the default state is set up. * * pagesetup * * page pagesetup - * * Does whatever is needed to set things up for the next page. Expects * to find the current page number on the stack. * * bitmap * * columns rows bitmap - * * Prints the image that's read as a hex string from standard input. The * image consists of rows lines, each of which includes columns elements. * Eight bits per pixel are used to encode the matrix elements. * * labelmatrix * * matrixname matrixlimits labelmatrix - * * Prints string matrixname just below the lower left corner of the image * and prints string martixlimits near the lower right corner. Outlines * the entire image with a (one pixel wide) box and then draws tick marks * along the top and left sides of the image. One tick mark is printed * for every ten elements. * * legend * * n1 ... nN N c1 m1 ... cM mM total regions legend - * * Prints the legend as a bar graph below the matrix image. n1 ... nN are * strings that represent the interval list. c1 m1 ... cm mM are pairs * that consist of a region's color and the statistics count. Actually * the c's are trivial procedures that just leave a one character string * on the stack when they're executed by image - which is the way the * bar graph is drawn. * * done * * done * * Makes sure the last page is printed. Only needed when we're printing * more than one page on each sheet of paper. * * Many default values, like the magnification and orientation, are defined in * the prologue, which is where they belong. If they're changed (by options), an * appropriate definition is made after the prologue is added to the output file. * The -P option passes arbitrary PostScript through to the output file. Among * other things it can be used to set (or change) values that can't be accessed by * other options. * */#include <stdio.h>#include <signal.h>#include <ctype.h>#ifdef plan9#define isascii(c) ((unsigned char)(c)<=0177)#endif#include <sys/types.h>#include <fcntl.h>#include <string.h>#include "comments.h" /* PostScript file structuring comments */#include "gen.h" /* general purpose definitions */#include "path.h" /* for the prologue */#include "ext.h" /* external variable declarations */#include "postmd.h" /* special matrix display definitions */char *optnames = "a:b:c:d:g:i:m:n:o:p:w:x:y:A:C:E:J:L:P:R:DI";char *prologue = POSTMD; /* default PostScript prologue */char *formfile = FORMFILE; /* stuff for multiple pages per sheet */char *temp_dir = TEMPDIR; /* temp directory for copying stdin */int formsperpage = 1; /* page images on each piece of paper */int copies = 1; /* and this many copies of each sheet */int bytespp = 6; /* bytes per pattern - on output */int dostats = ON; /* permanent statistics flag */int nxtstat = ON; /* and the one for the next matrix */char *interval = DFLTILIST; /* string representations of the interval */char *colormap = NULL; /* color map */char *window = NULL; /* and window lists */char *matrixname = "pipe.end"; /* name for the next plot */Ilist ilist[128]; /* active interval list and color map */int next = 0; /* one past the last element in ilist[] */int regions; /* an index assigned to the last region */int wlist[4]; /* upper left and lower right corners */int page = 0; /* last page we worked on */int printed = 0; /* and the number of pages printed */int dfltrows = 0; /* default rows */int dfltcols = 0; /* and columns - changed by -d option */int rows; /* real number of rows */int columns; /* and columns in the matrix */int patcount = 0; /* will be set to columns * rows */double element; /* next matrix element */char *raster = NULL; /* next raster line */char *rptr; /* next free byte in raster */char *eptr; /* one past the last byte in raster */FILE *fp_in = stdin; /* read from this file */FILE *fp_out = stdout; /* and write stuff here */FILE *fp_acct = NULL; /* for accounting data *//*****************************************************************************/main(agc, agv) int agc; char *agv[];{/* * * Bitmap display program for matrices. Only one matrix is allowed per input file, * and each one will be displayed on a page by itself. Input files consist of an * optional header followed by floating point numbers that represent the matrix * elements - in row major order. * */ argc = agc; /* other routines may want them */ argv = agv; prog_name = argv[0]; /* really just for error messages */ init_signals(); /* sets up interrupt handling */ header(); /* PostScript header comments */ options(); /* handle the command line options */ setup(); /* for PostScript */ arguments(); /* followed by each input file */ done(); /* print the last page etc. */ account(); /* job accounting data */ exit(x_stat); /* not much could be wrong */} /* End of main *//*****************************************************************************/init_signals(){/* * * Make sure we handle interrupts. * */ if ( signal(SIGINT, interrupt) == SIG_IGN ) { signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGHUP, SIG_IGN); } else { signal(SIGHUP, interrupt); signal(SIGQUIT, interrupt); } /* End else */ signal(SIGTERM, interrupt); signal(SIGFPE, interrupt);} /* End of init_signals *//*****************************************************************************/header(){ int ch; /* return value from getopt() */ int old_optind = optind; /* for restoring optind - should be 1 *//* * * Scans the option list looking for things, like the prologue file, that we need * right away but could be changed from the default. Doing things this way is an * attempt to conform to Adobe's latest file structuring conventions. In particular * they now say there should be nothing executed in the prologue, and they have * added two new comments that delimit global initialization calls. Once we know * where things really are we write out the job header, follow it by the prologue, * and then add the ENDPROLOG and BEGINSETUP comments. * */ while ( (ch = getopt(argc, argv, optnames)) != EOF ) if ( ch == 'L' ) prologue = optarg; else if ( ch == '?' ) error(FATAL, ""); optind = old_optind; /* get ready for option scanning */ fprintf(stdout, "%s", CONFORMING); fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION); fprintf(stdout, "%s %s\n", DOCUMENTFONTS, ATEND); fprintf(stdout, "%s %s\n", PAGES, ATEND); fprintf(stdout, "%s", ENDCOMMENTS); if ( cat(prologue) == FALSE ) error(FATAL, "can't read %s", prologue); fprintf(stdout, "%s", ENDPROLOG); fprintf(stdout, "%s", BEGINSETUP); fprintf(stdout, "mark\n");} /* End of header *//*****************************************************************************/options(){ int ch; /* return value from getopt() *//* * * Reads and processes the command line options. Added the -P option so arbitrary * PostScript code can be passed through. Expect it could be useful for changing * definitions in the prologue for which options have not been defined. * */ while ( (ch = getopt(argc, argv, optnames)) != EOF ) { switch ( ch ) { case 'a': /* aspect ratio */ fprintf(stdout, "/aspectratio %s def\n", optarg); break; case 'b': /* bytes per pattern - on output */ bytespp = atoi(optarg); break; case 'c': /* copies */ copies = atoi(optarg); fprintf(stdout, "/#copies %s store\n", optarg); break; case 'd': /* default matrix dimensions */ sscanf(optarg, "%dx%d", &dfltrows, &dfltcols); break; case 'g': /* set the colormap (ie. grayscale) */ colormap = optarg; break; case 'i': /* matrix element interval list */ interval = optarg; break; case 'm': /* magnification */ fprintf(stdout, "/magnification %s def\n", optarg); break; case 'n': /* forms per page */ formsperpage = atoi(optarg); fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg); fprintf(stdout, "/formsperpage %s def\n", optarg); break; case 'o': /* output page list */ out_list(optarg); break; case 'p': /* landscape or portrait mode */ if ( *optarg == 'l' ) fprintf(stdout, "/landscape true def\n"); else fprintf(stdout, "/landscape false def\n"); break; case 'w': /* set the window */ window = optarg; break; case 'x': /* shift things horizontally */ fprintf(stdout, "/xoffset %s def\n", optarg); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -