This is the README for tifftoeps.c [Download] [Browse] [Up]
From uucp Thu Feb 22 03:31 PST 1990
>From uunet!watmath!ccng.waterloo.edu!rheiger Thu Feb 22 01:28:57 1990 remote from dbi
Received: from watmath.UUCP by uunet.uu.net (5.61/1.14) with UUCP
id AA03817; Thu, 22 Feb 90 01:38:09 -0500
Received: from ccng.waterloo.edu by watmath.waterloo.edu with SMTP
id <AA22525>; Thu, 22 Feb 90 00:33:34 EST
Received: by ccng.waterloo.edu
for epsilon@wet
id <AA25527>; Thu, 22 Feb 90 00:33:28 EST
Date: Thu, 22 Feb 90 00:33:28 EST
From: "Richard H. E. Eiger" <dbi!uunet!watmath!ccng.waterloo.edu!rheiger>
Message-Id: <9002220533.AA25527@ccng.waterloo.edu>
To: wet!epsilon
Subject: tiff2eps : modified
Return-Receipt-To: dbi!uunet!watmath!ccng.waterloo.edu!rheiger
Status: R
Hi
Many, many thanks for your tiff2eps source it came in very handy for something
I needed to do. Unfortunately I don't have a MAC and the only way I can scan
pictures is with a handy scanner on my PC (I'd rather get a scanner for my
NeXT, but it's still not out).
So I needed to read little endian tiff files and while I was at it, I
decided to include the capability to read 32773 compressed files as well.
The feature of showing some parameters above and below the eps-image is
inteded for archiving and out of curiosity (same goes for the added tags
recognized).
I was really in a hurry to get the thing working, so it's not nice code but it
works on all kind of tiff files from NeXT and PC I've tried so far.
I assume you have extended the program yourself already since you wrote it
in September. Anyway I thought you might be interested. Since I'm not
expereinced with SCCS I didn't change the id string.
You may do whatever you like with this code. I didn't want to post this on the
net since it's grown quite a bit and it's originally yours, so you decide.
What's missing:
- color and/or alpha
- some tags
- graceful handling of errors and defaults
- handling of dithering (but that's discouraged anyway)
Many thanks again.
Richard
Richard H. E. Eiger (Foreign student from Switzerland)
rheiger@ccng.waterloo.edu
--------------------------------------------------------------------------
/*
* tifftoeps - convert AppleScanned .tiff file to EPSF
* Eric P. Scott, San Francisco State University, September 1989
*
* Disclaimer: this is a cheap hack; it does not attempt to
* handle arbitrary .tiff files, nor does it make use of all the
* information available to it. In particular, the XResolution
* and YResolution tags are ignored. Heck, it doesn't even
* accept little-endian TIFF...
*
* Future versions may (will?) support other kinds of scanners.
*
* Extension by Richard H. E. Eiger (RHE^2)
*
* 19. Feb. 90 Code to support little-endian
* Code to support some more tags (ie. XRes & YRes influence PostScript !!
* Code to support 32773 Compression Scheme
* Image Info written above and below eps image (if selected at
* compile-time
* ->#undef NO_INFO)
*
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define LITTLE_END 1
#define BIG_END -1
/* PS uses inch/72 units ( = mm/2.835) */
#define PS_metric 72
#ifdef NO_INFO
#define FONTSIZE 0
#else
#define FONTSIZE 3
#endif
int endian = 0;
static char sccsid[]="@(#)tifftoeps 1.0 (SFSU) 9/15/89";
int iwidth=0, ilen=0, invert=255, compr = 1;
long stripoff=0L, strip_b_count=0L,strips_p_image=0L;
short str_off_typ,str_b_typ;
int vsiz[6] = {{255},{sizeof(unsigned char)},{sizeof(unsigned char)},
{sizeof(unsigned short)},{sizeof(long)},{2*sizeof(long)}};
struct ifdent {
unsigned short ifd_tag;
unsigned short ifd_type;
long ifd_len;
union {
unsigned long ifd_long;
unsigned short ifd_short[2];
unsigned char ifd_byte[4];
} ifd_off;
};
void quit(int rc, char *outf)
{
extern int unlink(char *);
if(strcmp(outf,"-"))
unlink(outf);
exit(rc);
}
#ifndef NO_INFO
unsigned char *unparen(unsigned char *s)
{
int parcount;
unsigned char *t,*tt;
if(s == (unsigned char *)0)
return ("");
t = (char *)s;
parcount = 0;
while(*s++)
if((*s == '(') || (*s == ')'))
parcount++;
if(parcount != 0){
s = (unsigned char *)t;
tt = t = (unsigned char *)malloc(strlen(s)+1 + parcount);
assert(t != (char *)0);
while(*s){
if((*s == '(') || (*s == ')'))
*t++ = '\\';
*t++ = *s++;
}
*t = '\0';
t = tt;
free(s);
}
return (t);
}
#endif /* NO_INFO */
int readid(FILE *f)
{
long id;
if(fread(&id, sizeof(id), 1, f) != 1) {
perror("fread in readid");
exit(1);
}
return (id==0x4d4d002a ? BIG_END : (id == 0x49492a00 ? LITTLE_END : 0));
}
void longfread(long *l, size_t n, FILE *f)
{
unsigned char *from, *to;
unsigned char buf;
for(;n;n--){
from = (unsigned char *)l;
if(fread(l,sizeof(long),1,f) != 1) {
perror("fread in longfread");
exit(1);
}
if(endian == LITTLE_END){
to = from + sizeof(long) - 1;
while(from < to){
buf = *from;
*from++ = *to;
*to-- = buf;
}
}
l++;
}
}
void shortfread(unsigned short *l, size_t n, FILE *f)
{
unsigned char *from, *to;
unsigned char buf;
for(;n;n--){
from = (unsigned char *)l;
if(fread(l,sizeof(short),1,f) != 1) {
perror("fread in shortfread");
exit(1);
}
if(endian == LITTLE_END){
to = from + sizeof(short) - 1;
while(from < to){
buf = *from;
*from++ = *to;
*to-- = buf;
}
}
l++;
}
}
int get_tiff_img_byte(FILE *f,char *ofname)
{
static long bytes_left=0,stripstart,i,position=0;
int c,j;
static int curstrip=0;
static unsigned char *unpacked=(unsigned char *)0;
unsigned short shtemp;
if(bytes_left==0){
if(strips_p_image<=0){
return(EOF);
}
if(strips_p_image>1){
if (fseek(stdin, strip_b_count + curstrip * (str_b_typ==3 ? sizeof(short) :
sizeof(long)), 0)<0L) {
perror("fseek");
quit(1,ofname);
}
if(str_b_typ==3){
shortfread(&shtemp,1,f);
bytes_left = (long)shtemp;
}
else{
longfread(&bytes_left,1,f);
}
}
else{
bytes_left = strip_b_count;
}
if(strips_p_image>1){
if (fseek(stdin, stripoff + curstrip * (str_off_typ==3 ? sizeof(short) :
sizeof(long)), 0)<0L) {
perror("fseek");
quit(1,ofname);
}
if(str_off_typ==3){
shortfread(&shtemp,1,f);
stripstart = (long)shtemp;
}
else{
longfread(&stripstart,1,f);
}
}
else{
stripstart = stripoff;
}
if (fseek(stdin, stripstart, 0)<0L) {
perror("fseek");
quit(1,ofname);
}
strips_p_image--;
curstrip++;
}
switch(compr){
case 1:
c = fgetc(f);
break;
case 32773:
if(position==0){
if(unpacked != (unsigned char *)0){
free(unpacked);
}
unpacked = (unsigned char *)malloc(bytes_left);
assert(unpacked != (unsigned char *)0);
/* start unpacking */
i = 0;
while(i<bytes_left){
c = fgetc(f);
if(c == EOF){
fprintf(stderr,"Invalid TIFF-File. Missing data.\n");
quit(4,ofname);
}
if((c>=0) && (c<=127)){
for(j=0;j<=c;j++)
unpacked[i++] = fgetc(f);
}
else{
if(c!=128){
j = 1-(int)(signed char)c;
c = fgetc(f);
while(j--)
unpacked[i++] = c;
}
}
}
}
c = unpacked[position++];
break;
default:
fprintf(stderr,"This error can never hapen!!\n");
quit(5,ofname);
break;
}
bytes_left--;
return(c);
}
int ifditemfread(struct ifdent *l, size_t n, FILE *f)
{
long buf;
for(;n;n--){
shortfread(&(l->ifd_tag),1,f);
shortfread(&(l->ifd_type),1,f);
longfread(&(l->ifd_len),1,f);
if(l->ifd_len*vsiz[l->ifd_type]<sizeof(long)){
switch(l->ifd_type){
case 1:
case 2:
if(fread(&(l->ifd_off.ifd_byte[0]), sizeof(unsigned char),
l->ifd_len,f) !=1 ){
perror("fread in ifditemread");
return(1);
}
if(fread((char *)&buf,sizeof(unsigned char),
4-l->ifd_len,f)!=4-l->ifd_len){
perror("fread in ifditemread");
return(1);
}
break;
case 3:
shortfread(&(l->ifd_off.ifd_short[0]),2-l->ifd_len,f);
if(l->ifd_len < 2)
shortfread((unsigned short *)&buf,1,f);
break;
default:
fprintf(stderr,"ifdfread: unsupported type %d tag %d len %d.\n",
l->ifd_type,l->ifd_tag,l->ifd_len);
return(2);
}
}
else {
longfread((long *)&(l->ifd_off.ifd_long),1,f);
}
l++;
}
return(0);
}
int main(int argc, char *argv[])
{
register int i;
register long value;
long sig, ifdoff,rows_p_strip=0L;
unsigned short ifditems,bits;
unsigned short values[2],res_unit,cel_len,cel_wid,thresh;
unsigned char valuec[4];
struct ifdent *ifdp;
char *resolname[4]={"NA","Undef.","\"","cm"};
char *thrname[4]={"NA","line art","dithered","error diffused"};
long xres[2],yres[2],white[2],primchrom[2],xscale,yscale;
unsigned char *artist,*datetime,*hostcomputer,
*imagedesc,*make,*model,*software;
artist = datetime = hostcomputer = (unsigned char *)0;
imagedesc = make = model = software = (unsigned char *)0;
res_unit = 0;
thresh = 0;
cel_len = cel_wid = 0;
xres[0] = xres[1] = yres[0] = yres[1] = 0L;
if (argc!=3) {
fprintf(stderr, "Usage: %s tiff-file eps-file\n", *argv);
exit(1);
}
if (strcmp(argv[1], "-")&&!freopen(argv[1], "r", stdin)) {
perror(argv[0]);
exit(1);
}
if (strcmp(argv[2], "-")&&!freopen(argv[2], "w", stdout)) {
perror(argv[2]);
exit(1);
}
if (!(endian = readid(stdin))) {
fprintf(stderr, "%s: that's not a TIFF file!\n", argv[0]);
quit(1,argv[2]);
}
longfread(&ifdoff, 1, stdin);
if (fseek(stdin, ifdoff, 0)<0L) {
perror("fseek");
quit(1,argv[2]);
}
shortfread(&ifditems, 1, stdin);
if (!(ifdp=(struct ifdent *)malloc(ifditems*sizeof (struct ifdent)))) {
perror("malloc");
quit(1,argv[2]);
}
if(ifditemfread(ifdp, ifditems, stdin))
quit(3,argv[2]);
for (i=0;i<ifditems;i++) {
switch (ifdp->ifd_type) {
case 1:
case 2:
if(ifdp->ifd_len > 4){
if (fseek(stdin, ifdp->ifd_off.ifd_long, 0L)<0L) {
perror("fseek");
quit(1,argv[2]);
}
}
else {
valuec[0] = ifdp->ifd_off.ifd_byte[0];
valuec[1] = ifdp->ifd_off.ifd_byte[1];
valuec[2] = ifdp->ifd_off.ifd_byte[2];
valuec[3] = ifdp->ifd_off.ifd_byte[3];
}
break;
case 3:
if(ifdp->ifd_len > 2){
if (fseek(stdin, ifdp->ifd_off.ifd_long, 0L)<0L) {
perror("fseek");
quit(1,argv[2]);
}
}
else {
values[0]=ifdp->ifd_off.ifd_short[0];
values[1]=ifdp->ifd_off.ifd_short[1];
}
break;
case 4:
if(ifdp->ifd_len > 1){
if (fseek(stdin, ifdp->ifd_off.ifd_long, 0L)<0L) {
perror("fseek");
quit(1,argv[2]);
}
}
else
value=ifdp->ifd_off.ifd_long;
break;
case 5:
if (fseek(stdin, ifdp->ifd_off.ifd_long, 0L)<0L) {
perror("fseek");
quit(1,argv[2]);
}
break;
default: /* ifdp->ifd_off.ifd_long is offset */
value=0L; /* do The Wrong Thing(tm) */
break;
}
/********** Analyze Tags *************/
switch (ifdp->ifd_tag) {
case 255: /* SubfileType - not recommended (ignored) */
break;
case 256: /* ImageWidth */
iwidth=values[0];
break;
case 257: /* ImageLength */
ilen=values[0];
break;
case 258: /* BitsPerSample */
bits=values[0];
break;
case 259: /* Compression */
compr = values[0];
if ((values[0]!=1) && (values[0]!=32773)) {
fprintf(stderr, "%s: Compression=%ld\n",
argv[1], values[0]);
quit(1,argv[2]);
}
break;
case 262: /* PhotometricInterpretation */
switch (values[0]) {
case 0:
invert=255;
break;
case 1:
invert=0;
break;
default:
fprintf(stderr,
"%s: PhotometricInterpretation=%ld\n",
argv[0], values[0]);
if (values[0]==5)
fputs("\tI don't grok alpha\n",stderr);
quit(1,argv[2]);
break;
}
break;
case 263: /* Thresholding - not recommended */
thresh = values[0];
break;
case 264: /* CellWidth - not recommended */
cel_wid = values[0];
break;
case 265: /* CellLength - not recommended */
cel_len = values[0];
break;
case 270: /* Image description */
imagedesc = malloc(ifdp->ifd_len+1);
assert(imagedesc != (unsigned char *)0);
if(ifdp->ifd_len>4){
if(fread((char *)imagedesc,sizeof(unsigned char),
ifdp->ifd_len,stdin) != ifdp->ifd_len){
perror("Reading image description");
free(imagedesc);
imagedesc = (unsigned char *)0;
}
}
else
strcpy(imagedesc,ifdp->ifd_off.ifd_byte);
if(imagedesc != (unsigned char *)0)
imagedesc[ifdp->ifd_len] = '\0';
break;
case 271: /* Make */
make = malloc(ifdp->ifd_len+1);
assert(make != (unsigned char *)0);
if(ifdp->ifd_len>4){
if(fread((char *)make,sizeof(unsigned char),
ifdp->ifd_len,stdin) != ifdp->ifd_len){
perror("Reading Make");
free(make);
make = (unsigned char *)0;
}
}
else
strcpy(make,ifdp->ifd_off.ifd_byte);
if(make != (unsigned char *)0)
make[ifdp->ifd_len] = '\0';
break;
case 272: /* Model */
model = malloc(ifdp->ifd_len+1);
assert(model != (unsigned char *)0);
if(ifdp->ifd_len>4){
if(fread((char *)model,sizeof(unsigned char),
ifdp->ifd_len,stdin) != ifdp->ifd_len){
perror("Reading Model");
free(model);
model = (unsigned char *)0;
}
}
else
strcpy(model,ifdp->ifd_off.ifd_byte);
if(model != (unsigned char *)0)
model[ifdp->ifd_len] = '\0';
break;
case 273:
stripoff=(long)ifdp->ifd_type==3 ? values[0] : value;
break;
case 277: /* SamplesPerPixel */
if (values[0]!=1) {
fprintf(stderr, "%s: SamplesPerPixel=%ld\n",
argv[0], values[0]);
quit(1,argv[2]);
}
break;
case 278: /* RowsPerStrip */
rows_p_strip=(long)ifdp->ifd_type==3 ? values[0] : value;
break;
case 279: /* StripByteCount */
strip_b_count=(long)ifdp->ifd_type==3 ? values[0] : value;
break;
case 282:/* XResolution RATIONAL */
longfread((long *)&xres,2,stdin);
break;
case 283:/* YResolution */
longfread((long *)&yres,2,stdin);
break;
case 284: /* PlanarConfiguration */
break;
case 296:/* Resolution Unit */
res_unit = values[0];
break;
case 305: /* Software */
software = malloc(ifdp->ifd_len+1);
assert(software != (unsigned char *)0);
if(ifdp->ifd_len>4){
if(fread((char *)software,sizeof(unsigned char),
ifdp->ifd_len,stdin) != ifdp->ifd_len){
perror("Reading Software");
free(software);
software = (unsigned char *)0;
}
}
else
strcpy(software,ifdp->ifd_off.ifd_byte);
if(software != (unsigned char *)0)
software[ifdp->ifd_len] = '\0';
break;
case 306: /* DateTime */
datetime = malloc(ifdp->ifd_len+1);
assert(datetime != (unsigned char *)0);
if(ifdp->ifd_len>4){
if(fread((char *)datetime,sizeof(unsigned char),
ifdp->ifd_len,stdin) != ifdp->ifd_len){
perror("Reading DateTime");
free(datetime);
datetime = (unsigned char *)0;
}
}
else
strcpy(datetime,ifdp->ifd_off.ifd_byte);
if(datetime != (unsigned char *)0)
datetime[ifdp->ifd_len] = '\0';
break;
case 315: /* Artist */
artist = malloc(ifdp->ifd_len+1);
assert(artist != (unsigned char *)0);
if(ifdp->ifd_len>4){
if(fread((char *)artist,sizeof(unsigned char),
ifdp->ifd_len,stdin) != ifdp->ifd_len){
perror("Reading Artist");
free(artist);
artist = (unsigned char *)0;
}
}
else
strcpy(artist,ifdp->ifd_off.ifd_byte);
if(artist != (unsigned char *)0)
artist[ifdp->ifd_len] = '\0';
break;
case 316: /* HostComputer */
hostcomputer = malloc(ifdp->ifd_len+1);
assert(hostcomputer != (unsigned char *)0);
if(ifdp->ifd_len>4){
if(fread((char *)hostcomputer,sizeof(unsigned char),
ifdp->ifd_len,stdin) != ifdp->ifd_len){
perror("Reading HostComputer");
free(hostcomputer);
hostcomputer = (unsigned char *)0;
}
}
else
strcpy(hostcomputer,ifdp->ifd_off.ifd_byte);
if(hostcomputer != (unsigned char *)0)
hostcomputer[ifdp->ifd_len] = '\0';
break;
case 318:/* WhitePoint */
longfread((long *)&white,2,stdin);
break;
case 319:/* PrimaryChromaticities */
longfread((long *)&primchrom,2,stdin);
break;
default:
fprintf(stderr,"%s:Unknown tag %d - ignored\n",
argv[0],ifdp->ifd_tag);
break;
}
ifdp++;
}
if (iwidth<=0L) {
fprintf(stderr, "%s: missing ImageWidth\n", argv[0]);
quit(1,argv[2]);
}
if (ilen<=0L) {
fprintf(stderr, "%s: missing ImageLength\n", argv[0]);
quit(1,argv[2]);
}
if (bits<=0L) {
fprintf(stderr, "%s: missing BitsPerSample\n", argv[0]);
quit(1,argv[2]);
}
sig=(((long)iwidth*bits+7L)/8L)*ilen;
if (stripoff<=0L) {
fprintf(stderr, "%s: missing StripOffsets\n", argv[0]);
quit(1,argv[2]);
}
if (rows_p_strip<=0L) {
strips_p_image = 1;
}
else{
strips_p_image = (ilen + rows_p_strip - 1)/rows_p_strip;
}
if(strip_b_count==0){
if(strips_p_image==1){
strip_b_count = sig;
}
else{
fprintf(stderr,"Can't handle multiple strips without bytecount.\n");
quit(1,argv[2]);
}
}
/*****************************************************
*
* If tags XResolution and/or YResolution are present (and != 0) they are used to size
* the image to the original size.
* If you don't want that feature, just set xscal = iwidth and yscale = ilen.
*
******************************************************/
if((xres[1]==0L) || (xres[0]/xres[1] == 0L))
xscale = iwidth;
else
xscale = (PS_metric*iwidth)/(xres[0]/xres[1]);
if((yres[1]==0L) || (yres[0]/yres[1] == 0L))
yscale = ilen;
else
yscale = (PS_metric*ilen)/(yres[0]/yres[1]);
fputs("%!PS-Adobe-2.0 EPSF-1.2\n%%Creator:tifftoeps\n\
%%Origin:0 720\n%%BoundingBox: 0 0 ", stdout);
printf("%ld %ld", xscale, yscale+2*(FONTSIZE+4));
fputs("\n%%DocumentFonts: Helvetica",stdout);
fputs("\n%%EndComments\n/picstr ", stdout);
printf("%ld", ((long)iwidth*bits+7L)/8L);
printf(" string def\ngsave\n0 %d translate\n1 1 scale\n",(FONTSIZE+2));
#ifndef NO_INFO
printf("gsave\n");
#endif
printf("%ld %ld scale\n%d %d %d\n", xscale, yscale, iwidth, ilen, bits);
printf("[%d 0 0 %d neg 0 %d]\n", iwidth, ilen, ilen);
fputs("{currentfile picstr readhexstring pop}\nimage", stdout);
value=0L; while ((i=get_tiff_img_byte(stdin,argv[2]))!=EOF) {
if (value>=sig) break;
if ((value&31)==0) putchar('\n');
printf("%02X", i^invert);
value++;
}
if(value<sig){
fprintf(stderr,"Insufficient data read %ld expected %ld.\n",value,sig);
}
#ifndef NO_INFO
fputs("\n\n\ngrestore\n", stdout);
printf("0 -%d moveto\n/Helvetica %d selectfont\n",FONTSIZE+2,FONTSIZE);
fputs("0 setgray\n",stdout);
printf("(File : %s ",argv[1]);
if(imagedesc != (unsigned char *)0)
printf("I-desc : %s ",unparen(imagedesc));
if(datetime != (unsigned char *)0)
printf("Date : %s ",unparen(datetime));
if(artist != (unsigned char *)0)
printf("Artist : %s ",unparen(artist));
if(cel_wid > 0)
printf("CelWid : %d ",cel_wid);
if(cel_len > 0)
printf("CelLen : %d ",cel_len);
printf("thr : %s Bits : %d",thrname[thresh],bits);
printf(") show\n");
printf("0 %d moveto\n(",yscale+2);
if(hostcomputer != (unsigned char *)0)
printf("Host : %s ",unparen(hostcomputer));
if(model != (unsigned char *)0)
printf("Model : %s ",unparen(model));
if(make != (unsigned char *)0)
printf("Make : %s ",unparen(make));
if(software != (unsigned char *)0)
printf("Software : %s ",unparen(software));
if((xres[1]!=0L) && (yres[0]!=0L)){
printf(" XRes x YRes : %g x %g [%s] Pixels: %d x %d",
(double)xres[0]/(double)xres[1],(double)yres[0]/(double)yres[1],
resolname[res_unit],iwidth,ilen);
}
printf(") show\n");
#endif /* NO_INFO */
exit(0);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.