/* program PICK to pick line out of an image to run, type: pick [-x -l -d( no dither ) -s ] or just pick and use the menu */ #include #include #include "az:plane.h" #include "az:general.h" #define X_SIDE 110 /* left side of disp. square */ #define Y_BASE 100 /* base for display square */ #define MIN_SIDE 5 /* minimun side for square */ #define X0 430 /* x for slice origin */ #define Y0 100 /* y for slice origin */ #define M 255 /* vectors run from 0 to M */ #define NO_DATA -1000.0 /* to indicate no data */ char dith_flag; /* true if dither required */ char menu_flag; /* true if main menu active */ char move_flag; /* true if text line cleared when cursor moved */ char larg_flag; /* true if expanded display required */ char out_flag; /* true if output file given */ char new_flag; /* true if new line required */ char side_flag; /* true if fixed line length required */ unsigned short fontbuf[FONTSIZE]; /* buffer for largest expected font */ char *fontname = "fmacs:font.visual"; int l, h, w; int xl_menu; /* left x for menu region */ int xr_menu; /* right x for menu region */ int y_menu; /* top y for menu region */ int nop; /* no. of options for menu */ FILE *fp = NULL; FILE *fq = NULL; int size_file = 0; /* size of file */ int size = 0; /* size of image */ int scale_size = 1; /* enlargement factor for displaying image, reduction factor when writing out image */ int grey; /* current grey level for text & information regions */ int col; /* current colour - red or cyam */ char store_filename[ 40 ]; /* stores output filename if any */ char int_array[ 256 * 256 ]; /* intensity array */ float vec[ M + 1 ], out_vec[ M + 1 ]; extern char read_file(), write_file(); void region(), pick(), limit_image(), draw_line(), clear_line(); void write_size(), clear_size(); int max(); char near(), in_image(); char sel_side(); void shift(), copy_line(); void menu(), draw_menu(), cl_menu(); void form_vec(), plot_vector(); main(argc,argv) char **argv; int argc; { char header_flag = TRUE; /* true if file contains header */ char arg_flag = FALSE; /* true if command line arguments given */ char i_flag = FALSE; /* true if intensity file given */ char c, *p, *p1; int line_size; dith_flag = TRUE; /* FLAG DEFAULTS */ out_flag = FALSE; larg_flag = FALSE; new_flag = TRUE; side_flag = FALSE; if ( argc > 1 ) { /* command line arguments given */ argv++; arg_flag = TRUE; while( ( argc > 0 ) && ( (*argv)[0] == '-' ) ) { switch( (*argv)[1] ) { case 'x': sscanf( *argv + 2, "%d", &size_file); header_flag = FALSE; break; case 'd': /* no dither */ dith_flag = FALSE; break; case 'l': larg_flag = TRUE; sscanf( *argv+2, "%d", &scale_size ); break; case 's': side_flag = TRUE; sscanf( *argv+2, "%d", &line_size ); break; default: error( "bad option"); break; } argc--; argv++; } } if ( --argc> 0 ) /* open input file if any */ { if ( ( fp = fopen( *(argv++), "r" ) ) == NULL ) { putchar( BEEP ); error( "can't open picture file" ); } else i_flag = TRUE; } if ( --argc > 0 ) /* open output file if any */ { if ( ( fq = fopen( *(argv++), "w" ) ) == NULL ) { putchar( BEEP ); error("can't open output file"); } else { out_flag = TRUE; p = *(argv); p1 = store_filename; while ( *p1++ = *p++ ); /* copy string */ } } l = readfont(fontname, fontbuf, FONTSIZE, &h, &w); grey = P_WHITE; col = P_RED; offset(0,0); sterm( 5 ); setup_map(); clear_screen(); setup_text(); setup_menu(); draw_axes( X0, Y0 ); /* default - menu on */ /* DEFAULT VALUES */ menu_flag = TRUE; draw_menu(); if ( i_flag ) { /* display image */ if ( header_flag ) size_file = getc( fp ) & 0377; if ( size_check() ) display( X_SIDE, Y_BASE, int_array, TRUE ); else exit( 0 ); } if ( arg_flag ) { /* to avoid error with command line arg */ write_text( "press return to continue " ); /* if command file not used */ if ( ( c = getchar() ) == EOF ) clearerr( stdin ); /* clear buffer */ clear_text(); } if ( side_flag ) /* write size */ { enable( col ); colour( P_COL ); write_size( line_size ); } region( line_size ); } void region( line_size ) /* middle Mouse Button ( MB ) selects option */ int line_size; { int option; int x = 50; /* initial position for cursor */ int y = 360; char exit_region_flag = FALSE; int x_ll, y_ll, side; /* lower left coordinates & length of line */ if ( side_flag ) /* side given in command line */ side = line_size - 1; while ( !exit_region_flag ) { enable( P_GREEN ); cursor( 0, &x, &y); if ( (mouse->b & 0377) == 2 ) { if ( in_image( x, y ) ) /* select line */ { pick( 2, &x, &y, &x_ll, &y_ll, &side ); } else if ( ( menu_flag ) && ( option = in_box( x, y) ) ) { menu( option, &x, &y, &x_ll, &y_ll, &side ); /* draw cursor - while button held */ enable( P_GREEN ); draw_cross( x, y); } } while ( mouse->b == 2 ) /* pause until button released */ ; } /* end of while */ } /* end of function */ void pick( c, px, py, px_ll, py_ll, pside ) /* while c = mouse>b moves cursor & returns current position (px,py) & returns line */ int c, *px, *py, *px_ll, *py_ll, *pside; { static int delta = 3; int old_x, old_y, x_offset, y_offset; int x_max, y_max, new_side; x_max = X_SIDE + size; /* upper limit for display image */ y_max = Y_BASE + size; old_x = *px; /* stores current position */ old_y = *py; /* calculate offset between mouse position and current position */ x_offset = SCALE( mouse->x ) - old_x; y_offset = SCALE( mouse->y ) - old_y; while ( (mouse->b & 0377) == c ) { *px = SCALE( mouse->x ) - x_offset; /* new position */ *py = SCALE( mouse->y ) - y_offset; limit_image( px, py); /* restricts cursor to image */ enable( P_GREEN ); draw_cross( *px, *py); /* draw cursor at new position */ if ( new_flag ) { if ( !side_flag ) /* size not fixed */ *pside = MIN_SIDE; if ( ( *px <= (x_max - 1 - *pside) ) ) { /* start new line */ *px_ll = *px; /* lower left hand corner for line */ *py_ll = *py; draw_line( *px_ll, *py_ll, *pside ); write_size( *pside + 1 ); new_flag = FALSE; delta = max( *pside >> 2, 3 ); } else { putchar( BEEP ); write_text("cursor too close to image boundary" ); move_flag = TRUE; } } else { if ( near( *px, *py, *px_ll, *py_ll, delta ) && ( (*px + *pside) < x_max ) ) { /* move line - not over boundary */ clear_line( *px_ll, *py_ll, *pside ); *px_ll = *px; *py_ll = *py; draw_line( *px_ll, *py_ll, *pside ); } else if ( !side_flag && near( *px, *py, *px_ll + *pside, *py_ll, delta ) ) { /* change side - not growing over boundary */ new_side = fabs( *px - *px_ll ); /* to prevent line shrinking to nothing */ new_side = max( new_side, MIN_SIDE ); if ( ( (*px_ll + new_side) < x_max ) && ( *pside != new_side ) ) { clear_line( *px_ll, *py_ll, *pside ); *pside = new_side; draw_line( *px_ll, *py_ll, *pside ); write_size( *pside + 1 ); delta = max( *pside >> 2, 3 ); } } else draw_line( *px_ll, *py_ll, *pside ); } if ( (*px != old_x) || (*py != old_y) ) { /* erase old cursor position */ if ( move_flag ) { /* clear text */ clear_text(); move_flag = FALSE; } enable( P_GREEN ); clear_cross( old_x, old_y); old_x = *px; old_y = *py; } } } void limit_image( px, py) /* restricts px & py to image */ int *px, *py; { if ( *px < X_SIDE ) *px = X_SIDE; if ( *px > X_SIDE + size - 1 ) *px = X_SIDE + size - 1; if ( *py < Y_BASE ) *py = Y_BASE; if ( *py > Y_BASE + size - 1 ) *py = Y_BASE + size - 1; } char near( x, y, x1, y1, delta ) /* returns TRUE if (x,y) nearer than delta but not coincident with (x1,y1) else returns FALSE */ int x, y, x1, y1, delta; { int dx, dy; dx = abs( x - x1 ); dy = abs( y - y1 ); if ( ( dx <= delta ) && ( dy <= delta ) && ( ( dx > 0 ) || ( dy > 0 ) ) ) return( TRUE ); else return( FALSE ); } int max( x, y ) /* returns maximun of x & y */ int x, y; { if ( x >= y ) return( x ); else return( y ); } void draw_line( x1, y1, side ) /* draws line with lower left hand corner (x1, y1) & side size */ int x1, y1, side; { enable( col ); colour( P_COL ); hline( x1, x1 + side, y1); } void clear_line( x1, y1, side ) /* clears line with lower left hand corner (x1, y1) & side size */ int x1, y1, side; { enable( col ); colour( BLACK ); hline( x1, x1 + side, y1); } char in_image( x, y) /* returns TRUE if (x,y) inside image else returns FALSE */ int x, y; { /* check if mouse inside image */ if ( ( x >= X_SIDE ) && ( x < ( X_SIDE + size ) ) && ( y >= Y_BASE ) && ( y < Y_BASE + size ) ) { return( TRUE ); } else return( FALSE ); } void write_size( size ) /* writes size - should only be invoked when size changed */ int size; { static char size_text[ 20 ] = ""; /* space to store text */ static char *text; static int x_text; static int y_text; x_text = xl_menu + 26; /* 15 + w */ y_text = y_menu - 420; /* y_menu - nop * 50 - 70 */ /* erase old text */ colour( BLACK ); text = size_text; setpos( x_text, y_text ); while ( *text ) gputc( *text++ ); /* write new text */ if ( size < 10 ) sprintf( size_text, " %d", size ); else if ( size < 100 ) sprintf( size_text, " %d", size ); else sprintf( size_text, "%d", size ); colour( P_COL ); text = size_text; setpos( x_text, y_text ); while ( *text ) gputc( *text++ ); } void clear_size() /* clears size */ { static int x_text; static int y_text; x_text = xl_menu + 26; /* 15 + w */ y_text = y_menu - 420; /* y_menu - nop * 50 - 70 */ /* erase size */ enable( P_COL ); colour( BLACK ); fill( x_text, y_text, x_text + 3 * w, y_text + h ); } /* ************************** MENU FUNCTIONS ******************************* */ void menu( option, px, py, px_ll, py_ll, pside ) /* selects option */ int option, *px, *py, *px_ll, *py_ll, *pside; { static char answer[ 20 ]; char statement[ 40 ]; switch ( option ) { case 1 : /* read intensity file */ if ( read_file() ) { display( X_SIDE, Y_BASE, int_array, TRUE ); } move_flag = TRUE; break; case 2 : /* write out to file */ if ( out_flag ) { sprintf( statement, "writing to file %s", store_filename ); write_text( statement ); copy_line( *px_ll, *py_ll, *pside, vec ); form_vec( vec, *pside, out_vec ); write_vec( out_vec ); out_flag = FALSE; } if ( open_write() ) { copy_line( *px_ll, *py_ll, *pside, vec ); form_vec( vec, *pside, out_vec ); write_vec( out_vec ); } move_flag = TRUE; break; case 3 : /* new box */ if ( sel_side( pside ) ) new_flag = TRUE; move_flag = TRUE; break; case 4 : /* clear */ cl_menu( px, py, px_ll, py_ll, pside ); clear_menu(); clear_text(); nop = 7; lab_menu( " read", "write", " new", "clear", " draw" ,"dither", " quit" ); break; case 5 : /* draw */ copy_line( *px_ll, *py_ll, *pside, vec ); plot_vector( col, vec, X0, Y0, *pside ); break; case 6 : /* dither on/off */ dith_flag = !dith_flag; if ( dith_flag ) write_text( "dither on" ); else write_text( "dither off" ); move_flag = TRUE; break; case 7 : /* quit */ clear_screen(); exit( 0 ); break; default: break; } } void draw_menu() /* draws menu */ { char *text; int x_text; nop = 7; x_text = xl_menu + 15; /* draw and label menu region */ enable( P_GREY ); colour( grey ); line( xr_menu + 10, 5, xr_menu + 10, y_menu ); /* label menu */ lab_menu( " read", "write", " new", "clear", " draw" ,"dither", " quit" ); /* write size label */ text = " size"; setpos( x_text, y_menu - nop * 50 - 50 ); while ( *text ) gputc( *text++ ); /* draw line for text region */ hline( 0, XPIXELS, YPIXELS - h - 3 ); } void cl_menu( px, py, px_ll, py_ll, pside ) /* CLEAR */ int *px, *py, *px_ll, *py_ll, *pside; { int option; static char title[ 20 ] = "CLEAR"; char exit_menu; clear_menu(); nop = 4; lab_menu( "line", "red", "cyam", "return" ); exit_menu = FALSE; while ( mouse->b == 2 ) /* pause until button released */ ; while ( !exit_menu ) { write_text( title ); enable( P_GREEN ); cursor( 0, px, py); if ( ( (mouse->b & 0377) == 2 ) && ( option = in_box( *px, *py) ) ) { switch ( option ) { case 1 : /* line */ clear_line( *px_ll, *py_ll, *pside ); clear_size(); new_flag = TRUE; break; case 2 : /* red */ colour( BLACK ); enable( P_RED ); fill( X0, Y0, X0 + M, Y0 + M ); break; case 3 : /* cyam */ colour( BLACK ); enable( P_CYAM ); fill( X0, Y0, X0 + M, Y0 + M ); break; case 4 : /* return */ exit_menu = TRUE; break; default: break; } } /* end of if */ while ( mouse->b == 2 ) /* pause until button released */ ; } /* end of while */ } /* end of cl_menu */ /***************************** GENERAL FUNCTIONS ***************************/ void copy_line( x_ll, y_ll, side, pvec ) /* copies contents of line into vector */ int x_ll, y_ll, side; float *pvec; { int x_image, y_image, new_size, intens; register int x, y1; register char *p; shift( x_ll, y_ll, &x_image, &y_image ); /* convert to image origin */ /* copy line */ y1 = size - 1 - y_image; /* since picture starts from the top */ p = int_array + size * y1; /* start of display line */ for ( x = x_image; x < x_image + side + 1; x++ ) { intens = *( p + x ) & 0377; *pvec++ = (float)intens; } } void shift( x, y, px_image, py_image) /* changes from screen origin to display image origin */ int x, y; int *px_image, *py_image; { *px_image = x - X_SIDE; *py_image = y - Y_BASE; } char sel_side( pside ) /* selects side length for line */ int *pside; { int line_size; char answer[ 20 ]; write_text( "fixed line size ? (y/n) : " ); read_response( answer ); if ( ( answer[ 0 ] == 'y' ) || ( answer[ 0 ] == 'Y' ) ) { write_text("size : "); read_response( answer ); sscanf( answer, "%d", &line_size ); if ( line_size > size ) { putchar( BEEP ); write_text( "size too large" ); return( FALSE ); } else if ( line_size < (MIN_SIDE + 1) ) { putchar( BEEP ); write_text( "size too small" ); return( FALSE ); } else { *pside = line_size - 1; side_flag = TRUE; clear_size(); if ( col == P_RED ) /* change colour */ col = P_CYAM; else col = P_RED; enable( col ); colour( P_COL ); write_size( line_size ); write_text( "select line" ); return( TRUE ); } } else if ( ( answer[ 0 ] == 'n' ) || ( answer[ 0 ] == 'N' ) ) { side_flag = FALSE; clear_size(); write_text( "select line" ); if ( col == P_RED ) /* change colour */ col = P_CYAM; else col = P_RED; return( TRUE ); } else { putchar( BEEP ); return( FALSE ); } } void form_vec( vec, m, out_vec ) /* formats vector for output - expands vector to as near 256 as possible, fills remaining points with NO_DATA */ float *vec, *out_vec; int m; { register int x, i; register float g; int scale_size, remainder; /* determine expansion factor */ scale_size = ( M + 1 ) / ( m + 1 ); remainder = M + 1 - ( m + 1 ) * scale_size; /* expand by scale size & write to output vector */ for ( x = 0; x < m + 1; x++ ) { g = *vec++; for ( i = 0; i < scale_size; i++ ) *out_vec++ = g; } /* fill in remainder */ for ( i = 0; i < remainder; i++ ) *out_vec++ = NO_DATA; } void plot_vector( col, p, x0, y0, m ) /* draws vector ( length = m + 1 ) colour col as y values on screen */ int col; float *p; int x0, y0, m; { int x, y; enable( col ); colour( P_COL ); for ( x = 0; x < m + 1; x++ ) { if ( *p != NO_DATA ) { y = *p++ + 0.5; plot( x + x0 , y + y0 ); } else { p++; } } }