/* program to read BYU SIR image files and create a gif file Written DGL Aug. 8, 1997 Revised by DGL Nov. 1, 2000 + version 3.0 header Written in ANSI C. link with sir_io.c */ #include #include #include #include #include "sir_ez.h" /* function prototypes */ int writegif(char *name_in, int *len_in, char *pic, int *pw, int *ph, char *rmap, char *gmap, char *bmap, int *pnumcols, int *pcolorstyle); /* main routine */ int main(int argc, char **argv) { FILE *imf; int i, j, k, nsx, nsy; char outfname[80]; char rtab[256], gtab[256], btab[256]; float smin, smax; int bmin, bmax; sir_head head; int ierr; char *data, temp; fprintf(stdout,"BYU SIR to GIF conversion program\n") ; if (argc < 3) { fprintf(stdout,"\nusage: %s sir_in gif_out \n\n",argv[0]); fprintf(stdout," input parameters:\n"); fprintf(stdout," sir_in = input SIR file\n"); fprintf(stdout," gif_out = output gif file\n"); fprintf(stdout," dmin = min saturation value (optional,def=vmin)\n"); fprintf(stdout," dmax = max saturation value (optional,def=vmax)\n"); fprintf(stdout," ctab = color table file (optional,def=greyscale)\n"); return(0); } /* use sir_ez routine to open file and read SIR header */ sir_init_head(&head); ierr = get_sir_head_name(argv[1], &head, &imf); if (ierr < 0) { fprintf(stdout,"*** Error opening/reading SIR header from file '%s'\n",argv[1]); exit(-1); } /* print file header */ fprintf(stdout,"\nSIR file header: '%s'\n",argv[1]); print_sir_head(stdout, &head); smin = head.v_min; smax = head.v_max; if (argc > 3) sscanf(argv[3],"%f",&smin); if (argc > 4) sscanf(argv[4],"%f",&smax); if (smax - smin == 0.0) smax = smin + 1.0; fprintf(stdout,"GIF Min, Max: %f , %f\n\n",smin,smax); /* allocate byte array */ nsx = head.nsx; nsy = head.nsy; data = (char *) malloc(sizeof(char) * nsx * nsy); if (data == NULL) { fprintf(stderr,"*** ERROR: image memory allocation failure...\n"); exit(-1); } /* read image data from file, converting to bytes in the process */ bmin=0; bmax=255; ierr=get_sir_data_byte(imf, data, &head, smin, smax, bmin, bmax); if (ierr < 0) fprintf(stdout,"ERROR reading SIR input file\n"); else fprintf(stdout,"SIR input file successfully read\n"); /* a SIR file has its origin at the lower-left corner however a GIF image has its origin at the upper-left so we need to shuffle the rows of the byte */ for (i = 0; i < nsy/2; i++) for (j = 0; j < nsx; j++) { temp = *(data+i*nsx+j); *(data+i*nsx+j) = *(data+(nsy-i-1)*nsx+j); *(data+(nsy-i-1)*nsx+j) = temp; } /* generate default greyscale color table for gif file*/ j=255; for (i=0; i<256; i++) { if (i > 127) rtab[i]=i-256; else rtab[i]=i; gtab[i]=rtab[i]; btab[i]=rtab[i]; } if (argc > 5) { /* read user input color table file */ fprintf(stdout,"Reading input color table file '%s'\n",argv[5]); imf = fopen(argv[5],"rb"); if (imf == NULL) { fprintf(stdout,"*** ERROR: cannot open color table file: %s\n",argv[5]); fprintf(stdout,"Using greyscale color table\n"); } else { if (fread(rtab, sizeof(char), 256, imf) == 0) fprintf(stdout," *** Error reading color table file\n"); if (fread(gtab, sizeof(char), 256, imf) == 0) fprintf(stdout," *** Error reading color table file\n"); if (fread(btab, sizeof(char), 256, imf) == 0) fprintf(stdout," *** Error reading color table file\n"); fclose(imf); } } else fprintf(stdout,"Using greyscale color table\n"); k=strlen(argv[2]); i=0; fprintf(stdout,"Writing to output file '%s'\n", argv[2]); ierr=writegif(argv[2], &k, data, &nsx, &nsy, rtab, gtab, btab, &j, &i); if (ierr < 0) { fprintf(stderr,"*** ERROR writing output file ***\n"); fflush(stderr); } else fprintf(stdout,"Output file successfully written\n"); return(0); } /* * xvgifwr.c - handles writing of GIF files. based on flgife.c and * flgifc.c from the FBM Library, by Michael Maudlin * * Contains: * WriteGIF(fp, pic, w, h, rmap, gmap, bmap, numcols, colorstyle) * * Note: slightly brain-damaged, in that it'll only write non-interlaced * GIF files (in the interests of speed, or something) * */ /***************************************************************** * Portions of this code Copyright (C) 1989 by Michael Mauldin. * Permission is granted to use this file in whole or in part provided * that you do not sell it for profit and that this copyright notice * and the names of all authors are retained unchanged. * * Authors: Michael Mauldin (mlm@cs.cmu.edu) * David Rowley (mgardi@watdcsu.waterloo.edu) * * Based on: compress.c - File compression ala IEEE Computer, June 1984. * * Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) * Jim McKie (decvax!mcvax!jim) * Steve Davies (decvax!vax135!petsd!peora!srd) * Ken Turkowski (decvax!decwrl!turtlevax!ken) * James A. Woods (decvax!ihnp4!ames!jaw) * Joe Orost (decvax!vax135!petsd!joe) *****************************************************************/ /* * Copyright 1989, 1990 by the University of Pennsylvania * * Permission to use, copy, and distribute for non-commercial purposes, * is hereby granted without fee, providing that the above copyright * notice appear in all copies and that both the copyright notice and this * permission notice appear in supporting documentation. * * The software may be modified for your own purposes, but modified versions * may not be distributed. * * This software is provided "as is" without any express or implied warranty. */ typedef unsigned char byte; /* MONO returns total intensity of r,g,b components */ #define MONO(rd,gn,bl) (((rd)*11 + (gn)*16 + (bl)*5) >> 5) /*.33R+ .5G+ .17B*/ typedef long int count_int; static int Width, Height; static int curx, cury; static long CountDown; static int Interlace; static byte bw[2] = {0, 0xff}; #ifdef __STDC__ static void putword(int, FILE *); static void compress(int, FILE *, byte *, int); static void output(int); static void cl_block(void); static void cl_hash(count_int); static void char_init(void); static void char_out(int); static void flush_char(void); #else static void putword(), compress(), output(), cl_block(), cl_hash(); static void char_init(), char_out(), flush_char(); #endif /*************************************************************/ int writegif(char *name_in, int *len_in, char *pic, int *pw, int *ph, char *rmap, char *gmap, char *bmap, int *pnumcols, int *pcolorstyle) { FILE *fp; int RWidth, RHeight; int LeftOfs, TopOfs; int Resolution, ColorMapSize, InitCodeSize, Background, BitsPerPixel; int i,j,w,h,numcols,colorstyle; char fname[120]; w = *pw; h = *ph; numcols = *pnumcols; colorstyle = *pcolorstyle; for (i=0; i < *len_in; i++) fname[i] = *(name_in+i); fname[*len_in] = 0; fp = fopen(&fname[0],"wb"); /* printf("Writing output file '%s'\n",&fname[0]); */ /* if writing B/W stipple... */ if (colorstyle==2) { rmap = gmap = bmap = (char *) bw; numcols = 2; } Interlace = 0; Background = 0; /* figure out 'BitsPerPixel' */ for (i=1; i<8; i++) if ( (1<= numcols) break; BitsPerPixel = 8; ColorMapSize = 1 << BitsPerPixel; RWidth = Width = w; RHeight = Height = h; LeftOfs = TopOfs = 0; Resolution = BitsPerPixel; CountDown = w * h; /* # of pixels we'll be doing */ if (BitsPerPixel <= 1) InitCodeSize = 2; else InitCodeSize = BitsPerPixel; curx = cury = 0; if (!fp) { fprintf(stderr, "WriteGIF: file not open for writing\n" ); return (1); } /* if (DEBUG) fprintf(stderr,"WrGIF: pic=%lx, w,h=%dx%d, numcols=%d, Bits%d,Cmap=%d\n", pic, w,h,numcols,BitsPerPixel,ColorMapSize); */ fwrite("GIF87a", 1, 6, fp); /* the GIF magic number */ putword(RWidth, fp); /* screen descriptor */ putword(RHeight, fp); i = 0x80; /* Yes, there is a color map */ i |= (8-1)<<4; /* OR in the color resolution (hardwired 8) */ i |= (BitsPerPixel - 1); /* OR in the # of bits per pixel */ fputc(i,fp); fputc(Background, fp); /* background color */ fputc(0, fp); /* future expansion byte */ if (colorstyle == 1) { /* greyscale */ for (i=0; i>8)&0xff, fp); } /***********************************************************************/ static unsigned long cur_accum = 0; static int cur_bits = 0; #define min(a,b) ((a>b) ? b : a) #define BITS 12 #define MSDOS 1 #define HSIZE 5003 /* 80% occupancy */ typedef unsigned char char_type; static int n_bits; /* number of bits/code */ static int maxbits = BITS; /* user settable max # bits/code */ static int maxcode; /* maximum code, given n_bits */ static int maxmaxcode = 1 << BITS; /* NEVER generate this */ #define MAXCODE(n_bits) ( (1 << (n_bits)) - 1) static count_int htab [HSIZE]; static unsigned short codetab [HSIZE]; #define HashTabOf(i) htab[i] #define CodeTabOf(i) codetab[i] static int hsize = HSIZE; /* for dynamic table sizing */ /* * To save much memory, we overlay the table used by compress() with those * used by decompress(). The tab_prefix table is the same size and type * as the codetab. The tab_suffix table needs 2**BITS characters. We * get this from the beginning of htab. The output stack uses the rest * of htab, and contains characters. There is plenty of room for any * possible stack (stack used to be 8000 characters). */ #define tab_prefixof(i) CodeTabOf(i) #define tab_suffixof(i) ((char_type *)(htab))[i] #define de_stack ((char_type *)&tab_suffixof(1< 0 ) goto probe; nomatch: output(ent); out_count++; ent = c; if ( free_ent < maxmaxcode ) { CodeTabOf (i) = free_ent++; /* code -> hashtable */ HashTabOf (i) = fcode; } else cl_block(); } /* Put out the final code */ output(ent); out_count++; output(EOFCode); } /***************************************************************** * TAG( output ) * * Output the given code. * Inputs: * code: A n_bits-bit integer. If == -1, then EOF. This assumes * that n_bits =< (long)wordsize - 1. * Outputs: * Outputs code to the file. * Assumptions: * Chars are 8 bits long. * Algorithm: * Maintain a BITS character long buffer (so that 8 codes will * fit in it exactly). Use the VAX insv instruction to insert each * code in turn. When the buffer fills up empty it and start over. */ static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; static void output(code) int code; { cur_accum &= masks[cur_bits]; if (cur_bits > 0) cur_accum |= ((long)code << cur_bits); else cur_accum = code; cur_bits += n_bits; while( cur_bits >= 8 ) { char_out( (unsigned int) (cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. */ if (free_ent > maxcode || clear_flg) { if( clear_flg ) { maxcode = MAXCODE (n_bits = g_init_bits); clear_flg = 0; } else { n_bits++; if ( n_bits == maxbits ) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits); } } if( code == EOFCode ) { /* At EOF, write the rest of the buffer */ while( cur_bits > 0 ) { char_out( (unsigned int)(cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } flush_char(); fflush( g_outfile ); if( ferror( g_outfile ) ) fprintf(stderr,"unable to write GIF file"); } } /********************************/ static void cl_block () /* table clear for block compress */ { /* Clear out the hash table */ cl_hash ( (count_int) hsize ); free_ent = ClearCode + 2; clear_flg = 1; output(ClearCode); } /********************************/ static void cl_hash(hsize) /* reset code table */ register count_int hsize; { register count_int *htab_p = htab+hsize; register long i; register long m1 = -1; i = hsize - 16; do { /* might use Sys V memset(3) here */ *(htab_p-16) = m1; *(htab_p-15) = m1; *(htab_p-14) = m1; *(htab_p-13) = m1; *(htab_p-12) = m1; *(htab_p-11) = m1; *(htab_p-10) = m1; *(htab_p-9) = m1; *(htab_p-8) = m1; *(htab_p-7) = m1; *(htab_p-6) = m1; *(htab_p-5) = m1; *(htab_p-4) = m1; *(htab_p-3) = m1; *(htab_p-2) = m1; *(htab_p-1) = m1; htab_p -= 16; } while ((i -= 16) >= 0); for ( i += 16; i > 0; i-- ) *--htab_p = m1; } /****************************************************************************** * * GIF Specific routines * ******************************************************************************/ /* * Number of characters so far in this 'packet' */ static int a_count; /* * Set up the 'byte output' routine */ static void char_init() { a_count = 0; } /* * Define the storage for the packet accumulator */ static char accum[ 256 ]; /* * Add a character to the end of the current packet, and if it is 254 * characters, flush the packet to disk. */ static void char_out(c) int c; { accum[ a_count++ ] = c; if( a_count >= 254 ) flush_char(); } /* * Flush the packet to disk, and reset the accumulator */ static void flush_char() { if( a_count > 0 ) { fputc( a_count, g_outfile ); fwrite( accum, 1, a_count, g_outfile ); a_count = 0; } }