matlab/strred/matlabPyrTools/MEX/wrap.c (195 lines of code) (raw):

/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; File: wrap.c ;;; Author: Eero Simoncelli ;;; Description: Circular convolution on 2D images. ;;; Creation Date: Spring, 1987. ;;; MODIFICATIONS: ;;; 6/96: Switched array types to double float. ;;; 2/97: made more robust and readable. Added STOP arguments. ;;; ---------------------------------------------------------------- ;;; Object-Based Vision and Image Understanding System (OBVIUS), ;;; Copyright 1988, Vision Science Group, Media Laboratory, ;;; Massachusetts Institute of Technology. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */ #include <stdlib.h> #include "convolve.h" /* -------------------------------------------------------------------- Performs correlation (i.e., convolution with filt(-x,-y)) of FILT with IMAGE followed by subsampling (a.k.a. REDUCE in Burt&Adelson81). The operations are combined to avoid unnecessary computation of the convolution samples that are to be discarded in the subsampling operation. The convolution is done in 9 sections so that mod operations are not performed unnecessarily. The subsampling lattice is specified by the START, STEP and STOP parameters. -------------------------------------------------------------------- */ /* abstract out the inner product computation */ #define INPROD(YSTART,YIND,XSTART,XIND) \ { \ sum=0.0; \ for (y_im=YSTART, filt_pos=0, x_filt_stop=x_fdim; \ x_filt_stop<=filt_size; \ y_im++, x_filt_stop+=x_fdim) \ for (x_im=XSTART ; \ filt_pos<x_filt_stop; \ filt_pos++, x_im++) \ sum += imval[YIND][XIND] * filt[filt_pos]; \ result[res_pos] = sum; \ } int internal_wrap_reduce(image, x_dim, y_dim, filt, x_fdim, y_fdim, x_start, x_step, x_stop, y_start, y_step, y_stop, result) register image_type *filt, *result; register int x_dim, y_dim, x_fdim, y_fdim; image_type *image; int x_start, x_step, x_stop, y_start, y_step, y_stop; { register double sum; register int filt_size = x_fdim*y_fdim; image_type **imval; register int filt_pos, x_im, y_im, x_filt_stop; register int x_pos, y_pos, res_pos; int x_ctr_stop = x_dim - x_fdim + 1; int y_ctr_stop = y_dim - y_fdim + 1; int x_ctr_start = 0; int y_ctr_start = 0; int x_fmid = x_fdim/2; int y_fmid = y_fdim/2; /* shift start/stop coords to filter upper left hand corner */ x_start -= x_fmid; y_start -= y_fmid; x_stop -= x_fmid; y_stop -= y_fmid; if (x_stop < x_ctr_stop) x_ctr_stop = x_stop; if (y_stop < y_ctr_stop) y_ctr_stop = y_stop; /* Set up pointer array for rows */ imval = (image_type **) malloc(y_dim*sizeof(image_type *)); if (imval IS NULL) { printf("INTERNAL_WRAP: Failed to allocate temp array!"); return(-1); } for (y_pos=y_im=0;y_pos<y_dim;y_pos++,y_im+=x_dim) imval[y_pos] = (image+y_im); for (res_pos=0, y_pos=y_start; /* TOP ROWS */ y_pos<y_ctr_start; y_pos+=y_step) { for (x_pos=x_start; x_pos<x_ctr_start; x_pos+=x_step, res_pos++) INPROD(y_pos+y_dim, y_im%y_dim, x_pos+x_dim, x_im%x_dim) for (; x_pos<x_ctr_stop; x_pos+=x_step, res_pos++) INPROD(y_pos+y_dim, y_im%y_dim, x_pos, x_im) for (; x_pos<x_stop; x_pos+=x_step, res_pos++) INPROD(y_pos+y_dim, y_im%y_dim, x_pos, x_im%x_dim) } /* end TOP ROWS */ for (; /* MID ROWS */ y_pos<y_ctr_stop; y_pos+=y_step) { for (x_pos=x_start; x_pos<x_ctr_start; x_pos+=x_step, res_pos++) INPROD(y_pos, y_im, x_pos+x_dim, x_im%x_dim) for (; /* CENTER SECTION */ x_pos<x_ctr_stop; x_pos+=x_step, res_pos++) INPROD(y_pos, y_im, x_pos, x_im) for (; x_pos<x_stop; x_pos+=x_step, res_pos++) INPROD(y_pos, y_im, x_pos, x_im%x_dim) } /* end MID ROWS */ for (; /* BOTTOM ROWS */ y_pos<y_stop; y_pos+=y_step) { for (x_pos=x_start; x_pos<x_ctr_start; x_pos+=x_step, res_pos++) INPROD(y_pos, y_im%y_dim, x_pos+x_dim, x_im%x_dim) for (; x_pos<x_ctr_stop; x_pos+=x_step, res_pos++) INPROD(y_pos, y_im%y_dim, x_pos, x_im) for (; x_pos<x_stop; x_pos+=x_step, res_pos++) INPROD(y_pos, y_im%y_dim, x_pos, x_im%x_dim) } /* end BOTTOM ROWS */ free ((image_type **) imval); return(0); } /* end of internal_wrap_reduce */ /* -------------------------------------------------------------------- Performs upsampling (padding with zeros) followed by convolution of FILT with IMAGE (a.k.a. EXPAND in Burt&Adelson81). The operations are combined to avoid unnecessary multiplication of filter samples with zeros in the upsampled image. The convolution is done in 9 sections so that mod operation is not performed unnecessarily. Arguments are described in the comment above internal_wrap_reduce. WARNING: this subroutine destructively modifes the RESULT image, so the user must zero the result before invocation! -------------------------------------------------------------------- */ /* abstract out the inner product computation */ #define INPROD2(YSTART,YIND,XSTART,XIND) \ { \ val = image[im_pos]; \ for (y_res=YSTART, filt_pos=0, x_filt_stop=x_fdim; \ x_filt_stop<=filt_size; \ y_res++, x_filt_stop+=x_fdim) \ for (x_res=XSTART; \ filt_pos<x_filt_stop; \ filt_pos++, x_res++) \ imval[YIND][XIND] += val * filt[filt_pos]; \ } int internal_wrap_expand(image, filt, x_fdim, y_fdim, x_start, x_step, x_stop, y_start, y_step, y_stop, result, x_dim, y_dim) register image_type *filt, *result; register int x_fdim, y_fdim, x_dim, y_dim; image_type *image; int x_start, x_step, x_stop, y_start, y_step, y_stop; { register double val; register int filt_size = x_fdim*y_fdim; image_type **imval; register int filt_pos, x_res, y_res, x_filt_stop; register int x_pos, y_pos, im_pos; int x_ctr_stop = x_dim - x_fdim + 1; int y_ctr_stop = y_dim - y_fdim + 1; int x_ctr_start = 0; int y_ctr_start = 0; int x_fmid = x_fdim/2; int y_fmid = y_fdim/2; /* shift start/stop coords to filter upper left hand corner */ x_start -= x_fmid; y_start -= y_fmid; x_stop -= x_fmid; y_stop -= y_fmid; if (x_stop < x_ctr_stop) x_ctr_stop = x_stop; if (y_stop < y_ctr_stop) y_ctr_stop = y_stop; /* Set up pointer array for rows */ imval = (image_type **) malloc(y_dim*sizeof(image_type *)); if (imval IS NULL) { printf("INTERNAL_WRAP: Failed to allocate temp array!"); return(-1); } for (y_pos=y_res=0;y_pos<y_dim;y_pos++,y_res+=x_dim) imval[y_pos] = (result+y_res); for (im_pos=0, y_pos=y_start; /* TOP ROWS */ y_pos<y_ctr_start; y_pos+=y_step) { for (x_pos=x_start; x_pos<x_ctr_start; x_pos+=x_step, im_pos++) INPROD2(y_pos+y_dim, y_res%y_dim, x_pos+x_dim, x_res%x_dim) for (; x_pos<x_ctr_stop; x_pos+=x_step, im_pos++) INPROD2(y_pos+y_dim, y_res%y_dim, x_pos, x_res) for (; x_pos<x_stop; x_pos+=x_step, im_pos++) INPROD2(y_pos+y_dim, y_res%y_dim, x_pos, x_res%x_dim) } /* end TOP ROWS */ for (; /* MID ROWS */ y_pos<y_ctr_stop; y_pos+=y_step) { for (x_pos=x_start; x_pos<x_ctr_start; x_pos+=x_step, im_pos++) INPROD2(y_pos, y_res, x_pos+x_dim, x_res%x_dim) for (; /* CENTER SECTION */ x_pos<x_ctr_stop; x_pos+=x_step, im_pos++) INPROD2(y_pos, y_res, x_pos, x_res) for (; x_pos<x_stop; x_pos+=x_step, im_pos++) INPROD2(y_pos, y_res, x_pos, x_res%x_dim) } /* end MID ROWS */ for (; /* BOTTOM ROWS */ y_pos<y_stop; y_pos+=y_step) { for (x_pos=x_start; x_pos<x_ctr_start; x_pos+=x_step, im_pos++) INPROD2(y_pos, y_res%y_dim, x_pos+x_dim, x_res%x_dim) for (; x_pos<x_ctr_stop; x_pos+=x_step, im_pos++) INPROD2(y_pos, y_res%y_dim, x_pos, x_res) for (; x_pos<x_stop; x_pos+=x_step, im_pos++) INPROD2(y_pos, y_res%y_dim, x_pos, x_res%x_dim) } /* end BOTTOM ROWS */ free ((image_type **) imval); return(0); } /* end of internal_wrap_expand */ /* Local Variables: */ /* buffer-read-only: t */ /* End: */