home *** CD-ROM | disk | FTP | other *** search
- /*
- * Written by Leonid Rosenboim, Tel-Aviv University, Israel. This code is
- * placed in Punlic Domain on Feb 1988. May be copied freely for any purpose.
- */
-
- static char sccsid[] = "@(#)psraster.c 2.3 leonid@math.tau.ac.IL 88/06/16";
-
- /*
- * Standard rasterfile to PostScript filter.
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <pixrect/pixrect_hs.h>
-
- #define INCH * 72
- #define PG_SIZE_X ( 8.0 INCH ) /* Canvas is 7.5" x 9.5" area on a
- * 8x10.8" paper */
- #define PG_SIZE_Y ( 10.8 INCH )
- #define MAXBOX_X ( 7.5 INCH )
- #define MAXBOX_Y ( 9.0 INCH )
-
- #ifndef DESTLIB
- # define DESTLIB "/usr/local/lib/ps"
- #endif DESTLIB
-
- #define PROLOGUE "/psraster.ps"
- #define FALSE 0
- #define TRUE !FALSE
-
- #define MAX_LINE 0x7f
- #define FLAG 0x80
- #define min(x,y) (((x)<(y))?(x):(y))
- #define max(x,y) (((x)<(y))?(y):(x))
-
- #define SERROR(err_message) \
- {(void)fprintf(stderr, "%s: %s\n", Progname, err_message); exit(1);}
-
- #define ERR_RASTYPE "Input raster has incorrect ras_type"
- #define ERR_MAPTYPE "Input raster has incorrect ras_maptype"
- #define ERR_UNITS "Unrecognized units code"
- #define MY_RAS_TYPE RT_BYTE_ENCODED
-
- struct box { /* Bounding box structure, all in 1/72"
- * points */
- short size_x;
- short size_y;
- short off_x;
- short off_y;
- };
-
- struct box Canvas; /* The drawing canvas, default almost the
- * whole page */
- struct box Bounds; /* The actual BoundingBox for image */
-
- extern int pr_load_colormap(), pr_load_header();
- extern struct pixrect *pr_load_std_image();
- extern double
- atof(), strtod();
-
- FILE *infile, *outfile;
-
- char *file_name; /* Input filename or stdin */
- char *Progname; /* Program Name for error message generation */
- unsigned char *greymap; /* Grey level map */
-
- /* Program behaviour modifiers */
- int flg_inverse = 0;/* Weather the program must perform negation */
- int flg_square = 0; /* Put the image in a sqare */
- int flg_portrait = 0; /* Force Posrtait Mode */
- int flg_landscape = 0; /* Force Landscape Mode */
- int flg_noshow = 0; /* Supress showpage */
- int flg_nogrey = 0; /* Supress grey level calculation */
- float opt_scale = 0.; /* Scaling Factor */
-
- /*
- * Translate a string from inches/centimeters/points to points.
- */
- double
- points(s)
- char *s;
- {
- double v;
- char *p = s;
-
- v = strtod(s, &p);
- if ((p == NULL))
- return (v);
- switch (*--p) {
- case 'c':
- v *= (1 / 2.54);
- case 'i':
- v *= 72;
- case 'p':
- case '\0':
- case '0':
- break;
- default:
- SERROR(ERR_UNITS);
- }
- return (v);
- }
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- extern char *optarg;
- extern int optind;
- int c;
- /* Initialize default Canvas */
- Canvas.size_x = MAXBOX_X;
- Canvas.size_y = MAXBOX_Y;
- Canvas.off_x = -1;
- Canvas.off_y = -1;
-
-
- for (; optind < argc; optind++) {
-
- /*
- * Process argc/argv.
- */
- Progname = argv[0];
- while ((c = getopt(argc, argv, "plisnx:y:X:Y:z:")) != EOF)
- switch (c) {
- case 'i':
- flg_inverse++;
- break;
- case 's':
- flg_square++;
- break;
- case 'p':
- flg_portrait++;
- break;
- case 'l':
- flg_landscape++;
- break;
- case 'n':
- flg_noshow++;
- break;
- case 'z':
- opt_scale = atof(optarg);
- break;
- case 'x':
- Canvas.off_x = points(optarg);
- break;
- case 'y':
- Canvas.off_y = points(optarg);
- break;
- case 'X':
- Canvas.size_x = points(optarg);
- break;
- case 'Y':
- Canvas.size_y = points(optarg);
- break;
- }
-
- /* Center the canvas on the page */
- if (Canvas.off_x == -1)
- Canvas.off_x = (PG_SIZE_X - Canvas.size_x) / 2;
- if (Canvas.off_y == -1)
- Canvas.off_y = (PG_SIZE_Y - Canvas.size_y) / 2;
-
- outfile = stdout;
-
- if (optind == argc) {
- file_name = "Standard Input";
- load(stdin);
- } else {
- if ((infile = fopen(argv[optind], "r")) == NULL) {
- perror(argv[optind]);
- continue;
- }
- file_name = argv[optind];
- load(infile);
- }
- flg_square = flg_portrait = flg_landscape = flg_noshow = 0;
- opt_scale = 0;
- Canvas.size_x = MAXBOX_X;
- Canvas.size_y = MAXBOX_Y;
- Canvas.off_x = -1;
- Canvas.off_y = -1;
-
- }
- }
-
- /*
- * Process each raster file passed as argument, but make sure that the
- * prologue is written only once. Here we load the raster image and call
- * another routine to do the job.
- */
-
- load(infile)
- FILE *infile;
- {
- extern char *malloc();
- #define MALLOC(size) (unsigned char *)malloc((unsigned int)(size))
- struct pixrect *input_pr;
- struct rasterfile rh;
- colormap_t colormap;
-
- /*
- * Load the rasterfile header and the colormap (if there is one).
- * Also perform a few sanity checks on the rasterfile.
- */
- if (pr_load_header(infile, &rh) == PIX_ERR)
- SERROR(PR_IO_ERR_RASREAD);
- switch (colormap.type = rh.ras_maptype) {
- case RMT_NONE:
- greymap = NULL;
- break;
- case RMT_EQUAL_RGB:
- colormap.length = rh.ras_maplength / 3;
- colormap.map[0] = MALLOC(colormap.length);
- colormap.map[1] = MALLOC(colormap.length);
- colormap.map[2] = MALLOC(colormap.length);
- greymap = MALLOC(colormap.length);
- if (pr_load_colormap(infile, &rh, &colormap) == PIX_ERR)
- SERROR(PR_IO_ERR_RASREAD);
- if (!flg_nogrey) {
- register i;
- for (i = 0; i < colormap.length; i++)
- greymap[i] = (unsigned char)
- rint(sqrt((
- pow((double) colormap.map[0][i], 2.) +
- pow((double) colormap.map[1][i], 2.) +
- pow((double) colormap.map[2][i], 2.)) / 3.));
- }
- break;
- default:
- SERROR(ERR_MAPTYPE);
- }
- /*
- * If the rasterfile is a standard type, use pr_load_std_image to
- * read the image. If the rasterfile is non-standard type, use an
- * appropriate routine to read the image (for RT_BYTE_ENCODED, this
- * turns out to also be pr_load_std_image). In either case, transform
- * the input to the other type and output it.
- */
- switch (rh.ras_type) {
- case RT_STANDARD:
- if ((input_pr = pr_load_std_image(infile, &rh)) == NULL)
- SERROR(PR_IO_ERR_RASREAD);
-
- dump(input_pr);
- break;
- case MY_RAS_TYPE:
- if ((input_pr = pr_load_std_image(infile, &rh)) == NULL)
- SERROR(PR_IO_ERR_RASREAD);
-
- dump(input_pr);
- break;
- default:
- SERROR(ERR_RASTYPE);
- }
- }
-
- /*
- * This is the main procedure which dumps a raster it receives as argument on
- * the output in PostScript format. Routimes below are used for assist
- */
-
- dump(pr)
- struct pixrect *pr;
- {
- register int br, br1;/* Bytes per raw */
- struct mpr_data *mpr = (struct mpr_data *) pr->pr_data;
- register unsigned char *p;
- register x, y;
-
- /*
- * Compute the number of bytes per row : Here we have a slight
- * problem - rasterfile(5) number of bytes for each pixel row is
- * rounded to short, but in PostScript it must be rounded to 1 byte.
- * Hence, br is assigned the byte-pre-row from the input raster, and
- * br1 will have the correct value for PostScript.
- */
-
- br = mpr->md_linebytes;
- br1 = (pr->pr_size.x * pr->pr_depth - 1) / 8 + 1;
- if ((br != br1) && ((br - br1) != 1))
- (void) fprintf(stderr, "Warning: Bytes per line %d -> %d\n", br, br1);
-
- put_prologue(pr, br1);
-
- /* Start of memory image itself */
- p = (unsigned char *) mpr->md_image;
-
- for (y = 0; y < pr->pr_size.y; y++) {
- if (greymap != NULL)
- for (x = 0; x < br1; x++)
- p[x] = greymap[p[x]];
- put_line(p, br1);
- p += br;
- }
- if (!flg_noshow)
- (void) fprintf(outfile, "showpage\n");
- (void) fprintf(outfile, "grestore\n");
- }
-
- /*
- * Write the PostScript prologue, the constant and the variable parts. The
- * variable part is output for each image, and the appropriate
- * transformations are calculated.
- */
-
- put_prologue(pr, br)
- struct pixrect *pr;
- int br;
- {
- static int count = 0; /* Image counter */
- float cv_aspect, im_aspect; /* Canvas and image aspect
- * ratios */
- int x_size, y_size;
-
- /* Write the constant prologue */
- if (count == 0)
- get_prologue();
- count++;
-
- (void) fprintf(outfile, "gsave\n");
- (void) fprintf(outfile, "%%Rasterfile Image: %s\n", file_name);
- (void) fprintf(outfile, "%%Format:%d width %d hight %d depth\n",
- pr->pr_size.x, pr->pr_size.y, pr->pr_depth);
-
- /* Calculate aspect ratios ( y / x ) */
- cv_aspect = (float) Canvas.size_y / (float) Canvas.size_x;
- im_aspect = (float) pr->pr_size.y / (float) pr->pr_size.x;
-
- /* Decide weather to use Portrait or Landscape mode */
- if (flg_portrait == flg_landscape) {
- /*
- * Here we dont make any assumption as to the canvas
- * dimentions since it may be arbitratily set by the user
- */
- if ((cv_aspect > 1) && (im_aspect > 1) ||
- (cv_aspect < 1) && (im_aspect < 1))
- flg_portrait = TRUE;
- else
- flg_portrait = FALSE;
- flg_landscape = !flg_portrait;
- }
- if (flg_landscape) {
- x_size = pr->pr_size.y;
- y_size = pr->pr_size.x;
- } else {
- x_size = pr->pr_size.x;
- y_size = pr->pr_size.y;
- }
-
- /* Now we'll handle the scaling factor */
-
- if (opt_scale == 0.) {
- opt_scale = min((float) Canvas.size_x / (float) x_size,
- (float) Canvas.size_y / (float) y_size);
- }
- /* Fill in the Bounds structure */
- Bounds.size_x = (float) x_size *opt_scale;
- Bounds.size_y = (float) y_size *opt_scale;
- Bounds.off_x = Canvas.off_x + (Canvas.size_x - Bounds.size_x) / 2;
- Bounds.off_y = Canvas.off_y + (Canvas.size_y - Bounds.size_y) / 2;
-
- if (flg_square) { /* But if aspect ratio is to be ignored we'll
- * use a trivial formula */
- Bounds = Canvas;
- }
- #ifdef DEBUG
- (void) fprintf(stderr, "Drawing %s in %s mode, with scaling of %f\n",
- file_name, (flg_portrait) ? "portrait" : "landscape", opt_scale);
- (void) fprintf(stderr, "Canvas size %d %d, offset %d %d\n",
- Canvas.size_x, Canvas.size_y, Canvas.off_x, Canvas.off_y);
- (void) fprintf(stderr, "Image size %d %d, offset %d %d\n",
- Bounds.size_x, Bounds.size_y, Bounds.off_x, Bounds.off_y);
- #endif
- (void) fprintf(outfile, "%%%%BoundingBox [ %d %d %d %d ]\n",
- Bounds.off_x, Bounds.off_y,
- Bounds.off_x + Bounds.size_x,
- Bounds.off_y + Bounds.size_y);
-
- if (flg_portrait) {
- (void) fprintf(outfile, "%%%% Using Portrait mode\n");
- (void) fprintf(outfile, "%d %d translate %d %d scale\n",
- Bounds.off_x, Bounds.off_y,
- Bounds.size_x, Bounds.size_y);
- } else {
- (void) fprintf(outfile, "%%%% Using Landscape mode\n");
- (void) fprintf(outfile, "%d %d translate -90 rotate %d %d scale\n",
- Bounds.off_x, Bounds.off_y + Bounds.size_y,
- Bounds.size_y, Bounds.size_x);
- }
-
- if (flg_inverse)
- (void) fprintf(outfile, "{1 exch sub} settransfer ");
-
- (void) fprintf(outfile, "\n");
- (void) fprintf(outfile, "/picst %d string def \n", br);
- /* Dimensions */
- (void) fprintf(outfile, "%d %d %d \n",
- pr->pr_size.x, pr->pr_size.y, pr->pr_depth);
- /* Unit array */
- (void) fprintf(outfile, "[ %d 0 0 -%d 0 %d ]\n",
- pr->pr_size.x, pr->pr_size.y, pr->pr_size.y);
- /* Call Image */
- (void) fprintf(outfile, "{GetImageRow} image\n");
- }
-
- /*
- * Output a single pixel row in the encoded hexa format. Here is the format
- * description:
- *
- * Each output line consistes of a record that starts with one hexa byte C and
- * eands with a newline. if C > 0, then following will be C hexa bytes of
- * data. if C < 0, if will be followed by one hexa byte which must be
- * repeated (-C) times.
- */
- put_line(p, br)
- unsigned char *p;
- int br;
- {
- register i;
- register unsigned char *q;
-
- while (br) {
- for (q = p, i = 0; i < min(MAX_LINE, br); i++, q++)
- if (rep_count(q, (int) 6) > 5)
- break;
-
- if (i != 0) {
- br -= i;
- (void) fprintf(outfile, "%02x", (unsigned char) i);
- for (; i; i--)
- (void) fprintf(outfile, "%02x", (unsigned char) *p++);
- } else {
- i = rep_count(p, br);
- i = min(i, min(MAX_LINE, br));
- (void) fprintf(outfile, "%02x", (unsigned char) (i | FLAG));
- (void) fprintf(outfile, "%02x", (unsigned char) *p);
- p += i;
- br -= i;
- }
- (void) fprintf(outfile, "\n");
- }
- }
-
- /*
- * Count the number of repeated bytes starting at *p. Search is mimmited to n
- * subsequent bytes.
- */
- int
- rep_count(p, n)
- unsigned char *p;
- int n;
- {
- register i;
- register char unsigned c;
- if (((c = *p) != *(p + 1)) || (c != *(p + 2)))
- return (0);
- for (i = 0; (c == *p) && (i < n); i++, p++);
- return (i);
- }
-
- /*
- * Print the invariable part of the PostScript prologue.
- */
- get_prologue()
- {
- FILE *pro;
- char buffer[BUFSIZ];
- int c;
-
- (void) strcpy(buffer, DESTLIB);
- (void) strcat(buffer, PROLOGUE);
-
- pro = fopen(buffer, "r");
- if (pro == NULL) {
- perror(buffer);
- exit(1);
- }
- (void) fprintf(outfile, "%%!\n%%%%Generated by %s version %s\n",
- Progname, sccsid);
-
- c = fread(buffer, 1, sizeof(buffer), pro);
- for (; c > 0;) {
- (void) fwrite(buffer, 1, c, outfile);
- c = fread(buffer, 1, sizeof(buffer), pro);
- }
- }
-