view tools/bufframe.c @ 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
line wrap: on
line source
/*
    bufframe.c    shifting AIM output frame buffer.
    ----------



Examples:

1. To convert gennap output to multiple animated frames:

gennap len=16ms display=off output=stdout file | \
bufframe width=8ms frstep=0.2ms anim=on > file.sai
gensai useprev=on top=1000 cegc             -(for landscape plot)
genspl useprev=on top=1000 pensize=2 cegc   -(for spiral plot)

    (Note: spirals look better in a square box, so you might use options:
	   dencf=1 width=500 height=500 )

2. To view the basilar membrane from a cross section, animating the waves on it.

genbmm mincf=220 maxcf=660 len=8ms output=stdout display=off file | \
bufframe width=1p frstep=1p Tran=on display=on anim=on > foo.sai
gensai bott=-100 useprev=on mag=.2 foo

or:

genbmm mincf=220 maxcf=660 len=32ms output=stdout display=off file | \
bufframe width=1p frstep=1p Tran=on Header=off > foo

x11play -n75 -a500 foo

*/



#include <stdio.h>
#include <math.h>
#include "header.h"
#include "options.h"
#include "units.h"
#include "strmatch.h"


char applic[]     = "shifting AIM output frame buffer. " ;


static char *helpstr,   *debugstr, *dispstr,    *anistr,    *transtr  ;
static char *widthstr,  *shiftstr, *headerstr,  *framestr             ;

static Options option[] = {
    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                  , DEBUG   },
    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                      , DEBUG   },
    {   "width"     ,   "32ms"      ,  &widthstr    ,   "Width of image frame."                 , VAL     },
    {   "frstep"    ,   "16ms"      ,  &shiftstr    ,   "Step between image frames."            , VAL     },
    {   "frames"    ,   "min-max"   ,  &framestr    ,   "Select frames inclusively"             , VAL     },
    {   "Transpose" ,   "off"       ,  &transtr     ,   "Transpose image frames"                , SETFLAG },
    {   "Header"    ,   "on"        ,  &headerstr   ,   "Header (for gensai useprevious=on)."   , VAL     },
    {   "display"   ,   "on"        ,  &dispstr     ,   "Display output image."                 , SETFLAG },
    {   "animate"   ,   "off"       ,  &anistr      ,   "Animate cartoon."                      , SETFLAG },
   ( char * ) 0 } ;


int        frameheight,    framewidth,    frames,    framebytes ;
int     Newframeheight, Newframewidth, Newframes, Newframebytes ;

int        rows,    cols,    numframes ;
int     Newrows, Newcols, Newnumframes ;

int     samplerate  ;
int     frstep      ;
int     application ;
int     startbytes  ;
int     frshift     ;
int     Transpose   ;

main(argc, argv)
int   argc ;
char *argv[] ;
{
    FILE   *fp ;
    char   *header, *Header() ;
    short  *frame, *endframe ;
    char   *val1, *val2 ;
    int     i,j,k, a,b ;

    fp = openopts( option,argc,argv ) ;
    if ( !isoff( helpstr ) )
	helpopts( helpstr, argv[0], applic, option ) ;

    if ( ( header = ReadHeader( fp ) ) == (char *) 0 ) {
	fprintf( stderr, "edframe: header not found\n" ) ;
	exit( 1 ) ;
    }
    frameheight = HeaderInt( header, "frameheight" );
    framewidth  = HeaderInt( header, "framewidth"  );
    frames      = HeaderInt( header, "frames"      );
    samplerate  = HeaderSamplerate( header );

    if ( ( application = Applic( header) ) < 0 ) {
	fprintf(stderr,"bufframe: application name not found in header\n" ) ;
	exit( 1 ) ;
    }
    if ( Format( application ) != NAP ) {
	fprintf(stderr,"bufframe: buffer for %s format not implemented\n", gen_applics[application] ) ;
	exit( 1 ) ;
    }
    frame_to_matrix( NAP, &rows, &cols, &numframes, frameheight, framewidth, frames ) ;

    Transpose    = ison( transtr ) ;
    frstep       = to_p( shiftstr, samplerate ) ;
    Newrows      = frameheight ;
    Newcols      = to_p( widthstr, samplerate ) ;
    Newnumframes = ( cols - Newcols ) / frstep + 1 ;    /* since: Newcols + ( Newnumframes - 1 ) * frstep <= cols */


    /* Get limits on specified number of frames */

    if ( getvals( framestr, &val1, &val2, "-" ) == BADVAL ) {
	fprintf(stderr,"bufframe: bad frame selector [%s]\n", framestr ) ;
	exit( 1 ) ;
    }
    if      ( ismin( val1 ) ) a = 0 ;
    else if ( ismax( val1 ) ) a = Newnumframes - 1 ;
    else if ( Units( val1 ) ) a = (int)to_p( val1, samplerate ) / frstep ;
    else                      a = atoi( val1 ) ;

    if ( isempty( val2 ) )    b = a ;
    else if ( ismin( val2 ) ) b = 0 ;
    else if ( ismax( val2 ) ) b = Newnumframes - 1 ;
    else if ( Units( val2 ) ) b = (int)to_p( val2, samplerate ) / frstep ;
    else                      b = atoi( val2 ) ;

    if (a<0 || b>=Newnumframes || a>b) {
	if ( b>=Newnumframes ) fprintf(stderr,"bufframe: bad frame selector [%d frames needed but %d available]\n", b+1, Newnumframes );
	else                fprintf(stderr,"bufframe: bad frame selector \n" );
	exit(1);
    }

    Newnumframes = b - a + 1 ;

    framebytes   = Newrows * ( Newcols + ( Newnumframes - 1 ) * frstep ) * sizeof(short) ;

    if ( Transpose )
	matrix_to_frame( SAI, Newcols, Newrows, Newnumframes, &Newframeheight, &Newframewidth, &Newframes ) ;
    else
	matrix_to_frame( SAI, Newrows, Newcols, Newnumframes, &Newframeheight, &Newframewidth, &Newframes ) ;

    Newframebytes  = Newframeheight * Newframewidth * sizeof(short) ;

    if ( ison( headerstr ) )
	WriteHeader( Header( header ), stdout ) ;


    /* Allocate space for framebytes of data */

    if ( ( frame = (short *)malloc( framebytes ) ) == NULL ) {
	fprintf( stderr, "bufframe: malloc out of space\n" ) ;
	exit( 1 ) ;
    }

    frshift = frstep * rows ;

    /* Seek past `a' frames in blocks of framebytes */

    startbytes = a * frshift * sizeof(short) ;
    for (i=framebytes ; i < startbytes ; i += framebytes)
	if ( fread( frame, framebytes, 1, fp ) == NULL ) {
	    fprintf(stderr,"bufframe: missing data after header\n");
	    exit(1);
	}
    if ( (startbytes -= (i - framebytes)) > 0 )
	if ( fread( frame, startbytes, 1, fp ) == NULL ) {
	    fprintf(stderr,"bufframe: missing data after header\n");
	    exit(1);
	}

    /* Read framebytes of data */

    if ( fread( frame, framebytes, 1, fp ) == NULL ) {
	fprintf(stderr,"bufframe: insufficient data after header\n");
	exit(1);
    }
    fclose( fp ) ;

    endframe = frame + Newframes * frshift ;

    fprintf(stderr,"bufframe: %d frames   [height=%d  width=%d]\n", Newnumframes, Newframeheight, Newframewidth );

    if ( ison( debugstr ) ) {
	fprintf( stderr,"   frameheight=%3d    framewidth=%3d       frames=%3d    framebytes=%d\n",     frameheight,    framewidth,    frames,    framebytes ) ;
	fprintf( stderr,"Newframeheight=%3d Newframewidth=%3d    Newframes=%3d Newframebytes=%d\n",  Newframeheight, Newframewidth, Newframes, Newframebytes ) ;
	fprintf( stderr,"          rows=%3d          cols=%3d    numframes=%d\n",     rows,    cols,    numframes ) ;
	fprintf( stderr,"       Newrows=%3d       Newcols=%3d Newnumframes=%d\n",  Newrows, Newcols, Newnumframes ) ;
	fprintf( stderr,"frstep=%d  startbytes=%d frshift=%d\n",  frstep, startbytes, frshift ) ;
	exit( 1 ) ;
    }

    if ( Transpose ) {

	for (  ; frame < endframe ; frame += frshift )
	    for ( j=0 ; j < Newcols ; j++ )
		fwrite( frame + j*frameheight, sizeof(short), Newrows, stdout ) ;
    }

    else {
	for (  ; frame < endframe ; frame += frshift )
	    for (j=0 ; j < Newrows ; j++)
		for (k=0 , i=j ; k < Newcols ; k++, i+=frameheight)
		    fwrite( &frame[i], sizeof(short), 1, stdout );
    }
    fprintf(stderr,"bufframe: done\n" );
}



/* Return 1 if the str has appended units. Otherwise return 0.             */
/* (A freqency specifier with no units is interpreted as a channel number) */

Units(str)
char *str ;
{
    char *eptr = str + strlen( str ) ;

    if( isdigit( *--eptr ) ) return 0 ; /* last char is digit, so no units */
    else return 1 ;
}


/*
   Copy the original (NAP format) header to a new sai header, changing in order:
     frstep
     frames
     framewidth
     frameheight
     framebytes
     animate
     display
   Copy application name "sai" into the version string.
   Finally, update the new header_bytes, and return the new header.
*/

char *Header( oldheader )
char *oldheader ;
{
    char *saiheader;
    char *p0, *p1, *p2, *s, str[64];

    saiheader = (char *)malloc( strlen(oldheader) + 256 ) ;

    p0 = saiheader ;
    p1 = oldheader ;

    /* copy to first item after the header_bytes */

    p2 = HeaderString( oldheader , "header_bytes" ) ;
    while( p1 < p2 )
	*p0++ = *p1++ ;
    while (*p1 != '\n')
	*p0++ = *p1++ ;
    *p0++ = *p1++;

    /* insert frstep_aid at top of new header */

    sprintf( str,"frstep_aid=%s\n", shiftstr ) ;
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;


    /** copy up to channels_afb (if transpose changes apparent number of channels) **/

    if ( Transpose ) {
	p2 = HeaderString( oldheader , "channels_afb" ) ;
	while( p1 < p2 )
	    *p0++ = *p1++ ;

	sprintf(str,"%d\n", Newframeheight);
	for (s = str ; *s != '\n' ; )
	    *p0++ = *s++;
	*p0++ = *s;
	while (*p1 != '\n')
	    *p1++;
	*p1++;
    }


    /** copy up to frames **/

    p2 = HeaderString( oldheader , "frames" ) ;
    while( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%d\n", Newframes);
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy up to framewidth **/

    p2 = HeaderString( oldheader , "framewidth" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%d\n", Newframewidth);
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy up to frameheight **/

    p2 = HeaderString( oldheader , "frameheight" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%d\n", Newframeheight);
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy up to framebytes **/

    p2 = HeaderString( oldheader , "framebytes" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%d\n", Newframebytes);
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy up to animate_ctn **/

    p2 = HeaderString( oldheader , "animate_ctn" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%s\n", anistr );
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy up to display **/

    p2 = HeaderString( oldheader , "display" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    sprintf(str,"%s\n", dispstr );
    for (s = str ; *s != '\n' ; )
	*p0++ = *s++;
    *p0++ = *s;
    while (*p1 != '\n')
	*p1++;
    *p1++;


    /** copy rest of header **/

    p2 = HeaderString( oldheader , "Version" ) ;
    while ( p1 < p2 )
	*p0++ = *p1++ ;

       /** ( copy application name "sai" into header ) **/

    if ( ( p2 = ApplicString( oldheader ) ) == (char *)0 )  {
	fprintf(stderr,"bufframe: application name not found in header\n");
	exit( 1 ) ;
    }
    while ( p1 < p2 )
	*p0++ = *p1++ ;

    *p0++ = 's' ; *p0++ = 'a' ; *p0++ = 'i' ;
    p1 += 3 ;

    while (*p1 != '\n')
	*p0++ = *p1++ ;
    *p0++ = *p1++ ;


    /** update header_bytes **/

    sprintf(str, "%0*d", 7, p0-saiheader);
    p0 = HeaderString( saiheader , "header_bytes" ) ;
    s = str;
    while(*p0 != '\n')
	*p0++ = *s++ ;


    return saiheader;
}