This is get4d.c in view mode; [Download] [Up]
/* * get4d.c - Put RLE images on the Iris/4D display under the window manager. * * Author: Russell D. Fish (Based on getmex.c .) * Computer Science Dept. * University of Utah * Date: Thu May 26 20:49:11 1988 * Copyright (c) 1988, University of Utah * */ #include <stdio.h> #include <math.h> #include "gl.h" #include "device.h" #include "rle.h" #ifdef USE_STDLIB_H #include <stdlib.h> #else #ifdef USE_STRING_H #include <string.h> #else #include <strings.h> #endif extern char *getenv (); #ifndef VOID_STAR extern char *malloc (); #else extern void *malloc(); #endif extern void free(); #endif /* USE_STDLIB_H */ #define MAX(i,j) ( (i) > (j) ? (i) : (j) ) #define MIN(i,j) ( (i) < (j) ? (i) : (j) ) /* Global variables. */ long window_number; /* Window number from MAX. */ int x_size, y_size; /* Size of image. */ int dbg = 0; /* Set if debug mode. */ int forkflg = 0; /* Set if not to run in background. */ int bwflag = 0; /* Set for greyscale output. */ int NoBorder = 0; /* Turn off border */ int gt; /* Whether we're using GT fast rectangle drawing. */ double disp_gamma = 1.0; /* Gamma of Iris display. */ double img_gamma = 0.0; /* Gamma of input image. */ /* Window preferences. */ int posflag = 0, w_xpos, w_ypos, sizeflag = 0, w_xsize, w_ysize; long *rect_image; /* GT Image data buffer pointer. */ char *rgb_image; /* Non-GT Image data buffer pointer. */ rle_pixel **cmap; /***************************************************************** * TAG( main ) * * Usage: * get4d [-G][-S] [-p xpos ypos] [-f] [-D] [-w] [file] * Inputs: * -D: Debug mode: print input file as read. * -f: Don't fork after putting image on screen. * -G: GT mode: single fast rectangle, panning disabled. * (GT mode is the default on GT, GTX, and Personal Iris 4Ds.) * -S: Slow mode: Allows resizing the window, and panning with the * mouse. (Slow mode is the default on non-GT 4Ds.) * -g disp_gamma: Gamma of the output display. * -i image_gamma: Gamma the image was calculated for. * -I image_gamma: Gamma of the image pixels (1.0 / (-i gamma)). * -n: No border will be drawn. * -p xpos ypos: Position of the lower left corner of the window. * -s xsize ysize: Initial size of the window (slow mode only.) * * -w: Black & white: reduce color images to B&W before display. * Advantage is that smoother shading can be achieved. * * file: Input Run Length Encoded file. Uses stdin if not * specified. * Outputs: * Puts image in a window on the screen. * Assumptions: * Input file is in RLE format. */ main(argc, argv) char **argv; { char *infname = NULL; FILE * infile = stdin; char vbuff[50]; char *var; int gtflag = 0, slowflag = 0, gflag = 0, iflag = 0; /* Handle arguments. */ if ( scanargs( argc, argv, "% D%- f%- GS%- g%-disp_gamma!F iI%-image_gamma!F n%- \n\ p%-xpos!dypos!d s%-xsize!dysize!d w%- file%s", &dbg, &forkflg, >flag, &gflag, &disp_gamma, &iflag, &img_gamma, &NoBorder, &posflag, &w_xpos, & w_ypos, &sizeflag, &w_xsize, &w_ysize, &bwflag, &infname ) == 0 ) exit( 1 ); if ( gtflag ) /* Mode args override if specified. */ gt = gtflag - 1; /* -G->2 means yes GT, -S->1 means no GT. */ else { #ifndef _IBMR2 /* See if we`re on a GT. For this purpose, a Personal Iris is a GT. */ gversion( vbuff ); /* String like "GL4DGTX-3.1". */ gt = strncmp( vbuff+4, "GT", 2 ) == 0 || strncmp( vbuff+4, "PI", 2 ) == 0; #else gt = 1; #endif } /* Diddle with gammas. */ if ( iflag == 2 ) /* -i flag. */ if ( img_gamma != 0.0 ) /* Paranoid. */ img_gamma = 1.0 / img_gamma; #ifndef _IBMR2 /* Look at home for .gamma file. */ if ( !gflag ) { char *var = getenv( "HOME" ); char buf[BUFSIZ]; FILE *gamfile; float flt_gam = 0; /* Just in case of 68000 iris botch. */ if ( var != NULL && *var != '\0' ) { sprintf( buf, "%s/.gamma", var ); if ( (gamfile = fopen( buf, "r" )) != NULL ) { fscanf( gamfile, "%f", &flt_gam ); if ( flt_gam != 0 ) disp_gamma = 2.4/flt_gam;/* SGI displays have gamma 2.4. */ fclose( gamfile ); } } } #endif infile = rle_open_f("get4d", infname, "r"); get_pic( infile, infname ); /* Read image and make a window for it. */ update_pic(); /* Keep drawing the window. */ } /* * Read an image from the input file and display it. */ 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, "get4d: Error reading setup information from %s\n", infname ? infname : "stdin"); 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; /* Do nicer b&w rendering if only one color channel in input. */ if ( ncolors == 1 && rle_dflt_hdr.ncmap <= 1 ) bwflag = 1; /* * Compute image size and allocate storage for colormapped image. */ x_size = (rle_dflt_hdr.xmax - rle_dflt_hdr.xmin + 1); y_size = (rle_dflt_hdr.ymax - rle_dflt_hdr.ymin + 1); if ( gt ) rect_image = (long *) malloc(x_size * y_size * sizeof( long )); else rgb_image = (char *) malloc(x_size * y_size * 3 * sizeof( char )); /* * Set up for rle_getrow. Pretend image x origin is 0. */ for (i = 0; i < 3; i++) scan[i] = (unsigned char *) malloc(x_size); rle_dflt_hdr.xmax -= rle_dflt_hdr.xmin; rle_dflt_hdr.xmin = 0; cmap = buildmap( &rle_dflt_hdr, 3, img_gamma, disp_gamma ); /* For each scan line, pack RGBs into the image memory. */ while ((y = rle_getrow(&rle_dflt_hdr, scan)) <= rle_dflt_hdr.ymax) { switch ( ncolors ) { case 1: /* Colormapped image */ for (i = 0; i < x_size; i++) { scan[2][i] = cmap[2][scan[0][i]]; scan[1][i] = cmap[1][scan[0][i]]; scan[0][i] = cmap[0][scan[0][i]]; } break; case 2: /* Weird image. */ for (i = 0; i < x_size; i++) { scan[2][i] = cmap[2][scan[1][i]]; scan[1][i] = cmap[1][scan[1][i]]; scan[0][i] = cmap[0][scan[0][i]]; } break; case 3: /* Normal image. */ for (i = 0; i < x_size; i++) { scan[2][i] = cmap[2][scan[2][i]]; scan[1][i] = cmap[1][scan[1][i]]; scan[0][i] = cmap[0][scan[0][i]]; } break; } if ( bwflag ) { if (ncolors == 1) rgb_to_bw (scan[0], scan[1], scan[2], scan[0], x_size ); else rgb_to_bw( scan[0], scan[1], scan[ncolors - 1], scan[0], x_size ); /* Note: pack_scanline only uses channel 0 for B&W */ } if ( gt ) pack_rect_scanline( scan, x_size, &rect_image[(y - rle_dflt_hdr.ymin) * x_size] ); else pack_rgb_scanline( scan, x_size, &rgb_image[(y - rle_dflt_hdr.ymin) * x_size * 3] ); } /* * Free temp storage */ for (i = 0; i < 3; i++) free(scan[i]); /* Size flag can cut down the window size, except in GT rectangle mode. */ w_xsize = sizeflag && !gt ? MIN( w_xsize, x_size ) : x_size; w_ysize = sizeflag && !gt ? MIN( w_ysize, y_size ) : y_size; /* Window should be completely on the screen in GT rectangle mode. */ if ( posflag && gt ) { w_xpos = MIN( w_xpos, XMAXSCREEN - w_xsize ); w_ypos = MIN( w_ypos, YMAXSCREEN - w_ysize); } w_xpos = MAX( 0, w_xpos ); /* Be positive. */ w_ypos = MAX( 0, w_ypos ); /* Register our preferences for the window size and location. */ if ( posflag ) prefposition( w_xpos, w_xpos + w_xsize - 1, w_ypos, w_ypos + w_ysize - 1 ); else if ( sizeflag || gt ) /* Have to keep the window full size to use the fast pixel commands. */ prefsize( w_xsize, w_ysize ); else maxsize( x_size, y_size ); /* * Get a window of the right size (user positions it with the mouse). */ #ifndef _IBMR2 if ( forkflg ) foreground(); /* Don`t fork. */ #endif if ( NoBorder ) noborder(); window_number = winopen( "get4d" ); if ( infname ) wintitle( infname ); /* Loosen the constraints once the window is created. */ if ( !gt ) maxsize( x_size, y_size ); winconstraints(); RGBmode(); gconfig(); qdevice( ESCKEY ); qdevice( REDRAW ); unqdevice( INPUTCHANGE ); /* We don`t pay attention to these. */ if ( !gt ) /* Disable panning when in gt rectangle mode. */ { qdevice( LEFTMOUSE ); /* Pan the image under mouse control. */ qdevice( LEFTALTKEY ); /* Reset panning. */ qdevice( RIGHTALTKEY ); qdevice( F9KEY ); } /* There was a redraw event sent when the window was created, * but we weren`t listening for them yet. */ qenter( REDRAW, window_number ); } /* * Track events & redraw image when necessary. */ update_pic() { short data; long event; int window_x_size, window_y_size, window_x_origin, window_y_origin; int x_min, x_max, y_min, y_max, x_start, y_start, x_end, y_end, x_len; int x_origin, y_origin, new_x_center, new_y_center; int x_center, y_center, saved_x_center, saved_y_center; register int y; register char *y_ptr; /* Looking at the center, at first. */ x_center = saved_x_center = x_size / 2; y_center = saved_y_center = y_size / 2; /* Redraw the window when necessary. */ while ( TRUE ) { event = qread( &data ); # ifdef DEBUG printf( "event %d, data %d\n", event, data ); #endif switch ( event ) { case ESCKEY: gexit(); exit(0); break; case REDRAW: winset( window_number ); reshapeviewport(); if ( gt ) { /* On a GT, just blast out the whole rectangle. If the * origin is off the screen to the left, it kills the * window server. Could duplicate the slow output logic * below, but avoid the complication for now... */ getorigin( &x_origin, &y_origin ); if ( x_origin < 0 ) { RGBcolor( 128, 128, 128 ); /* Punt. */ clear(); } else lrectwrite( 0, 0, x_size-1, y_size-1, rect_image ); } else { /* Do panning in a resizable window. (Slow mode.) */ RGBcolor( 128, 128, 128 ); clear(); /* Lower left corner of screen, in image coordinates. * (Keep the center of the image in the center of the * window.) */ getsize( &window_x_size, &window_y_size ); x_min = x_center - window_x_size/2; x_max = x_min + (window_x_size-1); y_min = y_center - window_y_size/2; y_max = y_min + (window_y_size-1); /* Coordinate bounds have half a pixel added all around. */ ortho2( x_min - .5, x_max + .5, y_min - .5, y_max + .5 ); /* Draw just the part of the image in the window. */ x_start = MAX( x_min, 0 ); y_start = MAX( y_min, 0 ); x_end = MIN( x_max, x_size-1 ); y_end = MIN( y_max, y_size-1 ); x_len = x_end - x_start + 1; /* Dump the scanlines. Check once in a while for another * redraw event queued up, and quit early if one is seen. */ y_ptr = rgb_image + y_start*x_size*3 + x_start; for ( y = y_start; y <= y_end && (y%16 != 0 || qtest() != REDRAW); y++, y_ptr += x_size * 3 ) { cmov2i( x_start, y ); writeRGB( x_len, y_ptr, y_ptr + x_size, y_ptr + x_size * 2 ); } } break; /* Alt key - Reset viewing to look at the center of the image. * Shift-Alt - Restores a saved view center. * Control-alt - Saves the current view center for Shift-Setup. * F9 is the same as the Alt keys. */ case LEFTALTKEY: case RIGHTALTKEY: case F9KEY: if ( data == 1 ) /* Ignore button up events. */ { if ( getbutton(RIGHTSHIFTKEY) || getbutton(LEFTSHIFTKEY) ) { x_center = saved_x_center; /* Restore. */ y_center = saved_y_center; qenter( REDRAW, window_number ); } else if ( getbutton(CTRLKEY) ) { saved_x_center = x_center; /* Save. */ saved_y_center = y_center; } else { x_center = x_size / 2; /* Reset. */ y_center = y_size / 2; qenter( REDRAW, window_number ); } } break; /* Pan a point picked with the left mouse button to the center * of attention. Beep if cursor is not on the image. */ case LEFTMOUSE: if ( data == 1 ) /* Ignore button up events. */ { getorigin( &x_origin, &y_origin ); new_x_center = getvaluator( MOUSEX ) - x_origin + x_min; new_y_center = getvaluator( MOUSEY ) - y_origin + y_min; if ( new_x_center >= x_start && new_x_center <= x_end && new_y_center >= y_start && new_y_center <= y_end ) { x_center = new_x_center; y_center = new_y_center; qenter( REDRAW, window_number ); } else ringbell(); } break; } } } /* * Pack a scanline into a vector of RGB longs. * * Inputs: * rgb: Pointers to buffers containing the red, green, * and blue color rows. * n: Length of row. * line: Pointer to output buffer for packed color data. */ pack_rect_scanline( rgb, n, line ) unsigned char *rgb[3]; int n; long *line; { register int i; register long *dest = line; if ( !bwflag ) /* Color display. */ { register unsigned char *r, *g, *b; for ( i = 0, r = rgb[0], g = rgb[1], b = rgb[2]; i < n; i++, r++, g++, b++ ) /* Combine 3 8-bit colors into a long. */ *dest++ = *r + (*g<<8) + (*b<<16); } else /* Gray scale display. */ { register unsigned char *bw; for ( i = 0, bw = rgb[0]; i < n; i++, bw++ ) *dest++ = *bw + (*bw<<8) + (*bw<<16); } } /* * Pack a scanline into an RGB trio of vectors of bytes. * * Inputs: * rgb: Pointers to buffers containing the red, green, * and blue color rows. * n: Length of row. * line: Pointer to output buffer for packed color data. */ pack_rgb_scanline( rgb, n, lines ) unsigned char *rgb[3]; int n; char *lines; { int chnl; register int i; register unsigned char *src, *dest; for ( chnl = 0, dest = lines; chnl < 3; chnl++ ) { src = rgb[ bwflag ? 0 : chnl ]; /* Use just channel 0 for greyscale. */ for ( i = 0; i < n; i++ ) *dest++ = *src++; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.