Subject: converting PostScript to EPSI

From: [email-masked] (Dongchul Lim)
Date: Sun, 10 Apr 1994 23:19:30 -0400 (EDT)

A while ago, someone asked how to put a preview image into a PostScript file.
Probably this fits better in comp.lang.postscript,
but I'll post my own solution here.

EPS files can optionally contain one of three image preview formats,
i.e., PICT, TIFF and a platform independent bitmapped image.
EPS files with TIFF preview are called EPSF
and those with a bitmap preview are called EPSI.

I'm going to explain how to insert preview image into a PostScript file,
i.e., how to convert EPS to EPSI.
Before you proceed, you must have 
1) PostScript interpreter
2) snapshot (a program which grabs a portion of screen image)
3) a utility which converts image data from snapshot into PostScript
   image format.

For example, on SGI, you have
'xpsview' for PostScript interpreter,
'snapshot' for snapshot,
and 'rgb2pv' for the image conversion utility, which I wrote.

Let's say you have a PostScript file called 'file.eps'.
1) This step is not necessary, unless you want to find out the exact
   bounding box. 'bbfig' can be found in calypso-2.oit.unc.edu
   in the directory of /pub/packages/TeX/dviware/dvips/dvips/contrib/bbfig.

   % bbfig file.eps > file.bbfig

2) Open 'file.eps' or 'file.bbfig' with 'xpsview'.
      % xpsview file.eps 
   or % xpsview file.bbfig
3) Cut the image within the bounding box with 'snapshot'.
   Save the image into 'file.rgb'.
   % snapshot
4) Convert RGB image to PostScript image and insert it in 'file.eps'.
   % rgb2pv file.eps file.rgb > file.epsi

On other systems, you'll have to find out your own solution
(e.g., use 'ghostscript' and 'eps2epsi').

***************************
* Dongchul Lim            *
* Department of Chemistry *
* Yale University         *
***************************

-------------- CUT HERE (rgb2pv.c) ----------------------------------
/******************************************************************
* When you have a RGB image of a PostScript file, this program    *
* can be used to put a preview image into the PostScript file.    *
* This works on SGI only. The image library (/usr/lib/libimage.a) *
* is required for compilation.                                    *
*                                                                 *
* Compilation: cc -o rgb2pv rgb2pv.c -limage -lm                  *
* Usage: rgb2pv PSfile RGBfile                                    *
*                                                                 *
* Author: Dongchul Lim                                            *
*         Department of Chemistry, Yale University                *
*         [email-masked] (April, 1994)                    *
*******************************************************************/

#include <stdio.h>
#include <malloc.h>
#include <gl/image.h>
#define READLINE(fp, str)	fgets((str), sizeof((str)), (fp))

static void	image_error(char *msg)
{
	fprintf(stderr, "%s\n", msg);
}

static void	insert_preview (FILE *fp, unsigned long *pv_data, int pv_width, int pv_height)
{
	int	x, y, col, shift;
	int	pv_depth, pv_lines;
	unsigned long	*pixel, p;

	if (!fp || !pv_data || pv_width <= 0 || pv_height <= 0) return;

	/* count the number of Preview lines */
	pv_lines = 0;
	for(y=pv_height-1,col=0;y>=0;y--) {
		for(x=0;x<pv_width;x++) {
			col += 2;
			if (col > 80) {pv_lines++; col = 0;}
		}
		pv_lines++;
		col = 0;
	}

	/* actual writing of preview image */
	pv_depth = 8;
	fprintf(fp, "%%%%BeginPreview: %d %d %d %d\n", pv_width, pv_height, pv_depth, pv_lines);

	for(y=pv_height-1,col=0;y>=0;y--) {
		pixel = pv_data + y * pv_width;
		fprintf(fp, "%%%%");
		for (x=0;x<pv_width;x++) {
			p = *pixel++;
			fprintf(fp, "%02x", (int)(((77*((p>>16)&0XFF))+(151*((p>>8)&0XFF))+(28*(p&0XFF))) >> 8));
			col += 2;
			if (col > 80) {
				fprintf(fp, "\n");
				fprintf(fp, "%%%%");
				col = 0;
			}
		}
		fprintf(fp, "\n");
		col = 0;
	}
	fprintf(fp, "%%%%EndPreview\n");
}

int	main (int argc, char *argv[])
{
	IMAGE	*image;
	FILE	*ifp, *ofp, *tmpfp;
	char	*psfile, *imagefile, str[256];
	int	pv_width, pv_height, pv_lines;
	register int	y, width;
	register unsigned short	*sp, *rp, *gp, *bp, *ap, *rbuf, *gbuf, *bbuf, *abuf;
	register unsigned long	*lp, *base;

	if (argc < 3) {
		fprintf(stderr, "Usage: %s psfile imagefile\n", argv[0]);
		exit(1);
	}
	psfile    = argv[1];
	imagefile = argv[2];

	i_seterror(image_error);
	if (!(image = iopen(imagefile, "r"))) exit(1);
	if (image->xsize <= 0 || image->ysize <= 0 || image->zsize <= 0) {
		fprintf(stderr, "size of image is zero.\n");
		iclose(image);
		exit(1);
	}
		
	/* read in pixel values */
	base = (unsigned long *)malloc(image->xsize * image->ysize * sizeof(unsigned long));
	rbuf = (unsigned short *)malloc(image->xsize * sizeof(unsigned short));
	gbuf = (unsigned short *)malloc(image->xsize * sizeof(unsigned short));
	bbuf = (unsigned short *)malloc(image->xsize * sizeof(unsigned short));
	abuf = (unsigned short *)malloc(image->xsize * sizeof(unsigned short));
	if (!base || !rbuf || !gbuf || !bbuf) {
		iclose(image);
		fprintf(stderr, "not enough memory.\n");
		exit(1);
	}

	lp = base;
	for (y=0;y<image->ysize;y++) {
		width = image->xsize;
		rp = rbuf;
		gp = gbuf;
		bp = bbuf;
		ap = abuf;

		switch (image->zsize) {
		case 1:
		case 2:
			getrow(image, rbuf, y, 0);
			while (width--) *lp++ = 0x00010101 * (*rp++);
			break;
		case 3:
			getrow(image, rbuf, y, 0);
			getrow(image, gbuf, y, 1);
			getrow(image, bbuf, y, 2);
			while (width--) *lp++ = *rp++ | ((*gp++)<<8) | ((*bp++)<<16);
			break;
		default:
			getrow(image, rbuf, y, 0);
			getrow(image, gbuf, y, 1);
			getrow(image, bbuf, y, 2);
			getrow(image, abuf, y, 3);
			while (width--) *lp++ = *rp++ | ((*gp++)<<8) | ((*bp++)<<16) | ((*ap++)<<24);
			break;
		}
	}

	pv_width  = image->xsize;
	pv_height = image->ysize;
	iclose(image);
	free(rbuf);
	free(gbuf);
	free(bbuf);
	free(abuf);

	/* open input PostScript, output PostScript and tmp scractch files */
	if (!(ifp = fopen(psfile, "r"))) {
		fprintf(stderr, "Can't open file %s.\n", psfile);
		free(base);
		exit(1);
	}
	tmpfp = tmpfile();
	ofp = stdout;

	/* get rid of previous preview image */
	rewind(ifp);
	READLINE(ifp, str);
	if (strncmp(str, "%!", 2) != 0) {
		fprintf(stderr, "%s is not a PostScript file.\n");
		fclose(ifp); fclose(ofp); fclose(tmpfp); free(base);
		exit(1);
	}
	fprintf(tmpfp, "%!PS-Adobe-3.0 EPSI-3.0\n");
	while (READLINE(ifp, str)) {
		if (strncmp(str, "%%BeginPreview:", 15) == 0) {
			sscanf(str+15, "%*d %*d %*d %d", &pv_lines);
			while (pv_lines-- > 0) READLINE(ifp, str);
			continue;
		}
		fprintf(tmpfp, "%s", str);
	}

	/* insert preview image */
	rewind(tmpfp);
	while (READLINE(tmpfp, str)) {
		if (str[0] != '%') {	/* insert preview image */
			insert_preview(ofp, base, pv_width, pv_height);
			break;
		}
		fprintf(ofp, "%s", str);
	}
	free(base);

	/* concatenate the rest of the PostScript file to the output */
	while (READLINE(tmpfp, str)) fprintf(ofp, "%s", str);

	/* close all files */
	fclose(ifp);
	fclose(ofp);
	fclose(tmpfp);

	exit(0);
}

-------------- CUT HERE (rgb2pv.c) ----------------------------------