/* program PICK to pick square out of an image to run, type: pick [-x -l -d( no dither ) -s ] or just pick and use the menu */ #include #include #include "plane.h" #include "general.h" #define X_SIDE 100 /* left side of disp. square */ #define Y_BASE 5 /* base for display square */ #define MIN_SIDE 5 /* minimun side for square */ 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 square required */ char side_flag; /* true if fixed side square 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 */ extern char read_file(), write_file(); void region(), pick(), limit_image(), draw_square(), clear_square(); void write_size(), clear_size(); int max(); char near(), in_image(); char sel_side(); void shift(), write_square(); void menu(), draw_menu(); 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 square_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", &square_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(); /* 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( square_size ); } region( square_size ); } void region( square_size ) /* middle Mouse Button ( MB ) selects option */ int square_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 & size of square */ if ( side_flag ) /* side given in command line */ side = square_size - 1; while ( !exit_region_flag ) { enable( P_GREEN ); cursor( 0, &x, &y); if ( (mouse->b & 0377) == 2 ) { if ( in_image( x, y ) ) /* select square */ { pick( 2, &x, &y, &x_ll, &y_ll, &side ); } else if ( ( menu_flag ) && ( option = in_box( x, y) ) ) { menu( option, &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 square */ 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) ) && ( *py <= (y_max - 1 - *pside) ) ) { /* start new square */ *px_ll = *px; /* lower left hand corner for square */ *py_ll = *py; draw_square( *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 ) && ( (*py + *pside) < y_max ) ) { /* move square - not over boundary */ clear_square( *px_ll, *py_ll, *pside ); *px_ll = *px; *py_ll = *py; draw_square( *px_ll, *py_ll, *pside ); } else if ( !side_flag && near( *px, *py, *px_ll + *pside, *py_ll + *pside, delta ) ) { /* change side - not growing over boundary */ new_side = max( *px - *px_ll, *py - *py_ll ); /* to prevent square shrinking to nothing */ new_side = max( new_side, MIN_SIDE ); if ( ( (*px_ll + new_side) < x_max ) && ( (*py_ll + new_side) < y_max ) && ( *pside != new_side ) ) { clear_square( *px_ll, *py_ll, *pside ); *pside = new_side; draw_square( *px_ll, *py_ll, *pside ); write_size( *pside + 1 ); delta = max( *pside >> 2, 3 ); } } else draw_square( *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_square( x1, y1, side ) /* draws square with lower left hand corner (x1, y1) & side size */ int x1, y1, side; { enable( col ); colour( P_COL ); hline( x1, x1 + side, y1); hline( x1, x1 + side, y1 + side); line( x1, y1, x1, y1 + side ); line( x1 + side, y1, x1 + side, y1 + side ); } void clear_square( x1, y1, side ) /* clears square with lower left hand corner (x1, y1) & side size */ int x1, y1, side; { enable( col ); colour( BLACK ); hline( x1, x1 + side, y1); hline( x1, x1 + side, y1 + side); line( x1, y1, x1, y1 + side ); line( x1 + side, y1, x1 + side, y1 + side ); } 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_ll, py_ll, pside ) /* selects option */ int option, *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 ); write_square( *px_ll, *py_ll, *pside ); out_flag = FALSE; } else if ( write_file() ) write_square( *px_ll, *py_ll, *pside ); move_flag = TRUE; break; case 3 : /* new box */ if ( sel_side( pside ) ) new_flag = TRUE; move_flag = TRUE; break; case 4 : /* clear selected box */ clear_square( *px_ll, *py_ll, *pside ); clear_size(); new_flag = TRUE; break; case 5 : /* enlarged display */ larg_flag = TRUE; write_text( "scale factor : " ); read_response( answer ); sscanf( answer, "%d", &scale_size ); clear_text(); 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, Y_BASE, xr_menu + 10, y_menu ); /* label menu */ lab_menu( " read", "write", " new", "clear", "scale" ,"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 ); } /***************************** GENERAL FUNCTIONS ***************************/ void write_square( x_ll, y_ll, side ) /* writes out contents of square to file at required scale */ int x_ll, y_ll, side; { int x_image, y_image, new_size; register int x, y, y1; register char *p; char statement[ 40 ]; /* write header */ new_size = ( side + 1 ) / scale_size; putc( new_size, fq ); shift( x_ll, y_ll, &x_image, &y_image ); /* convert to image origin */ /* write out square */ for ( y = y_image + side; y > y_image - 1; y -= scale_size ) { y1 = size - 1 - y; /* 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 += scale_size ) putc( *( p + x ), fq); } fclose( fq ); sprintf( statement, "file written, size = %d", new_size ); write_text( statement ); } 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 square */ int *pside; { int square_size; char answer[ 20 ]; write_text( "fixed square size ? (y/n) : " ); read_response( answer ); if ( ( answer[ 0 ] == 'y' ) || ( answer[ 0 ] == 'Y' ) ) { write_text("size : "); read_response( answer ); sscanf( answer, "%d", &square_size ); if ( square_size > size ) { putchar( BEEP ); write_text( "size too large" ); return( FALSE ); } else if ( square_size < (MIN_SIDE + 1) ) { putchar( BEEP ); write_text( "size too small" ); return( FALSE ); } else { *pside = square_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( square_size ); write_text( "select square" ); return( TRUE ); } } else if ( ( answer[ 0 ] == 'n' ) || ( answer[ 0 ] == 'N' ) ) { side_flag = FALSE; clear_size(); write_text( "select square" ); if ( col == P_RED ) /* change colour */ col = P_CYAM; else col = P_RED; return( TRUE ); } else { putchar( BEEP ); return( FALSE ); } }