From: ger@cv.ruu.nl (Ger Timmens)
Subject: poster (Scale 1page postscript files)
Date: Fri, 8 Jan 1993 14:21:07 GMT
Organization: University of Utrecht, 3D Computer Vision Research Group
Keywords: scaling/multiple pages


This simple c programs poster is a generic PS scaling program,
just 'sh' this file, and compile poster.c with 'cc -O -c poster.c -o poster'.

Have fun,

#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 01/08/1993 14:18 UTC by ger@triton
# Source directory /Userspace1/ger/src/poster
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   2774 -rw-r--r-- README
#     41 -rw-r--r-- bool.h
#   7499 -rw-r--r-- poster.c
#
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
	echo 'x - skipping README (File already exists)'
else
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
Poster - a generic PS scaling program
X
Known restrictions:
1. It only works with one-pager.  Don't try multiple page document with this.
2. Always produce 7.5"x10" tiles with crop marks and grid # at lower right.
3. Won't best fit to use minimum number of tiles by intellegent rotation.  
X   (Enhancements are welcome, make sure you debug it before sending your fix 
X   to me! )
4. It treats Landscape mode page the same way as Portrait page.  The printing
X   is okay, but the width/height specification and grid numbering is rotated.
X   (use it on a Landscape page and look at the grid #, you'll see what I mean)
5. It uses brute force, it outputs the whole file once for each tile produced.
X   If you're printing a 1/4 Megabyte PS file on 4 tiles, you are creating a
X   file over one megabyte in size and takes 4 times as long to print.
6. If no BoundingBox info is found, assumes 0 0 612 792.  Will not look for
X   BoundingBox info beyond the first %%EndComments line (try to prevent getting
X   the wrong one from other imbedded images.)
7. Only leave 1/2" inch border.  If you need extra spacing around the image,
X   you should alter the BoundingBox info yourself.
8. Works well with all my PS images.  Yours?  Good luck! :-)
X
Compilation:
X	cc -o poster poster.c
X
Usage:
X	poster ps-file width height [ row col ]
X
X	ps-file is your well behaving PS program.
X	width and height is the output dimension expressed in inches.
X		Since the tiles are 7.5"x10", using 15 20 will usually
X		produces 2x2 (4) tiles.  Depends on the aspect ratio
X		of the BoundingBox, unneeded tiles will not be output.
X		The program will fit the image in the area specified
X		without altering the aspect ratio.  Hence using 15 10000
X		means you don't care about the height.  It will create
X		as many tiles as needed to fit the width.  
X	row and col is the grid that you want to output.  If not specified,
X	all tiles are output in the same stream.  This is useful in case
X	some tiles are demaged by paper jam.  Also if your PS program is
X	big and sending it out multiple times in one job is impossible,
X	then you can use a loop to output the tiles in separate jobs, e.g.
X
X		foreach i (1 2 3 4)
X			foreach j (1 2 3 4)
X				poster ps-file 30 40 $i $j | lpr -Pps
X			end
X		end
X
X	will print all 16 tiles (30"x40" output) to the printer.
X
Advice:
1	print the poster only at off hours.  
2	Enough overlapping of image is produced to assist easy fitting.
3	Paste every other tiles together in a "checker-board" manner (leave
X	the borders intact, only cut out the corners near the crop marks) 
X	and then clip the rest of the tiles along the crop marks and then paste 
X	the tiles on the "checker-board".  The borders that you left behind in 
X	the previous step now provide nice backing for the rest of the tiles.
SHAR_EOF
chmod 0644 README ||
echo 'restore of README failed'
Wc_c="`wc -c < 'README'`"
test 2774 -eq "$Wc_c" ||
	echo 'README: original size 2774, current size' "$Wc_c"
fi
# ============= bool.h ==============
if test -f 'bool.h' -a X"$1" != X"-c"; then
	echo 'x - skipping bool.h (File already exists)'
else
echo 'x - extracting bool.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bool.h' &&
int BOOL;
#define TRUE 0
#define FALSE 1
SHAR_EOF
chmod 0644 bool.h ||
echo 'restore of bool.h failed'
Wc_c="`wc -c < 'bool.h'`"
test 41 -eq "$Wc_c" ||
	echo 'bool.h: original size 41, current size' "$Wc_c"
fi
# ============= poster.c ==============
if test -f 'poster.c' -a X"$1" != X"-c"; then
	echo 'x - skipping poster.c (File already exists)'
else
echo 'x - extracting poster.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'poster.c' &&
/*
#  poster.c  -  a generic PS scaling program
#  This program outputs a PostScript page to a given size, create tiles if necessary.
#	each tile will be 7.5" by 10" with crop marks.
#
######################
#  CopyRight Notice: #
######################
#
#  Feel free to distribute or use, provided that nothing is changed.
#  Please send comments, bug fixes to pyramid!daisy!cplai
#
#  Author:  C.P. Lai  (All rights reserved)
#  Creation Date: Dec 22, 1987
#  Modification History:  
#		by C.P. Lai on Aug 18, 1989  for BoundingBox Handling.
#
#
#  Usage:  Poster ps-file width height [row col] | lpr -Pps
#	where ps-file is the file name of the PostScript page
#		width and height are the size in inches
#		row and col are option if only one tile is to be printed.
#		default is to print all tiles
*/
X
#include <stdio.h>
#include "bool.h"
#define BUFSIZE 512
/* tile size */
#define PAGEW 7.5
#define PAGEH 10.0
X
main (argc, argv)
int argc;
char *argv[];
{
char *pagename;
float width, height;
int row, col, llx, lly, urx, ury;
X
X	row = col = 0;
X	/* accepts only two command formats */
X	if (!(argc == 4 || argc == 6)) usage(argv[0]);	
X	pagename = argv[1];
X	if (sscanf (argv[2], "%f", &width) != 1) usage(argv[0]);
X	if (sscanf (argv[3], "%f", &height) != 1) usage(argv[0]);
X	if (argc == 6) {
X		if (sscanf (argv[4], "%d", &row) != 1) usage(argv[0]);
X		if (sscanf (argv[5], "%d", &col) != 1) usage(argv[0]);
X		if (row<1 || col<1) usage(argv[0]);
X	}
X	getBoundingBox (pagename, &llx, &lly, &urx, &ury);
X	printposter (pagename, llx, lly, urx, ury, width, height, row, col);
X
X	exit (0);
}
X
/**************************************/
/* output usage message and terminate */
/**************************************/
usage (prog_name)
char *prog_name;
{
X	fprintf (stderr, "Usage:\t%s ps-file width height [row col]\n", prog_name);
X	fprintf (stderr, "\twhere ps-file is the file name of the PostScript page\n");
X	fprintf (stderr, "\twidth and height are the size in inches\n");
X	fprintf (stderr, "\trow and col are option if only one tile is to be printed.\n");
X	fprintf (stderr, "\tdefault is to print all tiles.\n");
X	exit (1);
}
X
/*********************************************/
/* output the poster, create tiles if needed */
/*********************************************/
printposter (pagename, llx, lly, urx, ury, width, height, row, col)
char *pagename;
int llx, lly, urx, ury, row, col;
float width, height; 
{
int nrow, ncol, imagew, imageh; 
float xscale, yscale, scale;
X
X	imagew = urx - llx;
X	imageh = ury - lly;
X	xscale = (width * 72) / imagew;
X	yscale = (height * 72) / imageh;
X	scale = (xscale<yscale)?xscale:yscale;
X
X	/* adjust actual width and height based on aspect ratio */
X	width = imagew * scale / 72;
X	height = imageh * scale / 72;
X
X	ncol = (int) (width / PAGEW);
X	/* add one column if exceed by one user space unit */
X	if ((width-(ncol*PAGEW))*72 > 1) { ncol++; }
X	nrow = (int) (height / PAGEH);
X	/* add one row if exceed by one user space unit */
X	if ((height-(nrow*PAGEH))*72 > 1) { nrow++; }
X
X	if (row>nrow || col>ncol) {
X		fprintf (stderr, "The image does not fall on grid (%d,%d)\n", row, col);
X		exit (1);
X	}
X
X	printf ("%%!PS\t");
X	if (row == 0 || col == 0)
X 		printf ("All grids ");
X	else
X		printf ("Grid (%d,%d) ", row, col);
X	printf ("of poster %s in %dx%d tiles at %f scale\n", 
X		pagename, nrow, ncol, scale);
X
X	printprolog (scale, llx, lly);
X	if (row == 0 || col == 0) {
X		/* all tile */
X		for (row = 1; row <= nrow; row++)
X			for (col = 1; col <= ncol; col++)
X				tile (pagename, row, col);
X	} else tile (pagename, row, col);
X	printf ("%% End of Poster %s\n", pagename);
X	return;
}
X
/*******************************************************/
/* output PS prolog of the scaling and tiling routines */
/*******************************************************/
printprolog (scale, llx, lly)
float scale;
int llx, lly;
{
printf ("%%%%Creator: poster - a tiling program by C.P. Lai\n\n");
X
printf ("\
/cropmark	%% x y cropmark -\n\
{	%%def\n\
X	/y exch def\n\
X	/x exch def\n\
X	gsave\n\
X	0 y rmoveto\n\
X	0 y 2 mul rlineto \n\
X	gsave\n\
X	1 setgray 3 setlinewidth stroke	%% paint background white to highlite mark\n\
X	grestore\n\
X	0 setgray 0 setlinewidth stroke	%% use thinnest line on device\n\
X	grestore\n\
X	x 0 rmoveto\n\
X	x 2 mul 0 rlineto \n\
X	gsave\n\
X	1 setgray 3 setlinewidth stroke	%% paint background white to highlite mark\n\
X	grestore\n\
X	0 setgray 0 setlinewidth stroke	%% use thinnest line on device\n\
} bind def\n\n");
X
printf ("\
%% usage: 	row col tileprolog ps-code tilepilog\n\
%% these procedures output the tile specified by row & col\n\
/tileprolog\n\
{ 	%%def\n\
X	gsave\n\
X	/colcount exch def\n\
X	/rowcount exch def\n\
X	gsave\n\
X	pagewidth colcount 1 sub mul neg\n\
X	pageheight rowcount 1 sub mul neg\n\
X	translate\n\
X	sfactor dup scale\n\
X	llx neg lly neg translate\n\
X	tiledict begin\n\
} bind def\n\n");
X
printf("\
/tilepilog\n\
{	%%def\n\
X	end %% of tiledict\n\
X	grestore\n\
X	%% output the crop marks\n\
X	0 0 moveto\n\
X	-9 -9 cropmark\n\
X	0 pageheight moveto\n\
X	-9 9 cropmark\n\
X	pagewidth 0 moveto\n\
X	9 -9 cropmark\n\
X	pagewidth pageheight moveto\n\
X	9 9 cropmark\n\n\
X	1 setgray\n\
X	18 -18 moveto\n\
X	0 9 rlineto\n\
X	72 0 rlineto\n\
X	0 -9 rlineto\n\
X	closepath\n\
X	fill\n\n\
X	0 setgray\n\
X	18 -18 moveto\n\
X	(Grid \\( ) show\n\
X	rowcount strg cvs show\n\
X	( , ) show\n\
X	colcount strg cvs show\n\
X	( \\)) show\n\n\
X	showpage\n\
X	grestore\n\
} bind def\n\n");
X
printf("\
/sfactor %f def\n\
/llx %d def\n\
/lly %d def\n\
/leftmargin 36 def\n\
/botmargin 36 def\n\
/pagewidth %d def\n\
/pageheight %d def\n\n\
/strg 10 string def\n\
/tiledict 250 dict def\n\
tiledict begin\n\
/showpage {} def	%% delay users showpage until cropmark is printed.\n\
end\n\
%% end of prolog\n\n", scale, llx, lly, (int) (PAGEW * 72), (int) (PAGEH * 72));
X
printf ("\
/Times-Roman findfont 9 scalefont setfont\n\
%% readjust the origin to coincides with the cropping mark\n\
leftmargin botmargin translate\n\n");
return;
}
X
/*****************************/
/* output one tile at a time */
/*****************************/
tile (pagename, row, col)
char *pagename;
int row, col;
{
printf ("%d %d tileprolog\n", row, col);
printf ("%% Start of included ps code\n%% vvvvvvvvvvvv\n");
printfile (pagename);
printf ("%% ^^^^^^^^^^^^\n%% End of included ps code\n");
printf ("tilepilog\n");
return;
}
X
/******************************/
/* copy the PS file to output */
/******************************/
printfile (filename)
char* filename;
{
char tmp_byte;
X
X	if (freopen (filename, "r", stdin) == NULL) {
X		fprintf (stderr, "fail to open file %s\n", filename);
X		printf ("/systemdict /showpage get exec\n");
X		exit (1);
X	}
X	while ((tmp_byte = getchar()) != EOF)
X		putchar (tmp_byte);
X	return;
}
X
/*********************************************/
/* extract BoundingBox info from the PS file */
/*********************************************/
getBoundingBox (filename, llxp, llyp, urxp, uryp)
char *filename;
int *llxp, *llyp, *urxp, *uryp;
{
char buf[BUFSIZE];
int not_found;
X
X	/* initialize to 0 0 612 792 for defaults */
X	*llxp = *llyp = 0;
X	*urxp = 612; *uryp = 792;
X
X	if (freopen (filename, "r", stdin) == NULL) {
X		fprintf (stderr, "fail to open file %s\n", filename);
X		exit (1);
X	}
X	not_found = TRUE;
X	while (not_found && (gets(buf) != NULL)) {
X		/* cut short if not found */
X		if (strncmp (buf, "%%EndComments", 13) == 0) {
X			not_found = FALSE;
X			break;
X		}
X		if (sscanf (buf, "%%%%BoundingBox: %d %d %d %d", llxp, llyp, urxp, uryp) == 4)
X			not_found = FALSE;
X	}
X	return;
}
SHAR_EOF
chmod 0644 poster.c ||
echo 'restore of poster.c failed'
Wc_c="`wc -c < 'poster.c'`"
test 7499 -eq "$Wc_c" ||
	echo 'poster.c: original size 7499, current size' "$Wc_c"
fi
exit 0
-- 
|I|        Ger Timmens         |I| If you're not part of the solution, |I|
|M|  3D Computer Vision Group  |M| you're part of the problem!         |M|
|H|    e-mail ger@cv.ruu.nl    |H+-------------------------------------+H|
|O|   or  timmens@cs.unc.edu   |O| Album by Joe Henderson (best tenor) |O|