home *** CD-ROM | disk | FTP | other *** search
- 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);
- }
-
-