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.