Main Page   Data Structures   File List   Data Fields   Globals  

sconvl.c

Go to the documentation of this file.
00001 #include        "sadie.h"
00002 #include        "math.h"
00003 
00004 /*-Copyright Information------------------------------------------------------*/
00005 /* Copyright (c) 1988 by the University of Arizona Digital Image Analysis Lab */
00006 /*----------------------------------------------------------------------------*/
00007 /*-General Information--------------------------------------------------------*/
00008 /*                                                                            */
00009 /*   This function computes a two-dimensional spatial convolution between     */
00010 /*   a user-supplied spatial kernel and a single-band image.                  */
00011 /*                                                                            */
00012 /*----------------------------------------------------------------------------*/
00013 /*-Interface Information------------------------------------------------------*/
00014 void SCONVL (
00015 IMAGE *in,      /*  I   Pointer to the input image.                           */
00016 PIXEL *psf,     /*  I   Pointer to the convolution mask matrix[jsize][ksize]. */
00017 short jsize,    /*  I   Number of lines in the convolution mask.              */
00018 short ksize,    /*  I   Number of pixels/line in the convolution mask.        */
00019 IMAGE **out     /*  O   Address of a pointer to the output image.             */
00020 /*----------------------------------------------------------------------------*/
00021 ) { register short j, k, l, m, n, jmarg=jsize/2, kmarg=ksize/2, box;
00022     char   msg[SLEN];
00023     double sum, c1, cn, pinc, psum;
00024 
00025     int progmeter;
00026     double progress;
00027     int progcount, progtotal, progincr;
00028     int cancel=0;
00029 
00030     progmeter = ProgMeter_Create("Convolution");
00031     progress = 0.0;
00032 
00033 
00034     if (TIMES) TIMING(T_SCONVL);
00035     if (NAMES) {
00036         MESSAGE('I',"");
00037         MESSAGE('I',"SCONVL");
00038         MESSAGE('I',"");
00039         sprintf(msg," Input image:           %s",in->text);
00040         MESSAGE('I',msg);
00041         sprintf(msg," Kernel size: lines:    %d",jsize);
00042         MESSAGE('I',msg);
00043         sprintf(msg,"              pixels:   %d",ksize);
00044         MESSAGE('I',msg);
00045         if (jsize <= SLEN/16  &&  ksize <= SLEN/16) {
00046             MESSAGE('I'," Spatial kernel:");
00047             for (n=j=0; j<jsize; j++) {
00048                 for (m=k=0,msg[m++]=' '; k<ksize; k++,m=strlen(msg)) {
00049                     sprintf(msg+m,"%12.4e",(double)psf[n++]);
00050                 }
00051                 MESSAGE('I',msg);
00052             }
00053         } else {
00054             MESSAGE('I'," Kernel too large to list.");
00055         }
00056         MESSAGE('I'," ...............");
00057     }
00058 
00059     /* check input */
00060     if (!CHECKIMG(in)) {
00061         MESSAGE('E'," Can't identify image.");
00062         goto the_end;
00063     } else if (in->nbnd > 1) {
00064         MESSAGE('E'," Image must be single-band.");
00065         goto the_end;
00066     } else if (jsize < 0  ||  jsize%2 == 0) {
00067         MESSAGE('E'," Number of lines in the convolution mask must be an odd number greater than zero.");
00068         goto the_end;
00069     } else if (jsize > in->nlin) {
00070         MESSAGE('E'," Image size must be equal to or greater than convolution mask size in the line dimension.");
00071         goto the_end;
00072     } else if (ksize < 0  ||  ksize%2 == 0) {
00073         MESSAGE('E'," Number of pixels/line in the convolution mask must be an odd number greater than zero.");
00074         goto the_end;
00075     } else if (ksize > in->npix) {
00076         MESSAGE('E'," Image size must be equal to or greater than convolution mask size in the pixel dimension.");
00077         goto the_end;
00078     }
00079 
00080     /* create image of appropriate size */
00081     if (!CHECKIMG(*out)) GETMEM(1,in->nlin,in->npix,out);
00082     if (!*out) goto the_end;
00083 
00084     /* initialize progress indicator */
00085     if (LINES  &&  !PROGRESS(psum=0.0)) goto the_end;
00086     pinc = 1.0/(double)(in->nlin-2*jmarg);
00087     progtotal = in->nlin-2*jmarg;
00088     progcount = 0;
00089     progincr = rint((double)progtotal/20.0);
00090 
00091     /* see if it's a box-filter PSF */
00092     for (box=TRUE,k=1; box && k<jsize*ksize; k++) {
00093         box = psf[k] == psf[0];
00094     }
00095     
00096     if (box) {
00097         for (j=jmarg; j<in->nlin-jmarg; j++) {
00098 
00099             /* initialize box */
00100             for (c1=sum=0.0,l=j-jmarg; l<=j+jmarg; l++) {
00101                 c1 += (double)in->data[0][l][0];
00102                 for (k=1; k<ksize; k++) {
00103                     sum += (double)in->data[0][l][k];
00104                 }
00105             }
00106             (*out)->data[0][j][kmarg] = (PIXEL)((sum+=c1)*(double)psf[0]);
00107 
00108             /* box-filter algorithm */
00109             for (k=kmarg+1; k<in->npix-kmarg; k++) {
00110                 for (sum-=c1,c1=cn=0.0,l=j-jmarg; l<=j+jmarg; l++) {
00111                     c1 += (double)in->data[0][l][k-kmarg];
00112                     cn += (double)in->data[0][l][k+kmarg];
00113                 }
00114                 (*out)->data[0][j][k] = (PIXEL)((sum+=cn)*(double)psf[0]);
00115             }
00116             if (LINES  &&  !PROGRESS(psum+=pinc)) goto the_end;
00117             if (progmeter) {
00118                     progcount++;
00119                     if ((progcount%progincr) == 0) {
00120                         progress = ((double)progcount/(double)progtotal)*100.0;
00121                         cancel = ProgMeter_Update(progmeter,progress);
00122                         if (cancel != 0) goto the_end;
00123                     }
00124             }
00125         }
00126 
00127     } else /* compute normal convolution */ {
00128         for (j=jmarg; j<in->nlin-jmarg; j++) {
00129             for (k=kmarg; k<in->npix-kmarg; k++) {
00130                 for (sum=0.0,n=jsize*ksize,l=0; l<jsize; l++) {
00131                     for (m=0; m<ksize; m++) {
00132                         sum += (double)in->data[0][j-jmarg+l][k-kmarg+m]*(double)psf[--n];
00133                     }
00134                 }
00135                 (*out)->data[0][j][k] = (PIXEL)sum;
00136             }
00137             if (LINES  &&  !PROGRESS(psum+=pinc)) goto the_end;
00138             if (progmeter) {
00139                     progcount++;
00140                     if ((progcount%progincr) == 0) {
00141                         progress = ((double)progcount/(double)progtotal)*100.0;
00142                         cancel = ProgMeter_Update(progmeter,progress);
00143                         if (cancel != 0) goto the_end;
00144                     }
00145             }
00146         }
00147     }
00148 
00149     /* fill top and bottom margins */
00150     for (j=0; j<jmarg; j++) {
00151         for (k=0; k<in->npix-kmarg; k++) {
00152             (*out)->data[0][j][k]            = (*out)->data[0][jmarg][k];
00153             (*out)->data[0][in->nlin-j-1][k] = (*out)->data[0][in->nlin-jmarg-1][k];
00154         }
00155     }
00156 
00157     /* fill left and right margins */
00158     for (j=0; j<in->nlin; j++) {
00159         for (k=0; k<kmarg; k++) {
00160             (*out)->data[0][j][k]            = (*out)->data[0][j][kmarg];
00161             (*out)->data[0][j][in->npix-k-1] = (*out)->data[0][j][in->npix-kmarg-1];
00162         }
00163     }
00164 
00165     the_end:
00166     if (TIMES) TIMING(T_EXIT);
00167 
00168     if (progmeter) {
00169         ProgMeter_Destroy(progmeter);
00170     }
00171 
00172     if (cancel != 0) {
00173         if (*out) RELMEM(*out);
00174         *out = NULL;
00175     }
00176 }

Generated on Wed Apr 9 08:56:14 2003 for TREES by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002