This is tiffres.c in view mode; [Download] [Up]
/* TIFFRES -- Tiff Resolution utility ** (c) Peter Langston <psl@acm.org> 2/95 ** Version 1.2 6/15/95 ** ** I wrote this simple utility in frustration over the number of programs ** that either produce tiff files with no X and Y resolutions or that ** invert the specified resolutions (e.g. Icon, Pixelist ... oh, hi Keith). ** ** No special libraries are needed for compilation. I use: ** Compile: cc -O -Wall -s -object tiffres.c -o tiffres ** ******************** Legal Gobbledegook ************************************* ** This program is freeware - you are free to use it for your own personal, ** non-commercial enjoyment. For any other use (including transfer to other ** users), you must obtain my explicit permission. This program is entirely ** free of any warranty or guarantee as to its appropriateness for any use. ** Notwithstanding any implications from its status as freeware, this ** program is still mine (mine, all mine!) and I reserve all rights granted ** to me by my copyright on it. ** Peter Langston <psl@acm.org> Seattle, WA 3 June, 1995 ******************** E-O-L-G ************************************************ */ #include <libc.h> #define TIFFMAGIC 42 #define TAG_XRES 282 #define TAG_YRES 283 #define TYPE_BYTE 1 #define TYPE_ASCII 2 #define TYPE_SHORT 3 #define TYPE_LONG 4 #define TYPE_RATIONAL 5 #define SET_VAL 1 #define GET_VAL 2 int BigEnd; /* 0 => little-endian */ int Xmode, Ymode; /* what we're doing... */ int Vflg; /* verbosity */ double Xval, Yval; /* new values */ int tiffres(FILE *ifp, char *name); void getfield(char *name, char *ifde, FILE *ifp); void setfield(double val, char *ifde, FILE *ifp); int char2short(char *cp); int char2long(char *cp); void long2char(int l, char *cp); void syntax(char *prog) { fprintf(stderr, "Usage: %s [-r[=#]] [-v] [-x[=#]] [-y[=#]] tiff-file [...]\n", prog); fprintf(stderr, "-r\tprints the current x & y resolutions.\n"); fprintf(stderr, "-r=400\tsets the x & y resolutions to 400 dpi.\n"); fprintf(stderr, "-v\tincreases verbosity.\n"); fprintf(stderr, "-x\tprints the current x resolution.\n"); fprintf(stderr, "-y\tprints the current y resolution.\n"); fprintf(stderr, "-x=12.3\tsets the x resolution to 12.3 dpi.\n"); fprintf(stderr, "-y=300\tsets the y resolution to 300 dpi.\n"); fprintf(stderr, "The exit status is a count of errors.\n"); exit(2); } void main(int argc, char *argv[]) { int i, f, retval = 0; FILE *ifp; Vflg = Xmode = Ymode = f = 0; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'r': /* set/get X & Y resolutions */ if (argv[i][2] == '=') { Xval = Yval = atof(&argv[i][3]); Xmode |= SET_VAL; Ymode |= SET_VAL; } else { Xmode |= GET_VAL; Ymode |= GET_VAL; } break; case 'v': /* increment verbosity */ Vflg++; break; case 'x': /* set/get X resolution */ if (argv[i][2] == '=') { Xval = atof(&argv[i][3]); Xmode |= SET_VAL; } else Xmode |= GET_VAL; break; case 'y': /* set/get Y resolution */ if (argv[i][2] == '=') { Yval = atof(&argv[i][3]); Ymode |= SET_VAL; } else Ymode |= GET_VAL; break; default: syntax(argv[0]); } } else { f++; ifp = fopen(argv[i], ((Xmode | Ymode) & SET_VAL)? "r+" : "r"); if (!ifp) { perror(argv[i]); retval++; } else retval += tiffres(ifp, argv[i]); } } if (!f || (!Xmode && !Ymode)) syntax(argv[0]); exit(retval); } int tiffres(FILE *ifp, char *name) { char buf[12]; int i, nument, ent; long offset; fseek(ifp, 0, 0); fread(buf, 1, 8, ifp); if (buf[0] == 'I' && buf[1] == 'I') BigEnd = 0; else if (buf[0] == 'M' && buf[1] == 'M') BigEnd = 1; else { fprintf(stderr, "Error in %s: First 2 bytes bad.\n", name); return(1); } i = char2short(&buf[2]); if (i != TIFFMAGIC) { fprintf(stderr, "Error in %s: Second 2 bytes not magic (%d).\n", name, TIFFMAGIC); return(1); } i = char2long(&buf[4]); if (fseek(ifp, i, 0)) { fprintf(stderr, "Error in %s: Seek to %d (0x%x) failed\n", name, i, i); return(1); } for (;;) { /* go through the Image File Directory */ fread(buf, 1, 2, ifp); nument = char2short(&buf[0]); for (ent = 0; ent < nument; ent++) { fread(buf, 1, 12, ifp); i = char2short(&buf[0]); if (Xmode && i == TAG_XRES) { if (Xmode & GET_VAL) getfield("X resolution", buf, ifp); if (Xmode & SET_VAL) { setfield(Xval, buf, ifp); if (Vflg) getfield("Now X resolution", buf, ifp); } } if (Ymode && i == TAG_YRES) { if (Ymode & GET_VAL) getfield("Y resolution", buf, ifp); if (Ymode & SET_VAL) { setfield(Yval, buf, ifp); if (Vflg) getfield("Now Y resolution", buf, ifp); } } } fread(buf, 1, 4, ifp); offset = char2long(&buf[0]); if (!offset) break; fseek(ifp, offset, 0); } return(0); } void getfield(char *name, char *ifde, FILE *ifp) { char buf[1024]; int here = ftell(ifp); int type = char2short(&ifde[2]); int count = char2long(&ifde[4]); int offset = char2long(&ifde[8]); if (Vflg) printf("%s [type=%d count=%d offset=%d]", name, type, count, offset); if (type == TYPE_BYTE) { int n, i; if (count <= 4) fseek(ifp, here - 4, 0); else fseek(ifp, offset, 0); for (; count > 0; ) { n = MIN(count, sizeof buf); count -= n; fread(buf, 1, n, ifp); for (i = 0; i < n; i++) { if (Vflg) printf(" %d (0x%x)", buf[i] & 0xFF, buf[i] & 0xFF); else printf("%d", buf[i] & 0xFF); } } printf("\n"); } else if (type == TYPE_ASCII) { printf("I don't know how to do the ASCII type yet.\n"); } else if (type == TYPE_SHORT) { printf("I don't know how to do the SHORT type yet.\n"); } else if (type == TYPE_LONG) { printf("I don't know how to do the LONG type yet.\n"); } else if (type == TYPE_RATIONAL) { int num, den; for (fseek(ifp, offset, 0); --count >= 0; ) { fread(buf, 1, 8, ifp); num = char2long(&buf[0]); den = char2long(&buf[4]); if (Vflg) printf(" %d/%d=%g", num, den, (float)num / (float)den); else printf("%g", (float)num / (float)den); } printf("\n"); } else printf("I don't know how to do type %d.\n", type); fseek(ifp, here, 0); } void setfield(double val, char *ifde, FILE *ifp) { char buf[1024]; int here = ftell(ifp); int type = char2short(&ifde[2]); int count = char2long(&ifde[4]); int offset = char2long(&ifde[8]); if (type == TYPE_BYTE) { int n, i, v = val; if (count <= 4) fseek(ifp, here - 4, 0); else fseek(ifp, offset, 0); for (i = MIN(count, sizeof buf); --i >= 0; buf[i] = v); for (; count > 0; count -= n) { n = MIN(count, sizeof buf); fwrite(buf, 1, n, ifp); } } else if (type == TYPE_ASCII) { printf("I don't know how to do the ASCII type yet.\n"); } else if (type == TYPE_SHORT) { printf("I don't know how to do the SHORT type yet.\n"); } else if (type == TYPE_LONG) { printf("I don't know how to do the LONG type yet.\n"); } else if (type == TYPE_RATIONAL) { int num, den = 10000; num = den * val; long2char(num, buf); long2char(den, &buf[4]); for (fseek(ifp, offset, 0); --count >= 0; ) fwrite(buf, 1, 8, ifp); } else printf("I don't know how to do type %d.\n", type); fseek(ifp, here, 0); } int char2short(char *cp) { if (BigEnd) return(((cp[0] & 0xFF) << 8) + (cp[1] & 0xFF)); return(((cp[1] & 0xFF) << 8) + (cp[0] & 0xFF)); } int char2long(char *cp) { if (BigEnd) return(((cp[0] & 0xFF) << 24) + ((cp[1] & 0xFF) << 16) + ((cp[2] & 0xFF) << 8) + (cp[3] & 0xFF)); return(((cp[3] & 0xFF) << 24) + ((cp[2] & 0xFF) << 16) + ((cp[1] & 0xFF) << 8) + (cp[0] & 0xFF)); } void long2char(int l, char *cp) { int i; if (BigEnd) for (i = 4; --i >= 0; ) cp[i] = (l >> (24 - 8 * i)) & 0xFF; else for (i = 4; --i >= 0; ) cp[i] = (l >> (8 * i)) & 0xFF; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.