diff options
Diffstat (limited to 'funtools/filter/imfilter.c')
-rw-r--r-- | funtools/filter/imfilter.c | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/funtools/filter/imfilter.c b/funtools/filter/imfilter.c new file mode 100644 index 0000000..d2495da --- /dev/null +++ b/funtools/filter/imfilter.c @@ -0,0 +1,335 @@ +/* for TEST: gcc -DTEST -g -o foo imfilter.c imregions.o -lm */ +#ifdef TEST +#include <stdio.h> +#include <math.h> +#define IMFILTRTN _FilterImage +#define NMASK 0 +#define MASKDIM 0 +#define _masks NULL +#define NSHAPE 2 +#define NREGION 2 +#define FILTER ((imcircle(g,1,1,1,4,(double)x,(double)y,8.0,8.0,5.0)))&&(imcircle(g,2,2,0,1,(double)x,(double)y,8.0,8.0,3.0)) +#define FILTSTR "((imcircle(g,1,1,1,4,(double)x,(double)y,8.0,8.0,5.0)))&&(imcircle(g,2,2,0,1,(double)x,(double)y,8.0,8.0,3.0))" +#define FINIT imcirclei(g,1,1,1,4,(double)x,(double)y,8.0,8.0,5.0);imcirclei(g,2,2,0,1,(double)x,(double)y,8.0,8.0,3.0); +#include "regions.h" +#endif + +/* these are global for use with special region routines */ +FilterMask masks=NULL; /* array valid region masks for one row */ +int maxmask; /* max masks allocated thus far */ +int nmask; /* number of mask segments */ +int nreg; /* number of regions in this set of rows */ +int rid; /* first valid region for current pixel */ +int x, y; /* current row and column */ +int rlen; /* length of temp region buf */ +int *rbuf; /* temp region flags */ +int *rptr; /* pointer into region buffer */ + +void incnmask(void) +{ + int omax; + nmask++; + if( nmask >= maxmask ){ + omax = maxmask; + maxmask += MASKINC; + masks = (FilterMask)realloc(masks, maxmask*sizeof(FilterMaskRec)); + memset(masks+omax, 0, (maxmask-omax)*sizeof(FilterMaskRec)); + } +} + +FilterMask +IMFILTRTN(int txmin, int txmax, int tymin, int tymax, int tblock, int *got) +{ + int i, j; + int fieldonly; + GFilt g; + Scan scan, tscan; + + /* make sure we have something to process */ + if( NSHAPE <=0 ){ + *got = 0; + return NULL; + } + /* allocate space for the globals */ + g = (GFilt)calloc(1, sizeof(GFiltRec)); + /* see if we have only the field shape */ + fieldonly = (NSHAPE==1) && strstr(FILTSTR, "field"); + /* allocate region records */ + g->nshapes = NSHAPE; + g->maxshapes = (NSHAPE*(XSNO+1))+1; + g->shapes = (Shape)calloc(g->maxshapes, sizeof(ShapeRec)); + /* make sure we start at 1 */ + g->block= max(1,tblock); + g->xmin = max(1,txmin); + g->xmax = txmax; + g->ymin = max(1,tymin); + g->ymax = tymax; + /* get x and y limits on subsection */ + g->x0 = 1; + g->y0 = 1; + g->x1 = (g->xmax-g->xmin)/g->block+1; + g->y1 = (g->ymax-g->ymin)/g->block+1; + /* allocate a temp region buffer */ + rlen = g->x1 - g->x0 + 1; + rbuf = (int *)calloc(rlen+1, sizeof(int)); + /* allocate an array of masks, which will be written to caller */ + maxmask = MASKINC; + masks = (FilterMask)calloc(maxmask, sizeof(FilterMaskRec)); + /* seed the first region mask value */ + nmask = 0; + masks[nmask].region = 0; + /* keep track of how many hits we had for this set of rows */ + nreg = 0; + /* allocate a buffer for valid y row flags */ + g->ybuf = (int *)calloc(g->y1+1, sizeof(int)); + g->x0s = (int *)calloc(g->y1+1, sizeof(int)); + g->x1s = (int *)calloc(g->y1+1, sizeof(int)); + /* seed impossible values for x limits */ + for(i=0; i<=g->y1; i++) g->x0s[i] = g->x1; + for(i=0; i<=g->y1; i++) g->x1s[i] = g->x0; + /* save image mask values */ + if( NMASK ){ + g->nmask = NMASK; + g->maskdim = MASKDIM; + g->masks = _masks; + } + /* initialize ybuf */ + FINIT; + /* process all valid rows */ + for(y=g->y0; y<=g->y1; y++){ + if( fieldonly ){ + /* inc the mask count, (extend mask array, if necessary) */ + masks[nmask].region = 1; + masks[nmask].y = y - g->y0 + 1; + masks[nmask].xstart = 1; + masks[nmask].xstop = (g->x1 - g->x0 + 1); + incnmask(); + continue; + } + if( g->ybuf[y] ){ + /* to start this line, we make a seed mask with no region */ + if( masks[nmask].region ){ + /* inc the mask count, (extend mask array, if necessary) */ + incnmask(); + masks[nmask].region = 0; + } + /* process each pixel in this row where there is a region */ + for(x=g->x0s[y], rptr=&rbuf[1+(g->x0s[y]-g->x0)]; x<=g->x1s[y]; + x++, rptr++){ + /* get filter result, which is the region id or 0 */ + g->rid = 0; + if( FILTER ){ + /* never change a region id to a -1 */ + if( *rptr == 0 ){ + nreg++; + *rptr = g->rid ? g->rid : -1; + } + /* but always overwrite a -1 */ + else if( (*rptr == -1) && (g->rid >0) ){ + *rptr = g->rid; + } + } + } + } + /* if we have processed a row, make up the segments */ + if( nreg ){ + for(i=1; i<=rlen; i++){ + if( rbuf[i] != masks[nmask].region ){ + /* if previous was non-zero region, finish it and bump to next */ + if( masks[nmask].region ){ + masks[nmask].xstop = i - 1; + /* inc the mask count, (extend mask array, if necessary) */ + incnmask(); + } + masks[nmask].y = y - g->y0 + 1; + masks[nmask].region = rbuf[i]; + masks[nmask].xstart = i; + } + } + /* finish last non-zero segment, inc number of mask segs */ + if( masks[nmask].region ){ + masks[nmask].xstop = (g->x1 - g->x0 + 1); + /* inc the mask count, (extend mask array, if necessary) */ + incnmask(); + } + /* reset counters for next set of rows */ + (void)memset(rbuf, 0, (rlen+1)*sizeof(int)); + rptr = rbuf; + nreg = 0; + } + } + /* free buffers */ + if( rbuf) free(rbuf); + /* free region information */ + if( g ){ + for(i=0; i<g->maxshapes; i++){ + if( g->shapes[i].scanlist ){ + for(j=0; j<=g->y1; j++){ + if( g->shapes[i].scanlist[j] ){ + for(scan=g->shapes[i].scanlist[j]; scan; ){ + tscan = scan->next; + free(scan); + scan = tscan; + } + } + } + free(g->shapes[i].scanlist); + } + if( g->shapes[i].pts ) free(g->shapes[i].pts); + if( g->shapes[i].xv ) free(g->shapes[i].xv); + } + if( g->masks ) free(g->masks); + if( g->shapes ) free(g->shapes); + if( g->ybuf ) free(g->ybuf); + if( g->x0s ) free(g->x0s); + if( g->x1s ) free(g->x1s); + if( g ) free(g); + } + /* return mask info */ + *got = nmask; + return masks; +} + +int main(int argc, char **argv) +{ + int i; + int get, got; +#if DO_FILTER_SWAP + int sgot; +#endif +#if HAVE_MINGW32==0 + int pipes[4]; +#endif + int txmin, txmax, tymin, tymax, tblock; + char tbuf[SZ_LINE]; + char *s=NULL, *t=NULL, *u=NULL; +#if USE_WIN32 + HANDLE hStdin, hStdout; + DWORD dwRead, dwWritten; +#endif + + /* Launch() sometimes rearranges passed pipes to be stdin/stdout */ +#if HAVE_MINGW32==0 + if( (s=getenv("LAUNCH_PIPES")) ){ + t = (char *)strdup(s); + for(i=0, u=(char *)strtok(t, ","); i<4 && u; + i++, u=(char *)strtok(NULL,",")){ + pipes[i] = atoi(u); + } + if( t ) free(t); + if( i < 4 ) return(1); + close(pipes[0]); + close(pipes[3]); + dup2(pipes[2], 0); close(pipes[2]); + dup2(pipes[1], 1); close(pipes[1]); + } +#endif + +#if USE_WIN32 + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + hStdin = GetStdHandle(STD_INPUT_HANDLE); + if( (hStdout == INVALID_HANDLE_VALUE) || (hStdin == INVALID_HANDLE_VALUE) ){ + unlink(argv[0]); + return 0; + } +#endif + + /* process requests for region information for sections of the image */ +#ifdef TEST + while( fgets(tbuf, SZ_LINE, stdin) ){ +#else +#if USE_WIN32 + while((ReadFile(hStdin, &get, sizeof(int), &dwRead, NULL) != FALSE) && + (dwRead == sizeof(int)) ){ +#else + while( read(0, &get, sizeof(int)) == sizeof(int) ){ +#endif +#if DO_FILTER_SWAP + switch(sizeof(int)){ + case 2: + _sw2((char *)&get,2,NULL,0); + break; + case 4: + _sw4((char *)&get,4,NULL,0); + break; + case 8: + _sw8((char *)&get,8,NULL,0); + break; + } +#endif +#if USE_WIN32 + if((ReadFile(hStdin, tbuf, get, &dwRead, NULL)==FALSE) || (dwRead != get)) + break; +#else + if(read(0, tbuf, get) != get) + break; +#endif +#endif /* #ifdef TEST */ + if(sscanf(tbuf, "%d %d %d %d %d", + &txmin, &txmax, &tymin, &tymax, &tblock)!=5){ + break; + } + masks = IMFILTRTN(txmin, txmax, tymin, tymax, tblock, &got); +#ifdef TEST + /* display segments for debugging */ + fprintf(stdout, "nmask=%d\n", nmask); + for(i=0; i<nmask; i++){ + fprintf(stdout, "region: %d\tx: (%d,%d)\ty: %d\n", + masks[i].region, masks[i].xstart, masks[i].xstop, masks[i].y); + } + fflush(stdout); +#else + /* calculate size of data we will write */ + got = got * sizeof(FilterMaskRec); +#if DO_FILTER_SWAP + sgot = got; + switch(sizeof(int)){ + case 2: + _sw2((char *)&sgot,2,NULL,0); + break; + case 4: + _sw4((char *)&sgot,4,NULL,0); + break; + case 8: + _sw8((char *)&sgot,8,NULL,0); + break; + } +#if USE_WIN32 + WriteFile(hStdout, &sgot, sizeof(int), &dwWritten, NULL); +#else + write(1, &sgot, sizeof(int)); +#endif +#else +#if USE_WIN32 + WriteFile(hStdout, &got, sizeof(int), &dwWritten, NULL); +#else + write(1, &got, sizeof(int)); +#endif +#endif +#if DO_FILTER_SWAP + switch(sizeof(int)){ + case 2: + _sw2((char *)masks,got,NULL,0); + break; + case 4: + _sw4((char *)masks,got,NULL,0); + break; + case 8: + _sw8((char *)masks,got,NULL,0); + break; + } +#endif +#if USE_WIN32 + WriteFile(hStdout, masks, got, &dwWritten, NULL); +#else + write(1, masks, got); +#endif +#endif + /* free mask records */ + if( masks ) free(masks); + } +#ifndef TEST + unlink(argv[0]); +#endif + return 0; +} |