This is getsun.c in view mode; [Download] [Up]
/* * getsun - display an rle image on a sun workstation running the * sun window environment. * * Bug reports, or better yet fixes/enhancements, may be sent to the author. * Author: * Philip J. Klimbal * RIACS * MS 230-5 * NASA Ames Research Center * Moffett Field, CA 94035 * ..!ames!riacs!klimbal * klimbal@riacs.edu * * Copyright (c) 1987 Research Institute for Advanced Computer Science * All rights reserved. No explicit or implicit warrenty provided. * * Based on getX - Put RLE images on X display, * by Spencer W. Thomas, University of Utah. * Copyright (c) 1986, University of Utah * * * Utah Copyright Header (getX): * * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * * cc .... -lrle -lsuntool -lsunwindow -lpixrect -lm */ #include <stdio.h> #include <math.h> #include <sys/file.h> #include <suntool/sunview.h> #include <suntool/canvas.h> #include "rle.h" #ifdef USE_STDLIB_H #include <stdlib.h> #else #ifdef VOID_STAR extern void *malloc(); #else extern char *malloc(); #endif extern void free(); #endif /* USE_STDLIB_H */ void get_pic(), create_window(), init_color(), map_rgb_to_bw(); void map_scanline(), put_scanline(); /* * Basic magic square for dithering */ int magic[4][4] = { 0, 14, 3, 13, 11, 5, 8, 6, 12, 2, 15, 1, 7, 9, 4, 10 }; int dm4[4][4] = { 0, 43, 9, 40, 34, 15, 25, 18, 37, 6, 46, 3, 21, 28, 12, 31 }; int dm16[16][16]; /* * Color map, gamma correction map, and lookup tables */ rle_pixel ** in_cmap; int modN[256], divN[256]; int bwflag = 0; /* if non zero, dither in B&W * Value of 2 means 1-bit system */ /* * Number of color map levels, (square and cube), and number of gradations * per level. */ int levels = 0, levelsq, levelsc; /* * Global variables */ double disp_gam = 2.5; /* default gammas for display and image */ double img_gam = 1.0; int iflag = 0; /* flag to tell if gamma was on command line */ int nscan, nrow; /* size of window */ int nbyte; /* size of bitrow for 1-bit displays */ int dbg = 0; /* set if debug mode */ unsigned char *buffer; /* data storage pointers */ Frame frame; /* sun window display frame */ Canvas canvas; /* display frame canvas */ Pixwin *pw; /* pixwin canvas */ /***************************************************************** * TAG( main ) * * Usage: * getsun [-D] [-{wW}] [-{iI} gamma] [-g gamma] [-l levels] [file] * Inputs: * -D: Debug mode: print input file as read. * -f: Don't fork after putting image on screen. * -w: Black & white: reduce color images to B&W before * display. Advantage is that smoother shading can * be achieved. * -i gamma: Specify gamma of image. (default 1.0) * -I gamma: Specify gamma of display image was computed for. * getsun will also read picture comments from the input file to determine * the image gamma. These are * image_gamma= gamma of image (equivalent to -i) * display_gamma= gamma of display image was computed for. * Command line arguments override values in the file. * -g gamma: Specify gamma of display. (default 2.5) * -l levels: Number of color levels. * file: Input Run Length Encoded file. Uses stdin if not * specified. * Outputs: * Puts image on screen. * Assumptions: * Input file is in RLE format. * Algorithm: * [None] */ void main(argc, argv) int argc; char **argv; { CONST_DECL char *infname = NULL; FILE * infile; int gflag = 0; int forkflg = 0; if ( scanargs( argc, argv, "% Ww%- D%- f%- l%-levels!d Ii%-gamma!F g%-gamma!F file%s", &bwflag, &dbg, &forkflg, &levels, &levels, &iflag, &img_gam, &gflag, &disp_gam, &infname ) == 0 ) exit( 1 ); if ( levels != 0 && (levels > 6 || levels < 2)) { fprintf(stderr,"Level must be in the range [2,6]; %d is invalid!\n", levels); exit( 1 ); } if ( iflag == 1 ) /* -i */ img_gam = 1.0 / img_gam; infile = rle_open_f("getsun", infname, "r"); if ( infile == stdin ) infname = "Standard Input"; if ( !forkflg && fork() != 0 ) exit(0); get_pic( infile, infname); if ( infname != NULL) fclose( infile); if ( !forkflg ) { fclose(stdin); /* Close stdio to release rshd. */ fclose(stdout); fclose(stderr); } window_main_loop(frame); exit(0); } /***************************************************************** * TAG( get_pic ) * * Read in an RLE image, compute color map, and display it. * * Inputs: * infile: File pointer for input. * infname: Name of input file. * */ void get_pic( infile, infname) FILE * infile; char * infname; { register int i, y; int ncolors; unsigned char *scan[3]; /* * Read setup info from file. */ rle_dflt_hdr.rle_file = infile; if (rle_get_setup(&rle_dflt_hdr) < 0) { fprintf(stderr, "getsun: Error reading setup information from %s\n", infname); exit(1); } if ( dbg ) rle_debug( 1 ); /* We're only interested in R, G, & B */ RLE_CLR_BIT(rle_dflt_hdr, RLE_ALPHA); for (i = 3; i < rle_dflt_hdr.ncolors; i++) RLE_CLR_BIT(rle_dflt_hdr, i); ncolors = rle_dflt_hdr.ncolors > 3 ? 3 : rle_dflt_hdr.ncolors; /* * Compute image size and allocate storage. */ nrow = (rle_dflt_hdr.xmax - rle_dflt_hdr.xmin + 1); nscan = (rle_dflt_hdr.ymax - rle_dflt_hdr.ymin + 1); /* * Get a window of the right size. */ create_window(nrow, nscan, infname); if ( bwflag == 2 ) nbyte = ((nrow + 15) / 16) * 2; /* 1 bit display */ else nbyte = ((nrow + 1) / 2) * 2; buffer = (unsigned char *) malloc(nbyte * nscan); /* * Set up for rle_getrow. Pretend image x origin is 0. */ for (i = 0; i < 3; i++) scan[i] = (unsigned char *) malloc(nrow); rle_dflt_hdr.xmax -= rle_dflt_hdr.xmin; rle_dflt_hdr.xmin = 0; /* If no image gamma on command line, check comments in file */ if ( ! iflag ) { char * v; if ( (v = rle_getcom( "image_gamma", &rle_dflt_hdr )) != NULL ) { img_gam = atof( v ); /* Protect against bogus information */ if ( img_gam == 0.0 ) img_gam = 1.0; else img_gam = 1.0 / img_gam; } else if ( (v = rle_getcom( "display_gamma", &rle_dflt_hdr )) != NULL ) { img_gam = atof( v ); /* Protect */ if ( img_gam == 0.0 ) img_gam = 1.0; } } /* * Set up the color map. */ /* Input map, at least 3 channels */ in_cmap = buildmap( &rle_dflt_hdr, 3, img_gam, 1.0 ); init_color(); /* * For each scan line, dither it and display. */ while ((y = rle_getrow(&rle_dflt_hdr, scan)) <= rle_dflt_hdr.ymax) { if ( bwflag && ncolors > 1 ) { map_rgb_to_bw( scan[0], scan[1], scan[ncolors - 1], scan[0], in_cmap, nrow ); /* Note: map_scanline only uses channel 0 for B&W */ } else if ( bwflag ) for ( i = 0; i < nrow; i++ ) scan[0][i] = in_cmap[0][scan[0][i]]; else for (i = 2; i >= ncolors; i--) bcopy(scan[0], scan[i], nrow); map_scanline(scan, nrow, 1, y, &buffer[(rle_dflt_hdr.ymax - y) * nbyte]); put_scanline(&buffer[(rle_dflt_hdr.ymax - y) * nbyte], nrow, 0, rle_dflt_hdr.ymax - y ); } /* * Free temp storage */ for (i = 0; i < 3; i++) free(scan[i]); } /***************************************************************** * TAG( create_window ) * * Create a sun window and place a pixwin canvas in it. * * Inputs: * width: width of window. * height: height of window. * name: name of image file. * */ void create_window( width, height, name) int width, height; char *name; { char buf[BUFSIZ]; sprintf(buf,"\"%s\": %d X %d", name, height, width); frame = window_create(0, FRAME, FRAME_SHOW_LABEL, TRUE, FRAME_LABEL, buf, FRAME_NO_CONFIRM, TRUE, 0); canvas = window_create(frame, CANVAS, WIN_HEIGHT, height, WIN_WIDTH, width, 0); window_fit(frame); if ((pw = canvas_pixwin(canvas)) == NULL) { perror("Cannot create pixwin"); exit( 1 ); } if (pw->pw_pixrect->pr_depth == 1) bwflag=2; } /***************************************************************** * TAG( map_scanline ) * * Map a scanline to 8 bits through the dither matrix. * * Inputs: * rgb: Pointers to buffers containing the red, green, * and blue color rows. * n: Length of row. * s: Skip between pixels in original image. * y: Y position of row (necessary for dither) * line: Pointer to output buffer for dithered color data. */ #define DMAP(v,x,y) (modN[v]>dm16[x][y] ? divN[v] + 1 : divN[v]) void map_scanline( rgb, n, s, y, line ) unsigned char *rgb[3], *line; int n, s, y; { register int i, col, row; if ( !bwflag ) { register unsigned char *r, *g, *b; for ( row = y % 16, col = 0, i = 0, r = rgb[0], g = rgb[1], b = rgb[2]; i < n; i++, r+=s, g+=s, b+=s, col = ((col + 1) & 15) ) line[i] = DMAP(in_cmap[0][*r], col, row) + DMAP(in_cmap[1][*g], col, row) * levels + DMAP(in_cmap[2][*b], col, row) * levelsq; } else if ( bwflag == 1 ) /* gray scale display */ { register unsigned char *r; for ( row = y % 16, col = 0, i = 0, r = rgb[0]; i < n; i++, r+=s, col = ((col + 1) & 15) ) line[i] = DMAP(*r, col, row); } else /* bitmap display */ { register unsigned short *l = (unsigned short *)line; register unsigned char * r; for ( row = y % 16, col = 0, i = 0, r = rgb[0], *l = 0; i < n; r+=s, col = ((col + 1) & 15) ) { *l |= (*r > dm16[col][row] ? 0 : 1) << (15-(i % 16)); if ( (++i % 16) == 0 ) *++l = 0; } } } /***************************************************************** * TAG( put_scanline ) * * Output scanline into pixwin. * * Inputs: * scan: pointer to scanline. * width: width of scanline. * x,y: coordinates of this scanline. * */ void put_scanline( scan, width, x, y ) unsigned char *scan; int width, x, y; { Pixrect *pix; if ((pix = mem_point(width,1,pw->pw_pixrect->pr_depth,scan)) == NULL) { perror("Unable to allocate pixrect"); exit( 1 ); } pw_write(pw, x, y, width, 1, PIX_SRC, pix, 0, 0); free(pix); } /***************************************************************** * TAG( map_rgb_to_bw ) * * Convert RGB to black and white through NTSC transform, but map * RGB through a color map first. * Inputs: * red_row, green_row, blue_row: Given RGB pixel data. * map: Array[3] of pointers to pixel arrays, * representing color map. * rowlen: Number of pixels in the rows. * Outputs: * bw_row: Output B&W data. May coincide with one of the * inputs. * Algorithm: * BW = .35*map[0][R] + .55*map[1][G] + .10*map[2][B] */ void map_rgb_to_bw( red_row, green_row, blue_row, bw_row, map, rowlen ) rle_pixel *red_row; rle_pixel *green_row; rle_pixel *blue_row; rle_pixel *bw_row; rle_pixel **map; int rowlen; { register int x, bw; for (x=0; x<rowlen; x++) { /* 68000 won't store float > 127 into byte? */ /* HP compiler blows it */ bw = .35*map[0][red_row[x]] + .55*map[1][green_row[x]] + .10*map[2][blue_row[x]]; bw_row[x] = bw; } } /***************************************************************** * TAG( init_color ) * * Build color map and load it into the pixwin. * */ void init_color() { register int i; int rgbmap[256][3], bwmap[256]; unsigned char colormap[3][256]; char buf[12]; if ( !bwflag ) { /* * Figure out how many color map entries we can get */ if ( levels == 0 ) levels = 5; /* default starting point */ levelsq = levels * levels; levelsc = levelsq * levels; dithermap( levels, disp_gam, rgbmap, divN, modN, dm16 ); /* * Copy the color map entries into something that sunwindows * can work with. */ for(i = 0; i < levelsc; i++) { colormap[0][i] = (u_char)rgbmap[i][0]&0xff; colormap[1][i] = (u_char)rgbmap[i][1]&0xff; colormap[2][i] = (u_char)rgbmap[i][2]&0xff; } sprintf(buf,"getsun.c%1d",levels); pw_setcmsname(pw, buf); pw_putcolormap(pw, 0, 4<<levels,colormap[0],colormap[1],colormap[2]); return; } /* Get a B&W color map (gray scale) */ if ( bwflag == 1 ) { if ( levels == 0 ) levels = 5; levelsq = levels * levels; levelsc = levelsq * levels; bwdithermap( levels, disp_gam, bwmap, divN, modN, dm16 ); /* * Copy the color map entries into something that sunwindows * can work with. */ for ( i = 0; i < levelsc; i++ ) { colormap[0][i] = (u_char)bwmap[i]&0xff; colormap[1][i] = (u_char)bwmap[i]&0xff; colormap[2][i] = (u_char)bwmap[i]&0xff; } sprintf(buf,"getsun.g%1d",levels); pw_setcmsname(pw, buf); pw_putcolormap(pw, 0,4<<levels, colormap[0],colormap[1],colormap[2]); return; } /* If b&w 1-bit display, just use two colors */ if ( bwflag == 2 ) { /* All we care about, really, is the magic square */ make_square( 255.0, divN, modN, dm16 ); levels = levelsc = 2; return; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.