/* gif2gpr.c - Displays a GIF image on the apollo screen using GPF graphics. * Works on color & monochrome displays, will dither images as needed. * * The majority of this code was lifted right out * of Scott Hemphill's gif to postscript converter. * The display portion of the code was written by * Ben Samit and Ken Hampel. Since Scott Hemphill was * kind enough to put his code in the public domain, * I feel obliged to do the same. * * This program is hereby placed in the public domain. * There are no restrictions on the use of all or any * part of this program. * * Ben Samit March 1989 * samit@demon.siemens.com * * Resizing feature added by Roque D. Oliveira, April 1989. * Save-to-a-bitmap feature added by Roque D. Oliveira, April 1989. * oliveria@caen.engin.umich.edu * I would appreciate hearing of any improvements (or bug fixes) you * make to this program. * * Code optimized for speed by Brett W. Davis, Feb 1990. * Full screen view option added by Brett W. Davis, Feb 1990. * bwdavis@icaen.uiowa.edu * Set_gray_map() and dither patterns from Roger Black, feb 1990. * jrblack@adus.ecn.uiowa.edu * Dithering on B&W screens by Brett W. Davis, Feb 1990. * Memory use decreased from 2.5megs to 300K by Brett W. Davis, Feb 1990. * Outerleave blur to screen feature added by Brett W. Davis, Feb 1990. * bwdavis@icaen.uiowa.edu * Cleanup handler pascal source from David B. Funk, feb 1990. * dbfunk@icaen.uiowa.edu * 4bit color supported via grayscale feature added by Brett W. Davis, Feb 1990. * I would appreciate hearing of any suggestions for added features * (and bug reports) regarding this program. Brett Davis. */ #include #include #include #include #include #include #include #include char *memcpy(); char *malloc(); int strncmp(); #define min(x,y) ((x) < (y) ? (x) : (y)) #define max(x,y) ((x) > (y) ? (x) : (y)) #define FALSE 0 #define TRUE 1 char *progname; /* the name of this program */ status_$t status; gpr_$color_vector_t color_map; gpr_$window_t display; gpr_$rgb_plane_t hi_plane; gpr_$disp_char_t display_characteristics; static short int disp_len = sizeof(gpr_$disp_char_t); short int disp_len_returned; gpr_$offset_t init_size , SIZE , eSIZE; gpr_$position_t ORIGIN , eORIGIN; gpr_$bitmap_desc_t display_bitmap_desc; gpr_$display_mode_t mode=gpr_$direct; stream_$id_t graphics_stream , unit; pad_$window_desc_t pad_window ; char wait_string[] = {"Resizing Image. Please wait..."}; short int wait_string_len = sizeof(wait_string); int save_to_bitmap = false; char *bitmap_file_name = NULL; void redraw(); gpr_$rwin_pr_t rwin = redraw; /* entry point for refreshing window */ gpr_$rhdm_pr_t rhdm = NULL; /* entry point for refreshing hidden display memory */ typedef int bool; typedef struct codestruct { struct codestruct *prefix; unsigned char first,suffix; } codetype; FILE *infile; unsigned int screenwidth; /* The dimensions of the screen */ unsigned int screenheight; /* (not those of the image) */ bool global; /* Is there a global color map? */ int globalbits; /* Number of bits of global colors */ unsigned char globalmap[256][3]; /* RGB values for global color map */ unsigned char *raster; /* Decoded image data */ codetype *codetable; /* LZW compression code data */ int datasize,codesize,codemask; /* Decoder working variables */ int clear,eoi; /* Special code values */ unsigned WIDTH, HEIGHT; unsigned eWIDTH, eHEIGHT; gpr_$pixel_value_t *foo; /* Scan line buffer */ int *ix_inc_table; /* Resize x table buffer */ int *interleavetable; /* Scan line interleave table */ int full_screen = false; /* Don't expand to max size by defalt */ gpr_$pixel_value_t gray[256]; /* Four-bit values for b/w dither, also 4bit color */ int monocrome = false; int outerleave = false; pfm_$cleanup_rec cl_rec; status_$t pfm_status; int four_bit_color = false; /* Here is the dithering array. The four octal numbers on each line represent a four-by-four bitmap that is displayed on the Apollo screen for that color code. There are, of course, 16 color codes from 0 to 15. */ static gpr_$pixel_value_t dither[256] = { 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,0,1, 1,1,1,1, 0,1,1,1, 1,0,1,1, 1,1,0,1, 1,1,1,1, 0,1,0,1, 1,1,1,1, 1,1,0,1, 1,1,1,1, 0,1,0,1, 1,0,1,1, 1,1,0,1, 1,0,1,1, 0,1,0,1, 1,0,1,0, 1,1,0,1, 1,0,1,1, 0,1,0,1, 1,0,1,0, 1,1,0,1, 1,0,1,0, 0,1,0,1, 1,0,1,0, 0,1,0,1, 1,0,1,0, 0,1,0,1, 1,0,1,0, 0,1,0,1, 1,0,1,0, 0,1,0,0, 1,0,1,0, 0,0,0,1, 1,0,1,0, 0,1,0,0, 1,0,1,0, 0,0,0,0, 1,0,1,0, 0,1,0,0, 1,0,1,0, 0,0,0,0, 1,0,1,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,1,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }; /***********************************/ void usage() { fprintf(stderr,"usage: %s [ -o bitmap_file_name ] gif_file_name\n",progname); exit(-1); } /***********************************/ void fatal(s) char *s; { fprintf(stderr,"%s: %s\n",progname,s); exit(-1); } /***********************************/ void check(messagex) char *messagex; { if (status.all) { error_$print (status); printf("Error occurred while %s.\n", messagex); } } /***********************************/ void checksignature() { char buf[6]; fread(buf,1,6,infile); if (strncmp(buf,"GIF",3)) fatal("file is not a GIF file"); if (strncmp(&buf[3],"87a",3)) fatal("unknown GIF version number"); } /***********************************/ /* Get information which is global to all the images stored in the file */ void readscreen() { unsigned char buf[7]; fread(buf,1,7,infile); screenwidth = buf[0] + (buf[1] << 8); screenheight = buf[2] + (buf[3] << 8); global = buf[4] & 0x80; if (global) { globalbits = (buf[4] & 0x07) + 1; printf("global bitmap : %d colors\n",(1<prefix) outcode(p->prefix,fill); *(*fill)++ = p->suffix; } /***********************************/ /* Process a compression code. "clear" resets the code table. Otherwise make a new code table entry, and output the bytes associated with the code. */ void process(code,fill) register code; unsigned char **fill; { static avail,oldcode; register codetype *p; if (code == clear) { codesize = datasize + 1; codemask = (1 << codesize) - 1; avail = clear + 2; oldcode = -1; } else if (code < avail) { outcode(&codetable[code],fill); if (oldcode != -1) { p = &codetable[avail++]; p->prefix = &codetable[oldcode]; p->first = p->prefix->first; p->suffix = codetable[code].first; if ((avail & codemask) == 0 && avail < 4096) { codesize++; codemask += avail; } } oldcode = code; } else if (code == avail && oldcode != -1) { p = &codetable[avail++]; p->prefix = &codetable[oldcode]; p->first = p->prefix->first; p->suffix = p->first; outcode(p,fill); if ((avail & codemask) == 0 && avail < 4096) { codesize++; codemask += avail; } oldcode = code; } else { fatal("illegal code in raster data"); } } /***********************************/ /* Decode a raster image */ void readraster(width,height) unsigned width,height; { unsigned char *fill = raster; unsigned char buf[255]; register bits=0; register unsigned count,datum=0; register unsigned char *ch; register int code; datasize = getc(infile); clear = 1 << datasize; eoi = clear+1; codesize = datasize + 1; codemask = (1 << codesize) - 1; codetable = (codetype*)malloc(4096*sizeof(codetype)); if (!codetable) fatal("not enough memory for code table"); for (code = 0; code < clear; code++) { codetable[code].prefix = (codetype*)0; codetable[code].first = code; codetable[code].suffix = code; } for (count = getc(infile); count > 0; count = getc(infile)) { fread(buf,1,count,infile); for (ch=buf; count-- > 0; ch++) { datum += *ch << bits; bits += 8; while (bits >= codesize) { code = datum & codemask; datum >>= codesize; bits -= codesize; if (code == eoi) goto exitloop; /* This kludge put in because some GIF files aren't standard */ process(code,&fill); } } } exitloop: if (fill != raster + width*height) fatal("raster has the wrong size"); free(codetable); } /***********************************/ void readimage() { unsigned char buf[9]; unsigned left,top,width,height; bool local,interleaved; char localmap[256][3]; int localbits; register row; register i; int rows; int table; fread(buf,1,9,infile); left = buf[0] + (buf[1] << 8); top = buf[2] + (buf[3] << 8); width = buf[4] + (buf[5] << 8); height = buf[6] + (buf[7] << 8); WIDTH= width; HEIGHT=height; printf("gif dimensions : %d x %d pixels\n",WIDTH,HEIGHT); local = buf[8] & 0x80; interleaved = buf[8] & 0x40; if (local) { localbits = (buf[8] & 0x7) + 1; fread(localmap,3,1< 0 ) { fprintf(stdout,"This apollo has %d planes (color display). \n",display_characteristics.n_planes); } else { fprintf(stdout,"This apollo has %d plane (black and white display). \n",display_characteristics.n_planes); monocrome = true; } if (globalbits < 5) four_bit_color = false; if ((hi_plane == 3) & (globalbits > 4)) four_bit_color = true; eWIDTH = WIDTH; eHEIGHT = HEIGHT; if ((full_screen) | (display_characteristics.x_visible_size < WIDTH) | (display_characteristics.y_visible_size < HEIGHT) ) { expand_X = display_characteristics.x_visible_size / (float)WIDTH; expand_Y = display_characteristics.y_visible_size / (float)HEIGHT; /* expand gets the smaller value for a even X,Y expansion. */ expand = (expand_X > expand_Y) ? expand_Y : expand_X; eWIDTH = WIDTH * expand; eHEIGHT = HEIGHT * expand; full_screen = true; } if (monocrome & (full_screen != true)) { if (WIDTH < display_characteristics.x_visible_size) { xskip = display_characteristics.x_visible_size/WIDTH; } if (HEIGHT < display_characteristics.y_visible_size) { yskip = display_characteristics.y_visible_size/HEIGHT; } skip = xskip; if (yskip < xskip) skip = yskip; if (skip > 1) { eWIDTH = eWIDTH * skip; eHEIGHT = eHEIGHT * skip; full_screen = true; } } foo = (gpr_$pixel_value_t *) malloc(display_characteristics.x_visible_size * 4 * sizeof(gpr_$pixel_value_t)); if (!foo) fatal("in Initialize: not enough memory for scan line buffer"); ix_inc_table = (int *) malloc(display_characteristics.x_visible_size * sizeof(int)); if (!ix_inc_table) fatal("in Initialize: not enough memory for scan line table"); pad_window.top = 0; pad_window.left = 0; pad_window.width = eWIDTH; pad_window.height = eHEIGHT; pad_$create_window((char *)0,(short)0,pad_$transcript,(short)1,pad_window,&graphics_stream,&status); unit = graphics_stream ; pad_$set_full_window(unit,(short) 1,&pad_window,&status); pad_$set_auto_close(unit, (short) 1, true, &status ); pad_$set_border (unit,(short) 1, false, &status); pad_$set_scale (unit,(short) 1,(short) 1, &status); init_size.x_size = 8192; init_size.y_size = 8192; gpr_$init(mode,unit, init_size, hi_plane, &display_bitmap_desc, &status); check("in Initialize after calling gpr_$init"); } /***********************************/ draw_color() { long int x,y,count; gpr_$window_t destination_window; destination_window.window_base.x_coord = 0; destination_window.window_size.x_size = WIDTH; destination_window.window_size.y_size = 1; gpr_$acquire_display(&status); for(y=0;y> 4; } } /***********************************/ set_color_map() { int i; gpr_$color_vector_t color; gpr_$acquire_display(&status); for(i=0;i<(1< 0 ) { fprintf(stdout,"The bitmap file %s has been created. The source bitmap has %d planes. \n",file_name,(hi_plane + 1)); } else { fprintf(stdout,"The bitmap file %s has been created. The source bitmap has %d plane. \n",file_name,(hi_plane + 1)); } if(curs_active) gpr_$set_cursor_active(true,&status); gpr_$release_display(&status) ; }