home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Der Mediaplex Sampler - Die 6 von Plex
/
6_v_plex.zip
/
6_v_plex
/
DISK2
/
MULTI_04
/
GIFTOEPS.ZIP
/
GIFTOPS.C
< prev
next >
Wrap
Text File
|
1990-07-12
|
15KB
|
478 lines
/*********************************************
* GIFtoPS Converter *
* *
* May 16, 1988 by Scott Hemphill *
* *
* I wrote this program, and hereby place it *
* in the public domain, i.e. there are no *
* copying restrictions of any kind. *
* *
* Command line processing, EPSF support, *
* and image positioning by Mic Kaczmarczik, *
* modeled after James Frew's ``suntops'' *
* *
* All ints were assumed 32 bits, changed to *
* work with 16 bit ints with mwc on Atari ST*
* The routine below provides the getopt() *
* routine unavailable with mwc. *
* A GEM version for the Atari ST may be *
* appearing soon in the Atari SIG. *
* Mark Storkamp 3/24/90. *
* *
* Converted to compile under Turbo C 2.0 *
* Changed "raster","fill", and "scanline" *
* to HUGE pointers and compiled using *
* "compact" memory model. Also stripped out *
* the getopt() function (for troubleshooting*
* purposes). Turbo C includes getopt() if *
* you want it. Atof() were substituted for *
* sscanf() in the command line parser (for *
* getting imageheight and imagewidth values,*
* I was unable to get atof to work with my *
* compiler). *
* Craig Moore 4/13/90 *
*********************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <alloc.h>
#define FALSE 0
#define TRUE 1
typedef int bool;
typedef struct codestruct {
struct codestruct *prefix;
unsigned char first,suffix;
} codetype;
FILE *infile;
unsigned int screenwidth; /* The dimensions of the screen */
unsigned int screenheight; /* (not those of the image) */
bool global; /* Is there a global color map? */
int globalbits; /* Number of bits of global colors */
unsigned char globalmap[256][3]; /* RGB values for global color map */
char colortable[256][3]; /* Hex intensity strings for an image */
char huge *raster; /* Decoded image data */
codetype codetable[4096]; /* LZW compression code data */
int datasize,codesize,codemask; /* Decoder working variables */
int clear,eoi; /* Special code values */
#define INCH 72.0
int EPSF = FALSE; /* should we generate EPSF? */
int screen = FALSE; /* use alternate halftone screen? */
int landscape = FALSE; /* display image in landscape mode? */
int copies = 1; /* number of copies to create */
double pagewidth;
double pageheight;
double imagewidth;
double imageheight;
void usage()
{
fprintf(stderr,
"usage: giftops [-els] [-c{copies}] [-w{width}] [-h{height}] [file]\n");
exit(-1);
}
void fatal(s)
char *s;
{
fprintf(stderr,"giftops: %s\n",s);
exit(-1);
}
void checksignature()
{
char buf[6];
fread(buf,1,6,infile);
if (strncmp(buf,"GIF",3)) fatal("file is not a GIF file");
if (strncmp(&buf[3],"87a",3)) fatal("unknown GIF version number");
}
/* Get information which is global to all the images stored in the file */
void readscreen()
{
unsigned char buf[7];
fread(buf,1,7,infile);
screenwidth = buf[0] + (buf[1] << 8);
screenheight = buf[2] + (buf[3] << 8);
global = buf[4] & 0x80;
if (global) {
globalbits = (buf[4] & 0x07) + 1;
fread(globalmap,3,1<<globalbits,infile);
}
}
/* Convert a color map (local or global) to an array of two character
hexadecimal strings, stored in colortable. RGB is converted to
8-bit grayscale using integer arithmetic. */
void initcolors(colortable,colormap,ncolors)
char colortable[256][3];
unsigned char colormap[256][3];
int ncolors;
{
static char hextab[] = {'0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F'};
register unsigned color;
register i;
for (i = 0; i < ncolors; i++) {
color = 77*colormap[i][0] + 150*colormap[i][1] + 29*colormap[i][2];
color >>= 8;
colortable[i][0] = hextab[color >> 4];
colortable[i][1] = hextab[color & 15];
colortable[i][2] = '\0';
}
}
/* Write a postscript header to the standard output.
*
* imagewidth and imageheight always represent the width/height of the
* bounding box in the standard PostScript coordinate system, even when
* the image rotated 90 degrees.
*/
void writeheader(left,top,width,height)
unsigned left,top,width,height;
{
double aspect, xorg, yorg;
/*
* using imagewidth and imageheight as maxima, figure out how
* tall and wide the image will be on the PostScript page.
*/
aspect = ((double) width) / ((double) height);
if (landscape) {
if (aspect >= imageheight / imagewidth)
imagewidth = imageheight / aspect;
else
imageheight = imagewidth * aspect;
} else {
if (aspect >= imagewidth / imageheight)
imageheight = imagewidth / aspect;
else
imagewidth = imageheight * aspect;
}
/*
* For simplicity's sake, EPSF files have origin (0, 0).
*/
if (EPSF) {
xorg = yorg = 0.0;
printf("%%!PS-Adobe-2.0 EPSF-1.2\n"); /* magic number */
} else {
xorg = (pagewidth - imagewidth) / 2.0;
yorg = (pageheight - imageheight) / 2.0;
printf("%%!\n");
}
printf("%%%%BoundingBox: %.3f %.3f %.3f %.3f\n",
xorg, yorg, xorg + imagewidth, yorg + imageheight);
printf("%%%%Creator: GIFtoPS\n");
printf("%%%%EndComments\n");
/*
* setting # of copies doesn't make sense if creating EPSF file
*/
if (!EPSF)
printf("/#copies %d def\n", copies);
printf("gsave\n");
printf("/alternatehalftone %s def\n", screen ? "true" : "false");
printf("alternatehalftone {\n");
printf(" currentscreen\n");
printf(" /proc exch def /angle exch def /frequency exch def\n");
printf(" /angle 90 def /frequency 60 def\n");
printf(" frequency angle /proc load setscreen\n");
printf("} if\n");
printf("/picstr %d string def\n",width);
printf("/screen {\n");
printf(" %d %d 8 [%d 0 0 -%d 0 %d]\n",
width, height, width, height, height);
printf(" {currentfile picstr readhexstring pop} image} def\n");
printf("%.3f %.3f translate\n", xorg, yorg);
if (landscape) {
printf("%.3f 0 translate 90 rotate %.3f %.3f scale\n",
imagewidth, imageheight, imagewidth);
} else {
printf("%.3f %.3f scale\n", imagewidth, imageheight);
}
printf("screen\n");
}
/* Output the bytes associated with a code to the raster array */
void outcode(p,fill)
register codetype *p;
register unsigned char (huge **fill);
{
if (p->prefix) outcode(p->prefix,fill);
*(*fill)++ = p->suffix;
}
/* Process a compression code. "clear" resets the code table. Otherwise
make a new code table entry, and output the bytes associated with the
code. */
void process(code,fill)
register code;
unsigned char (huge **fill);
{
static avail,oldcode;
register codetype *p;
if (code == clear) {
codesize = datasize + 1;
codemask = (1 << codesize) - 1;
avail = clear + 2;
oldcode = -1;
} else if (code < avail) {
outcode(&codetable[code],fill);
if (oldcode != -1) {
p = &codetable[avail++];
p->prefix = &codetable[oldcode];
p->first = p->prefix->first;
p->suffix = codetable[code].first;
if ((avail & codemask) == 0 && avail < 4096) {
codesize++;
codemask += avail;
}
}
oldcode = code;
} else if (code == avail && oldcode != -1) {
p = &codetable[avail++];
p->prefix = &codetable[oldcode];
p->first = p->prefix->first;
p->suffix = p->first;
outcode(p,fill);
if ((avail & codemask) == 0 && avail < 4096) {
codesize++;
codemask += avail;
}
oldcode = code;
} else {
fatal("illegal code in raster data");
}
}
/* Decode a raster image */
void readraster(width,height)
unsigned width,height;
{
unsigned char huge *fill = raster;
unsigned char buf[255];
register bits=0;
register unsigned count;
register unsigned long datum=0L;
register unsigned char *ch;
register int code;
datasize = getc(infile);
clear = 1 << datasize;
eoi = clear+1;
codesize = datasize + 1;
codemask = (1 << codesize) - 1;
for (code = 0; code < clear; code++) {
codetable[code].prefix = (codetype*)0;
codetable[code].first = code;
codetable[code].suffix = code;
}
for (count = getc(infile); count > 0; count = getc(infile)) {
fread(buf,1,count,infile);
for (ch=buf; count-- > 0; ch++) {
datum += (long)*ch << bits;
bits += 8;
while (bits >= codesize) {
code = datum & codemask;
datum >>= codesize;
bits -= codesize;
if (code == eoi) goto exitloop; /* This kludge put in
because some GIF files
aren't standard */
process(code,&fill);
}
}
}
exitloop:
if (fill != raster + (long)width*height) fatal("raster has the wrong size");
}
/* Read a row out of the raster image and write it to the output file */
void rasterize(row,width)
int row,width;
{
unsigned char (huge *scanline);
register i;
scanline = raster + (long)row*width;
for (i = 0; i < width; i++) {
if (i % 40 == 0) printf("\n"); /* break line every 80 chars */
fputs(colortable[*scanline++],stdout);
}
printf("\n");
}
/* write image trailer to standard output */
void writetrailer()
{
printf("\n\ngrestore\n");
if (!EPSF)
printf("showpage\n");
}
/* Read image information (position, size, local color map, etc.) and convert
to postscript. */
void readimage()
{
unsigned char buf[9];
unsigned left,top,width,height;
unsigned long lwidth, lheight;
bool local,interleaved;
char localmap[256][3];
int localbits;
int *interleavetable;
register row;
register i;
fread(buf,1,9,infile);
left = buf[0] + (buf[1] << 8);
top = buf[2] + (buf[3] << 8);
lwidth = width = buf[4] + (buf[5] << 8);
lheight = height = buf[6] + (buf[7] << 8);
local = buf[8] & 0x80;
interleaved = buf[8] & 0x40;
if (local) {
localbits = (buf[8] & 0x7) + 1;
fread(localmap,3,1<<localbits,infile);
initcolors(colortable,localmap,1<<localbits);
} else if (global) {
initcolors(colortable,globalmap,1<<globalbits);
} else {
fatal("no colormap present for image");
}
writeheader(left,top,width,height);
raster = (char huge *)farmalloc(lwidth*lheight);
if (!raster) fatal("not enough memory for image");
readraster(width,height);
if (interleaved) {
interleavetable = (int*)malloc(lheight*sizeof(int));
if (!interleavetable) fatal("not enough memory for interleave table");
row = 0;
for (i = top; i < top+height; i += 8) interleavetable[i] = row++;
for (i = top+4; i < top+height; i += 8) interleavetable[i] = row++;
for (i = top+2; i < top+height; i += 4) interleavetable[i] = row++;
for (i = top+1; i < top+height; i += 2) interleavetable[i] = row++;
for (row = top; row < top+height; row++) rasterize(interleavetable[row],width);
free(interleavetable);
} else {
for (row = top; row < top+height; row++) rasterize(row,width);
}
farfree(raster);
writetrailer();
}
/* Read a GIF extension block (and do nothing with it). */
void readextension()
{
unsigned char code,count;
char buf[255];
code = getc(infile);
while (count = getc(infile)) fread(buf,1,count,infile);
}
extern char *optarg;
extern int optind;
main(argc,argv)
int argc;
char *argv[];
{
int quit = FALSE;
int opt, posn = 0;
char ch, gifname[40];
char optarg[10];
pagewidth = 8.5 * INCH; /* width, height of PostScript page */
pageheight = 11.0 * INCH;
imagewidth = 7.5 * INCH; /* default max image height */
imageheight = 9.0 * INCH;
while((++posn < argc) && (argv[posn][0] == '-')){
opt = argv[posn][1];
if(strlen(argv[posn]) > 2) strcpy(optarg, argv[posn]+2);
switch (opt) {
case 'c':
if ((copies = atoi(optarg)) <= 0)
fatal("#copies must be > 0");
break;
case 'e':
EPSF = TRUE;
break;
case 'l':
landscape = TRUE;
break;
case 's':
screen = TRUE;
break;
case 'w':
sscanf(optarg,"%lf",&imagewidth);
imagewidth *= INCH;
if (imagewidth <= 0.0)
fatal("negative image width");
break;
case 'h':
sscanf(optarg,"%lf",&imageheight);
imageheight *= INCH;
if (imageheight <= 0.0)
fatal("negative image height");
break;
default:
usage();
break;
}
}
strcpy(gifname, argv[posn]);
infile = fopen(gifname,"rb");
if (infile == NULL) {
perror("giftops");
exit(-1);
}
checksignature();
readscreen();
do {
ch = getc(infile);
switch (ch) {
case '\0': break; /* this kludge for non-standard files */
case ',': readimage();
break;
case ';': quit = TRUE;
break;
case '!': readextension();
break;
default: fatal("illegal GIF block type");
break;
}
} while (!quit);
}