wrap.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;;; File: wrap.c
  4. ;;; Author: Eero Simoncelli
  5. ;;; Description: Circular convolution on 2D images.
  6. ;;; Creation Date: Spring, 1987.
  7. ;;; MODIFICATIONS:
  8. ;;; 6/96: Switched array types to double float.
  9. ;;; 2/97: made more robust and readable. Added STOP arguments.
  10. ;;; ----------------------------------------------------------------
  11. ;;; Object-Based Vision and Image Understanding System (OBVIUS),
  12. ;;; Copyright 1988, Vision Science Group, Media Laboratory,
  13. ;;; Massachusetts Institute of Technology.
  14. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  15. */
  16. #include <stdlib.h>
  17. #include "convolve.h"
  18. /*
  19. --------------------------------------------------------------------
  20. Performs correlation (i.e., convolution with filt(-x,-y)) of FILT
  21. with IMAGE followed by subsampling (a.k.a. REDUCE in Burt&Adelson81).
  22. The operations are combined to avoid unnecessary computation of the
  23. convolution samples that are to be discarded in the subsampling
  24. operation. The convolution is done in 9 sections so that mod
  25. operations are not performed unnecessarily. The subsampling lattice
  26. is specified by the START, STEP and STOP parameters.
  27. -------------------------------------------------------------------- */
  28. /* abstract out the inner product computation */
  29. #define INPROD(YSTART,YIND,XSTART,XIND) \
  30. { \
  31. sum=0.0; \
  32. for (y_im=YSTART, filt_pos=0, x_filt_stop=x_fdim; \
  33. x_filt_stop<=filt_size; \
  34. y_im++, x_filt_stop+=x_fdim) \
  35. for (x_im=XSTART ; \
  36. filt_pos<x_filt_stop; \
  37. filt_pos++, x_im++) \
  38. sum += imval[YIND][XIND] * filt[filt_pos]; \
  39. result[res_pos] = sum; \
  40. }
  41. int internal_wrap_reduce(image, x_dim, y_dim, filt, x_fdim, y_fdim,
  42. x_start, x_step, x_stop, y_start, y_step, y_stop,
  43. result)
  44. register image_type *filt, *result;
  45. register int x_dim, y_dim, x_fdim, y_fdim;
  46. image_type *image;
  47. int x_start, x_step, x_stop, y_start, y_step, y_stop;
  48. {
  49. register double sum;
  50. register int filt_size = x_fdim*y_fdim;
  51. image_type **imval;
  52. register int filt_pos, x_im, y_im, x_filt_stop;
  53. register int x_pos, y_pos, res_pos;
  54. int x_ctr_stop = x_dim - x_fdim + 1;
  55. int y_ctr_stop = y_dim - y_fdim + 1;
  56. int x_ctr_start = 0;
  57. int y_ctr_start = 0;
  58. int x_fmid = x_fdim/2;
  59. int y_fmid = y_fdim/2;
  60. /* shift start/stop coords to filter upper left hand corner */
  61. x_start -= x_fmid; y_start -= y_fmid;
  62. x_stop -= x_fmid; y_stop -= y_fmid;
  63. if (x_stop < x_ctr_stop) x_ctr_stop = x_stop;
  64. if (y_stop < y_ctr_stop) y_ctr_stop = y_stop;
  65. /* Set up pointer array for rows */
  66. imval = (image_type **) malloc(y_dim*sizeof(image_type *));
  67. if (imval IS NULL)
  68. {
  69. printf("INTERNAL_WRAP: Failed to allocate temp array!");
  70. return(-1);
  71. }
  72. for (y_pos=y_im=0;y_pos<y_dim;y_pos++,y_im+=x_dim)
  73. imval[y_pos] = (image+y_im);
  74. for (res_pos=0, y_pos=y_start; /* TOP ROWS */
  75. y_pos<y_ctr_start;
  76. y_pos+=y_step)
  77. {
  78. for (x_pos=x_start;
  79. x_pos<x_ctr_start;
  80. x_pos+=x_step, res_pos++)
  81. INPROD(y_pos+y_dim, y_im%y_dim, x_pos+x_dim, x_im%x_dim)
  82. for (;
  83. x_pos<x_ctr_stop;
  84. x_pos+=x_step, res_pos++)
  85. INPROD(y_pos+y_dim, y_im%y_dim, x_pos, x_im)
  86. for (;
  87. x_pos<x_stop;
  88. x_pos+=x_step, res_pos++)
  89. INPROD(y_pos+y_dim, y_im%y_dim, x_pos, x_im%x_dim)
  90. } /* end TOP ROWS */
  91. for (; /* MID ROWS */
  92. y_pos<y_ctr_stop;
  93. y_pos+=y_step)
  94. {
  95. for (x_pos=x_start;
  96. x_pos<x_ctr_start;
  97. x_pos+=x_step, res_pos++)
  98. INPROD(y_pos, y_im, x_pos+x_dim, x_im%x_dim)
  99. for (; /* CENTER SECTION */
  100. x_pos<x_ctr_stop;
  101. x_pos+=x_step, res_pos++)
  102. INPROD(y_pos, y_im, x_pos, x_im)
  103. for (;
  104. x_pos<x_stop;
  105. x_pos+=x_step, res_pos++)
  106. INPROD(y_pos, y_im, x_pos, x_im%x_dim)
  107. } /* end MID ROWS */
  108. for (; /* BOTTOM ROWS */
  109. y_pos<y_stop;
  110. y_pos+=y_step)
  111. {
  112. for (x_pos=x_start;
  113. x_pos<x_ctr_start;
  114. x_pos+=x_step, res_pos++)
  115. INPROD(y_pos, y_im%y_dim, x_pos+x_dim, x_im%x_dim)
  116. for (;
  117. x_pos<x_ctr_stop;
  118. x_pos+=x_step, res_pos++)
  119. INPROD(y_pos, y_im%y_dim, x_pos, x_im)
  120. for (;
  121. x_pos<x_stop;
  122. x_pos+=x_step, res_pos++)
  123. INPROD(y_pos, y_im%y_dim, x_pos, x_im%x_dim)
  124. } /* end BOTTOM ROWS */
  125. free ((image_type **) imval);
  126. return(0);
  127. } /* end of internal_wrap_reduce */
  128. /*
  129. --------------------------------------------------------------------
  130. Performs upsampling (padding with zeros) followed by convolution of
  131. FILT with IMAGE (a.k.a. EXPAND in Burt&Adelson81). The operations
  132. are combined to avoid unnecessary multiplication of filter samples
  133. with zeros in the upsampled image. The convolution is done in 9
  134. sections so that mod operation is not performed unnecessarily.
  135. Arguments are described in the comment above internal_wrap_reduce.
  136. WARNING: this subroutine destructively modifes the RESULT image, so
  137. the user must zero the result before invocation!
  138. -------------------------------------------------------------------- */
  139. /* abstract out the inner product computation */
  140. #define INPROD2(YSTART,YIND,XSTART,XIND) \
  141. { \
  142. val = image[im_pos]; \
  143. for (y_res=YSTART, filt_pos=0, x_filt_stop=x_fdim; \
  144. x_filt_stop<=filt_size; \
  145. y_res++, x_filt_stop+=x_fdim) \
  146. for (x_res=XSTART; \
  147. filt_pos<x_filt_stop; \
  148. filt_pos++, x_res++) \
  149. imval[YIND][XIND] += val * filt[filt_pos]; \
  150. }
  151. int internal_wrap_expand(image, filt, x_fdim, y_fdim,
  152. x_start, x_step, x_stop, y_start, y_step, y_stop,
  153. result, x_dim, y_dim)
  154. register image_type *filt, *result;
  155. register int x_fdim, y_fdim, x_dim, y_dim;
  156. image_type *image;
  157. int x_start, x_step, x_stop, y_start, y_step, y_stop;
  158. {
  159. register double val;
  160. register int filt_size = x_fdim*y_fdim;
  161. image_type **imval;
  162. register int filt_pos, x_res, y_res, x_filt_stop;
  163. register int x_pos, y_pos, im_pos;
  164. int x_ctr_stop = x_dim - x_fdim + 1;
  165. int y_ctr_stop = y_dim - y_fdim + 1;
  166. int x_ctr_start = 0;
  167. int y_ctr_start = 0;
  168. int x_fmid = x_fdim/2;
  169. int y_fmid = y_fdim/2;
  170. /* shift start/stop coords to filter upper left hand corner */
  171. x_start -= x_fmid; y_start -= y_fmid;
  172. x_stop -= x_fmid; y_stop -= y_fmid;
  173. if (x_stop < x_ctr_stop) x_ctr_stop = x_stop;
  174. if (y_stop < y_ctr_stop) y_ctr_stop = y_stop;
  175. /* Set up pointer array for rows */
  176. imval = (image_type **) malloc(y_dim*sizeof(image_type *));
  177. if (imval IS NULL)
  178. {
  179. printf("INTERNAL_WRAP: Failed to allocate temp array!");
  180. return(-1);
  181. }
  182. for (y_pos=y_res=0;y_pos<y_dim;y_pos++,y_res+=x_dim)
  183. imval[y_pos] = (result+y_res);
  184. for (im_pos=0, y_pos=y_start; /* TOP ROWS */
  185. y_pos<y_ctr_start;
  186. y_pos+=y_step)
  187. {
  188. for (x_pos=x_start;
  189. x_pos<x_ctr_start;
  190. x_pos+=x_step, im_pos++)
  191. INPROD2(y_pos+y_dim, y_res%y_dim, x_pos+x_dim, x_res%x_dim)
  192. for (;
  193. x_pos<x_ctr_stop;
  194. x_pos+=x_step, im_pos++)
  195. INPROD2(y_pos+y_dim, y_res%y_dim, x_pos, x_res)
  196. for (;
  197. x_pos<x_stop;
  198. x_pos+=x_step, im_pos++)
  199. INPROD2(y_pos+y_dim, y_res%y_dim, x_pos, x_res%x_dim)
  200. } /* end TOP ROWS */
  201. for (; /* MID ROWS */
  202. y_pos<y_ctr_stop;
  203. y_pos+=y_step)
  204. {
  205. for (x_pos=x_start;
  206. x_pos<x_ctr_start;
  207. x_pos+=x_step, im_pos++)
  208. INPROD2(y_pos, y_res, x_pos+x_dim, x_res%x_dim)
  209. for (; /* CENTER SECTION */
  210. x_pos<x_ctr_stop;
  211. x_pos+=x_step, im_pos++)
  212. INPROD2(y_pos, y_res, x_pos, x_res)
  213. for (;
  214. x_pos<x_stop;
  215. x_pos+=x_step, im_pos++)
  216. INPROD2(y_pos, y_res, x_pos, x_res%x_dim)
  217. } /* end MID ROWS */
  218. for (; /* BOTTOM ROWS */
  219. y_pos<y_stop;
  220. y_pos+=y_step)
  221. {
  222. for (x_pos=x_start;
  223. x_pos<x_ctr_start;
  224. x_pos+=x_step, im_pos++)
  225. INPROD2(y_pos, y_res%y_dim, x_pos+x_dim, x_res%x_dim)
  226. for (;
  227. x_pos<x_ctr_stop;
  228. x_pos+=x_step, im_pos++)
  229. INPROD2(y_pos, y_res%y_dim, x_pos, x_res)
  230. for (;
  231. x_pos<x_stop;
  232. x_pos+=x_step, im_pos++)
  233. INPROD2(y_pos, y_res%y_dim, x_pos, x_res%x_dim)
  234. } /* end BOTTOM ROWS */
  235. free ((image_type **) imval);
  236. return(0);
  237. } /* end of internal_wrap_expand */
  238. /* Local Variables: */
  239. /* buffer-read-only: t */
  240. /* End: */