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.