Category : C Source Code
Archive   : TIFSRC.ZIP
Filename : TIFTAGS.C

 
Output of file : TIFTAGS.C contained in archive : TIFSRC.ZIP

/*
* tiff file validator
*/
#include



/*
* Header file for Tag Image File Format (TIFF) routines.
*/

/* TIFF data types */
#define INTELSTR "II"
#define INTEL 0x4949
#define MOTOROLA 0x4d4d
#define BYTE char
#define ASCII char
#define SHORT short
#define LONG long

typedef struct RAT {
long upper;
long lower;
} RATIONAL;

struct tdirent {
short tagno;
short ttype;
long lcount;
long foffset;
};

#define BYTE_SIZE sizeof(BYTE)
#define ASCII_SIZE sizeof(ASCII)
#define SHORT_SIZE sizeof(SHORT)
#define LONG_SIZE sizeof(LONG)
#define RATIONAL_SIZE sizeof(RATIONAL)

#define BYTE_TYPE 1
#define ASCII_TYPE 2
#define SHORT_TYPE 3
#define LONG_TYPE 4
#define RATIONAL_TYPE 5

#define ERROR_VALUE 0
#define DIRECT_VALUE 1
#define INDIRECT_VALUE 2

/* tags */
#define SUBFILE_TYPE_TAG 0x00ff
#define IMAGE_WIDTH_TAG 0x0100
#define IMAGE_LENGTH_TAG 0x0101
#define BITS_PER_SAMPLE_TAG 0x0102
#define COMPRESSION_TAG 0x0103

#define PHOTOMETRIC_INTERP_TAG 0x0106
#define THRESHOLDING_TAG 0x0107
#define CELL_WIDTH_TAG 0x0108
#define CELL_LENGTH_TAG 0x0109
#define FILL_ORDER_TAG 0x010a

#define DOCUMENT_NAME_TAG 0x010d
#define IMAGE_DESCRIPTION_TAG 0x010e
#define MAKE_TAG 0x010f
#define MODEL_TAG 0x0110
#define STRIP_OFFSETS_TAG 0x0111
#define ORIENTATION_TAG 0x0112
#define SAMPLES_PER_PIXEL_TAG 0x0115
#define ROWS_PER_STRIP_TAG 0x0116
#define STRIP_BYTE_COUNTS_TAG 0x0117
#define MIN_SAMPLE_VALUE_TAG 0x0118
#define MAX_SAMPLE_VALUE_TAG 0x0119
#define X_RESOLUTION_TAG 0x011a
#define Y_RESOLUTION_TAG 0x011b
#define PLANAR_CONFIG_TAG 0x011c
#define PAGE_NAME_TAG 0x011d
#define X_POSITION_TAG 0x011e
#define Y_POSITION_TAG 0x011f
#define FREE_OFFSETS_TAG 0x0120
#define FREE_BYTE_COUNTS_TAG 0x0121
#define GRAY_RESP_UNIT_TAG 0x0122
#define GRAY_RESP_CRVE_TAG 0x0123
#define GROUP_3_OPT_TAG 0x0124
#define GROUP_4_OPT_TAG 0x0125
#define RESOLUTION_TAG 0x0128
#define PAGE_NO_TAG 0x0129
#define COLOR_RSP_TAG 0x012C
#define COLOR_RSP_CRV_TAG 0x012D


/*
* Legal compression types. See the description of the "Compression" tag
* in the "Tag Image File Format" abstract, Aldus Corporation, 8/5/86 or
* later.
*/
#define PACK_TIGHTLY 1
#define ONE_D_MOD_HUFFMAN 2
#define TWO_D_CCITT 3

/*
* Answer to the question of the meaning of life and arbitrarily-chosen
* version number.
*/
#define LEGAL_VERSION 42
#define SIZEOF_DIR_ENT 12


char *tag_expl[] = {

"SUBFILE_TYPE_TAG ", "IMAGE_WIDTH_TAG ",
"IMAGE_LENGTH_TAG ", "BITS_PER_SAMPLE_TAG ",
"COMPRESSION_TAG ", "","","PHOTOMETRIC_INTERP_TAG ",
"THRESHOLDING_TAG ", "CELL_WIDTH_TAG ",
"CELL_LENGTH_TAG ", "FILL_ORDER_TAG ","","",
"DOCUMENT_NAME_TAG ", "IMAGE_DESCRIPTION_TAG ",
"MAKE_TAG ", "MODEL_TAG ",
"STRIP_OFFSETS_TAG ", "ORIENTATION_TAG ","","",
"SAMPLES_PER_PIXEL_TAG ", "ROWS_PER_STRIP_TAG ",
"STRIP_BYTE_COUNTS_TAG ", "MIN_SAMPLE_VALUE_TAG ",
"MAX_SAMPLE_VALUE_TAG ", "X_RESOLUTION_TAG ",
"Y_RESOLUTION_TAG ", "PLANAR_CONFIG_TAG ",
"PAGE_NAME_TAG ", "X_POSITION_TAG ",
"Y_POSITION_TAG ", "FREE_OFFSETS_TAG ",
"FREE_BYTE_COUNTS_TAG " , "GREY_RESPONSE_UNIT",
"GREY_RESPONSE_CURVE ", "GROUP_3_OPTIONS ",
"GROUP_4_OPTIONS_TAG ", "","","RESOLUTION_UNIT",
"PAGE_NUMBER_TAG ", "","","COLOR_RESP_UNIT",
"COLOR_RESP_CRVE_TAG "};

#define OPTION '-'
#define OPT_VERBOSE 'v'
#define LOWER 0x20

char creator;
long ifdptr; /* pointer to the first file descriptor */
int vflag; /* is this a verbose validation? */
char ifile[80]; /* input file name */

main(argc,argv)
int argc;
char *argv[];
{
int fd; /* file descriptor */

if(valid_parm(argc,argv)) {
printf("usage: %s [-v] infile.tif\n",argv[0]);
exit(1);
}

if((fd = open_tif_file(ifile)) == -1) {
printf("Cannot Open '%s' for reading\n",ifile);
printf("Job Aborted\n");
exit(2);
}

if(!read_tif_header(fd)) {
exit(3);
}

get_field_data(fd);


}

/* valid_parm - parses the passed parameters. loads ifile, ofile and vflag */
/* if only the input file name is passed, the output file is created by */
/* finding the input filename a putting a .s suffix on the end. */

valid_parm(argc,argv)
int argc;
char *argv[];
{

int i;
#ifdef DEBUG
printf("in valid_parm, argc = %d,\n",argc);
for(i=0;i printf("argv[%d] = '%s'\n",i,argv[i]);
}
#endif

if(argc < 2 || argc >3) {
return(1);
}

for(i=1;i if(argv[i][0] == OPTION) {
switch(argv[i][1]|LOWER) {

case OPT_VERBOSE: /* found a 'v' */
vflag = 1;
break;
default:
/* found an illegal parameter */
return(3);
break;
}
} else {
strcpy(ifile,argv[i]);
}
}

#ifdef DEBUG
printf("leaving valid_parm, vflag = %d, ifile = '%s'\n",vflag,ifile);
#endif
return(0);
}


/* open tiff file - nothing fancy here, just open the tiff file with the
* standard ms-dos file opens
*/

int open_tif_file(infilename)
char *infilename;
{

return(open(infilename,O_RDONLY));
}

/*
* read tif header - read the tiff header and report on its contents
*/

int read_tif_header(filedes)
int filedes;
{
int retval;

struct tif_head {
char creat[2]; /* where was this thing made */
short version; /* what version is this puppy */
long ifd; /* 1st image file directory */
}head_data;

if((retval = read(filedes,(char *)&head_data,sizeof(struct tif_head)))
!= sizeof(struct tif_head)) {
return(0);
}

if(!strncmp(head_data.creat,INTELSTR,2)){
printf("File was created on an Intel Processor\n");
creator = 'I';
} else {
printf("File was created on an Motorola Processor\n");
creator = 'M';
}

if(creator == 'M')
swapit(&head_data.version,SHORT_TYPE);

printf("Tiff spec. used to create format of file = %d\n",
head_data.version);

if(creator=='M'){
swapit(&head_data.ifd,LONG_TYPE);
}
printf("Offset of 1st IFD = %ld\n",head_data.ifd);
ifdptr = head_data.ifd;
return (1);
}

get_field_data(fileds)
int fileds;
{
short count;
long retval;
int bytes_to_read;
char *ifd;
char *sifd;

struct tdirent dirent;

retval = lseek(fileds,ifdptr,0);
if(read(fileds,&count,sizeof(short)) != sizeof(short)) {
printf("Cannot read tiff file, ifd directory entry corrupt\n");
exit(1);
}

if(creator == 'M')
swapit(&count,SHORT_TYPE);

bytes_to_read = count * SIZEOF_DIR_ENT;

ifd = (char *)malloc(bytes_to_read);

if(read(fileds,ifd,bytes_to_read) != bytes_to_read) {
printf("Cannot read tiff file, ifd directory elements corrput\n");
exit(2);
}

printf("number of entries in the first ifd = %d\n",count);

sifd = ifd;

while(count !=0) {
memcpy(&dirent,ifd,(unsigned)SIZEOF_DIR_ENT);
ifd += SIZEOF_DIR_ENT;
breakup(fileds,&dirent);
count--;
}
free(sifd);
}

breakup(fd,ptr)
int fd;
struct tdirent *ptr;
{
long i;
union values {
char byte[512];
char ascii[512];
short word[256];
long longw[128];
RATIONAL ratio[64];
} *buffer;
long bytes_to_read;

if(creator == 'M') {
swapit(&ptr->tagno,SHORT_TYPE);
swapit(&ptr->ttype,SHORT_TYPE);
swapit(&ptr->lcount,LONG_TYPE);
if(ptr->ttype == SHORT_TYPE && ptr->lcount == 1){
swapit(&ptr->foffset,SHORT_TYPE);
} else {
swapit(&ptr->foffset,LONG_TYPE);
}
}

printf("\ntag no. = %d ",ptr->tagno);

if(ptr->tagno -255 >= 0) {
printf("%s\n",tag_expl[ptr->tagno - 255]);
}
else {
printf("Private Tag\n");
}

printf("\tttype = %d",ptr->ttype);
switch(ptr->ttype) {
case BYTE_TYPE:
printf(" type of TAG is BYTE\n");
break;
case ASCII_TYPE:
printf(" type of TAG is ASCII\n");
break;
case SHORT_TYPE:
printf(" type of TAG is SHORT\n");
break;
case LONG_TYPE:
printf(" type of TAG is LONG\n");
break;
case RATIONAL_TYPE:
printf(" type of TAG is RATIONAL\n");
break;
}
printf("\tlcount = %ld\n",ptr->lcount);
printf("\tfoffset = %ld\n",ptr->foffset);

if( ptr->lcount > 1 || ptr->ttype > 4 ) {
printf("values of tag at offset:\n\t");
switch(ptr->ttype) {
case BYTE_TYPE:
case ASCII_TYPE:
bytes_to_read = BYTE_SIZE;
break;
case SHORT_TYPE:
bytes_to_read = SHORT_SIZE;
break;
case LONG_TYPE:
bytes_to_read = LONG_SIZE;
break;
case RATIONAL_TYPE:
bytes_to_read = RATIONAL_SIZE;
break;
}
bytes_to_read *= ptr->lcount;

if(bytes_to_read >4 ) {
lseek(fd,ptr->foffset,0);

buffer = (union values *)malloc(bytes_to_read);
if(read(fd,buffer,bytes_to_read) != bytes_to_read) {
printf("invalid tiff file, cannot read at foffset\n");
close(fd);
free(buffer);
exit(5);
}
}
else
{
memcpy(buffer,&ptr->foffset,bytes_to_read);
}
/* now based on type, break up the read in data area */
for(i=0;ilcount;i++) {
switch(ptr->ttype) {
case BYTE_TYPE:
printf("%x ",buffer->byte[i]);
break;
case ASCII_TYPE:
printf("%c",buffer->byte[i]);
break;
case SHORT_TYPE:
if(creator == 'M'){
swapit(&buffer->word[i],
SHORT_TYPE);
}
printf("%d ",buffer->word[i]);
break;
case LONG_TYPE:
if(creator == 'M') {
swapit(&buffer->longw[i],
LONG_TYPE);
}
printf("%ld ",buffer->longw[i]);
break;
case RATIONAL_TYPE:
if(creator == 'M') {
swapit(&buffer->ratio[i].upper,
LONG_TYPE);
swapit(&buffer->ratio[i].lower,
LONG_TYPE);
}
printf("%ld / %ld ",
buffer->ratio[i].upper,
buffer->ratio[i].lower);
break;
}
}
printf("\n");
free(buffer);
}
}


swapit(ptr,type)
char *ptr;
int type;
{

/* this function will swap the bytes of a long of short */

char temp;

if(type == SHORT_TYPE) {
temp = *ptr;
*ptr = *(ptr+1);
*(ptr+1) = temp;
}
else if(type == LONG_TYPE) {
temp = *(ptr+3);
*(ptr+3) = *ptr;
*ptr = temp;
temp = *(ptr+2);
*(ptr+2) = *(ptr+1);
*(ptr+1) = temp;
}
}