/* cs545 F97/98, transform a batch of gray-scale digital image into tiff images *//* Written by Norman Wittels *//* 05Apr97	first version - based on di2tif.c, version 28Mar97 *//* 14Apr97	updated to include 24-bit color */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <math.h>#include <limits.h>#include <time.h>#include <float.h>#define FILE_NAME_LENGTH 51 /* length of a file name */#define WHITE 255#define MIN(a,b) ((a)<(b) ? (a) : (b)) /* return the minimum value */typedef struct digital_image	{	unsigned int cols; /* digital image size */	unsigned int rows;	unsigned int colors; /* 1 for gray scale; 3 for color */	unsigned char *image; /* the image array */	struct digital_image *next; /* for linked list */	} digital_image; /* newly defined type *//* prototypes */digital_image *create_digital_image(int, int, int); /* create a digital image */void destroy_digital_image(digital_image *); /* destroy a digital_image */void erase_digital_image(digital_image *, unsigned char *); /* set all pixels to a color */int main()	{	FILE *f; /* the file */	unsigned char header[6]={0}; /* the header information */	char input_file_name[FILE_NAME_LENGTH - 6]; /* everything but the number extension */	char file_number[10];	int last_file_number=0;	char real_input_file_name[FILE_NAME_LENGTH];	char output_file_name[FILE_NAME_LENGTH];	int cols, rows, colors;	digital_image *the_image;	int n;	long int size, strip;	unsigned char *p2im; /* pointer to the image data */	printf("What is the name of the batch of digital image files?: ");	scanf("%s",input_file_name); /* read file name */	printf("What is the last image file number?: ");	scanf("%d",&last_file_number); /* read number of last file */	if (last_file_number < 0)		{		printf("File numbers must be positive\n");		return 0;		} /* end if(d) */		for (n=0; n<= last_file_number; n++) /* loop through all files */		{		/* assemble input file name and open it */		strncpy(real_input_file_name, input_file_name, FILE_NAME_LENGTH - 6); /* leave rooom for number */		sprintf(file_number, ".%04d", n); /* turn file number into extension */		strncat(real_input_file_name, file_number, 5); /* this is the input file name */		if ((f = fopen(real_input_file_name,"rb"))==NULL) /* open input file */			{			printf("Could not open input file %s\n",real_input_file_name);			return 0;			} /* end if(fopen()) */		if (fread(header,1,6,f) != 6)			{			printf("could not read file header\n");			fclose(f);			return;			}		cols = 256 * header[0] + header[1];		rows = 256 * header[2] + header[3];		colors = 256 * header[4] + header[5];		if ((the_image = create_digital_image(cols,rows,colors)) == NULL)			{			printf("could not allocate the digital image\n");			fclose(f);			return;			} /* end if(the_image) */		size = cols * rows * colors; /* the image size (number of pixels) */		if (fread(the_image->image,1,size,f) != size) /* read the image data */			{			printf("problem reading the digital image %s\n",real_input_file_name);			fclose(f);			return;			} /* end if(fread()) */		fclose(f); /* close the input file */		/* assemble output file name and open it */		strncpy(output_file_name, input_file_name, FILE_NAME_LENGTH - 8); /* leave rooom for number */		strcat(output_file_name,"_t"); /* add tiff identifier */		strncat(output_file_name, file_number, 5); /* add the number extension */		if ((f = fopen(output_file_name,"wb"))==NULL) /* open output file */			{			printf("Could not open output file %s\n",output_file_name);			destroy_digital_image(the_image);			return 0;			} /* end if(fopen()) */		/* write the tiff header */		fputc('M',f); fputc('M',f);  /* byte order */		fputc(0,f); fputc(42,f); /* "version" number */		fputc(0,f); fputc(0,f); fputc(0,f); fputc(0x10,f); /* ifd offset */				/* write the ifd */		fseek(f,0x10,SEEK_SET); /* beginning of ifd */		fputc(0,f); fputc(14,f); /* number of entries */		fputc(0x00,f); fputc(0xfe,f); /* tag 254 - NEW SUBFILE TYPE */		fputc(0x00,f); fputc(0x04,f); /* type LONG */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); /* the usual */		fputc(0x01,f); fputc(0x00,f); /* tag 256 - I_WIDTH */		fputc(0x00,f); fputc(0x04,f); /* type LONG */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		fputc(0x00,f); fputc(0x00,f); fputc(cols / 256 % 256,f); fputc(cols % 256,f); /* the data */		fputc(0x01,f); fputc(0x01,f); /* tag 257 - I_LENGTH */		fputc(0x00,f); fputc(0x04,f); /* type LONG */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		fputc(0x00,f); fputc(0x00,f); fputc(rows / 256 % 256,f); fputc(rows % 256,f); /* the data */				fputc(0x01,f); fputc(0x02,f); /* tag 258 - BITS_PER_SAMPLE */		fputc(0x00,f); fputc(0x03,f); /* type SHORT */		if (colors == 1) /* 8-bit grayscale */			{			fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */			fputc(0x00,f); fputc(0x08,f); fputc(0x00,f); fputc(0x00,f); /* the data - one byte per pixel */			} /* end if(colors == 1) */		if (colors == 3) /* 24-bit color */			{			fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x03,f); /* three of them */			fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); fputc(0x20,f); /* location of the data */			} /* end if(colors == 1) */				fputc(0x01,f); fputc(0x03,f); /* tag 259 - COMPRESSION */		fputc(0x00,f); fputc(0x03,f); /* type SHORT */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		fputc(0x00,f); fputc(0x01,f); fputc(0x00,f); fputc(0x00,f); /* no compression */				fputc(0x01,f); fputc(0x06,f); /* tag 262 - PHOTOMETRIC INTERPRETATION */		fputc(0x00,f); fputc(0x03,f); /* type SHORT */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		if (colors == 1)			{			fputc(0x00,f); fputc(0x01,f); fputc(0x00,f); fputc(0x00,f); /* grayscale level; Black is zero */			} /* end if(colors) */		if (colors == 3)			{			fputc(0x00,f); fputc(0x02,f); fputc(0x00,f); fputc(0x00,f); /* 24-bit rgb color; Black is zero */			} /* end if(colors) */				fputc(0x01,f); fputc(0X11,f); /* tag 273 - STRIP OFFSETS */		fputc(0x00,f); fputc(0x04,f); /* type LONG */		if (colors == 1)			{			fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */			fputc(0x00,f); fputc(0x00,f); fputc(0x03,f); fputc(0x00,f); /* beginning of first (and only) strip */			} /* end if(colors) */		if (colors == 3)			{			fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x03,f); /* 3 of them */			fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); fputc(0x30,f); /* offset of first strip offset */			} /* end if(colors) */		fputc(0x01,f); fputc(0x15,f); /* tag 277 - SAMPLES PER PIXEL */		fputc(0x00,f); fputc(0x03,f); /* type SHORT */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		if (colors == 1) /* 8-bit grayscale */			{			fputc(0x00,f); fputc(0x01,f); fputc(0x00,f); fputc(0x00,f); /* one sample per pixel */			} /* end if(colors) */		if (colors == 3) /* 24-bit rgb color */			{			fputc(0x00,f); fputc(0x03,f); fputc(0x00,f); fputc(0x00,f); /* three samples per pixel */			} /* end if(colors) */				fputc(0x01,f); fputc(0x16,f); /* tag 278 - ROWS PER STRIP */		fputc(0x00,f); fputc(0x04,f); /* type LONG */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		fputc(0x00,f); fputc(0x00,f); fputc(rows /256 % 256,f); fputc(rows % 256,f); /* the count */				fputc(0x01,f); fputc(0x17,f); /* tag 279 - STRIP BYTE COUNTS */		fputc(0x00,f); fputc(0x04,f); /* type LONG */		if (colors == 1)			{			fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */			fputc(size / 256 / 256 / 256 % 256, f);			fputc(size / 256 / 256 % 256, f);			fputc(size / 256 % 256,f);			fputc(size % 256,f); /* the count */			} /* end if(color) */		if (colors == 3)			{			fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x03,f); /* three of them */			fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); fputc(0x60,f); /* location of first item */			} /* end if(color) */				fputc(0x01,f); fputc(0x1A,f); /* tag 282 - X_RESOLUtiON */		fputc(0x00,f); fputc(0x05,f); /* type RATIONAL */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); fputc(0x00,f); /* location of the data */				fputc(0x01,f); fputc(0x1B,f); /* tag 283 - Y_RESOLUTION */		fputc(0x00,f); fputc(0x05,f); /* type RATIONAL */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); fputc(0x10,f); /* location of the data */				fputc(0x01,f); fputc(0x1C,f); /* tag 284 - PLANAR_CONFIGURATION */		fputc(0x00,f); fputc(0x03,f); /* type SHORT */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		fputc(0x00,f); fputc(0x02,f); fputc(0x00,f); fputc(0x00,f); /* planar format */				fputc(0x01,f); fputc(0x28,f); /* tag 296 - RESOLUTION_UNIT */		fputc(0x00,f); fputc(0x03,f); /* type SHORT */		fputc(0x00,f); fputc(0x00,f); fputc(0x00,f); fputc(0x01,f); /* only 1 of them */		fputc(0x00,f); fputc(0x02,f); fputc(0x00,f); fputc(0x00,f); /* default value - inches */				fputc(0,f); fputc(0,f); fputc(0,f); fputc(0,f); /* there is no other ifd */		fseek(f,0x100,SEEK_SET); /* X_RESOLUTION data */			fputc(0,f); fputc(0,f); fputc(0,f); fputc(72,f); /* 72/inch is default */		fputc(0,f); fputc(0,f); fputc(0,f); fputc(1,f);		fseek(f,0x110,SEEK_SET); /* Y_RESOLUTION data */			fputc(0,f); fputc(0,f); fputc(0,f); fputc(72,f); /* 72/inch is default */		fputc(0,f); fputc(0,f); fputc(0,f); fputc(1,f);		fseek(f,0x120,SEEK_SET); /* BITS_PER_SAMPLE data */			fputc(0x00,f); fputc(0x08,f); /* one byte per color */		fputc(0x00,f); fputc(0x08,f);		fputc(0x00,f); fputc(0x08,f);		fseek(f,0x130,SEEK_SET); /* STRIP_OFFSETS data */			strip = 0x300; /* beginning of red strip */		fputc(strip / 256 / 256 / 256 % 256, f);		fputc(strip / 256 / 256 % 256, f);		fputc(strip / 256 % 256,f);		fputc(strip % 256,f);		strip = size / 3 + 0x300; /* beginning of green strip */		fputc(strip / 256 / 256 / 256 % 256, f);		fputc(strip / 256 / 256 % 256, f);		fputc(strip / 256 % 256,f);		fputc(strip % 256,f);		strip = 2 * size / 3 + 0x300; /* beginning of blue strip */		fputc(strip / 256 / 256 / 256 % 256, f);		fputc(strip / 256 / 256 % 256, f);		fputc(strip / 256 % 256,f);		fputc(strip % 256,f);		fseek(f,0x160,SEEK_SET); /* STRIP_BYTE_COUNTS data */			fputc(size / 3 / 256 / 256 / 256 % 256, f); /* red */		fputc(size / 3 / 256 / 256 % 256, f);		fputc(size / 3 / 256 % 256,f);		fputc(size / 3 % 256,f);		fputc(size / 3 / 256 / 256 / 256 % 256, f); /* green */		fputc(size / 3 / 256 / 256 % 256, f);		fputc(size / 3 / 256 % 256,f);		fputc(size / 3 % 256,f);		fputc(size / 3 / 256 / 256 / 256 % 256, f); /* blue */		fputc(size / 3 / 256 / 256 % 256, f);		fputc(size / 3 / 256 % 256,f);		fputc(size / 3 % 256,f);		fseek(f,0x300,SEEK_SET); /* where to begin writing data */			fwrite(the_image->image,1,size,f); /* write the data */		fclose(f);		destroy_digital_image(the_image); /* clean up */		} /* end for() -- loop through all image files */	printf("goodbye\n");	} /* end main() *//* allocate and initialize a digital_image */digital_image *create_digital_image(int cols, int rows, int colors)	{	digital_image *image;	unsigned char *white; /* array to hold the color table for white */	int n_color;	/* create color table and set it to black */	if ((white = malloc(colors)) == NULL) return NULL; /* could not allocate */	for(n_color = 0; n_color < colors; n_color++) *(white + n_color) = WHITE;	if ((image = malloc(sizeof(digital_image))) == NULL) /* could not allocate */		{		free (white);		return NULL;		}	if ((image->image = malloc(cols * rows * colors)) == NULL) /* could not allocate */		{		free (white);		free (image);		return NULL;		}	image->cols = cols;	image->rows = rows;	image->colors = colors;	image->next = NULL;	erase_digital_image(image,white);	free (white);	return image; /* successful return */	} /* end create_digital_image() *//*** destroy a digital_image ***/void destroy_digital_image(digital_image *img)	{	if (img == NULL) return;	if (img->next != NULL) destroy_digital_image(img->next);	if (img->image != NULL) free(img->image);	free (img);	return;	} /* end destroy_digital_image() */ /*** set all pixels to a color ***/void erase_digital_image(digital_image *img, unsigned char *color_ptr)	{	int size = img->cols * img->rows;	int pixel = 0; int color = 0; /* loop counters */	unsigned char *image_ptr = img->image; /* pointer to pixel data */	for (color = 0; color < img->colors; color++) /* loop through color planes */		{		for (pixel=0;pixel<size;pixel++) /* loop through pixels within a color plane */			*(image_ptr++) = *color_ptr; /* write a pixel */		color_ptr++; /* go to next color */		} /* end for(color) */	} /* end erase_digital_image() *//* Copyright 1997, Norman Wittels */