reduceColor.cc 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #include <math.h>
  2. #include <assert.h>
  3. #include <string.h>
  4. #include "mex.h"
  5. // reduce(im) resizes im to half its size, using a 5-tap binomial filter for anti-aliasing
  6. // (see Burt & Adelson's Laplacian Pyramid paper)
  7. // reduce each column
  8. // result is transposed, so we can apply it twice for a complete reduction
  9. void reduce1dtran(double *src, int sheight, double *dst, int dheight,
  10. int width, int chan) {
  11. // resize each column of each color channel
  12. bzero(dst, chan*width*dheight*sizeof(double));
  13. int y;
  14. double *s, *d;
  15. for (int c = 0; c < chan; c++) {
  16. for (int x = 0; x < width; x++) {
  17. s = src + c*width*sheight + x*sheight;
  18. d = dst + c*dheight*width + x;
  19. // First row
  20. *d = s[0]*.6875 + s[1]*.2500 + s[2]*.0625;
  21. for (y = 1; y < dheight-2; y++) {
  22. s += 2;
  23. d += width;
  24. *d = s[-2]*0.0625 + s[-1]*.25 + s[0]*.375 + s[1]*.25 + s[2]*.0625;
  25. }
  26. // Last two rows
  27. s += 2;
  28. d += width;
  29. if (dheight*2 <= sheight) {
  30. *d = s[-2]*0.0625 + s[-1]*.25 + s[0]*.375 + s[1]*.25 + s[2]*.0625;
  31. } else {
  32. *d = s[1]*.3125 + s[0]*.3750 + s[-1]*.2500 + s[-2]*.0625;
  33. }
  34. s += 2;
  35. d += width;
  36. *d = s[0]*.6875 + s[-1]*.2500 + s[-2]*.0625;
  37. }
  38. }
  39. }
  40. // main function
  41. // takes a double color image and a scaling factor
  42. // returns resized image
  43. mxArray *reduce(const mxArray *mxsrc) {
  44. double *src = (double *)mxGetPr(mxsrc);
  45. const int *sdims = mxGetDimensions(mxsrc);
  46. if (mxGetNumberOfDimensions(mxsrc) != 3 ||
  47. mxGetClassID(mxsrc) != mxDOUBLE_CLASS)
  48. mexErrMsgTxt("Invalid input");
  49. int ddims[3];
  50. ddims[0] = (int)round(sdims[0]*.5);
  51. ddims[1] = (int)round(sdims[1]*.5);
  52. ddims[2] = sdims[2];
  53. if (sdims[0] < 5|| sdims[1] < 5)
  54. mexErrMsgTxt("Minimum size of image is 5x5");
  55. mxArray *mxdst = mxCreateNumericArray(3, ddims, mxDOUBLE_CLASS, mxREAL);
  56. double *dst = (double *)mxGetPr(mxdst);
  57. double *tmp = (double *)mxCalloc(ddims[0]*sdims[1]*sdims[2], sizeof(double));
  58. reduce1dtran(src, sdims[0], tmp, ddims[0], sdims[1], sdims[2]);
  59. reduce1dtran(tmp, sdims[1], dst, ddims[1], ddims[0], sdims[2]);
  60. mxFree(tmp);
  61. return mxdst;
  62. }
  63. // matlab entry point
  64. // dst = resize(src, scale)
  65. // image should be color with double values
  66. void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  67. if (nrhs != 1)
  68. mexErrMsgTxt("Wrong number of inputs");
  69. if (nlhs != 1)
  70. mexErrMsgTxt("Wrong number of outputs");
  71. plhs[0] = reduce(prhs[0]);
  72. }
  73. /**********
  74. d = repmat([1:6]',[1 5 3]);
  75. a = reduce(d);
  76. *********/