EtcFilter.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #pragma once
  2. #include <stdint.h>
  3. #include <algorithm>
  4. namespace Etc
  5. {
  6. enum FilterEnums
  7. {
  8. MaxFilterSize = 32
  9. };
  10. enum WrapFlags
  11. {
  12. FILTER_WRAP_NONE = 0,
  13. FILTER_WRAP_X = 0x1,
  14. FILTER_WRAP_Y = 0x2
  15. };
  16. typedef struct tagFilterWeights
  17. {
  18. int first;
  19. int numWeights;
  20. double weight[MaxFilterSize * 2 + 1];
  21. } FilterWeights;
  22. typedef struct tagRGBCOLOR
  23. {
  24. union
  25. {
  26. uint32_t ulColor;
  27. uint8_t rgba[4];
  28. };
  29. } RGBCOLOR;
  30. double FilterBox( double t );
  31. double FilterLinear( double t );
  32. double FilterLanczos3( double t );
  33. int FilterTwoPass( RGBCOLOR *pSrcImage, int srcWidth, int srcHeight,
  34. RGBCOLOR *pDestImage, int destWidth, int destHeight, unsigned int wrapFlags, double (*FilterProc)(double) );
  35. void FilterResample( RGBCOLOR *pSrcImage, int srcWidth, int srcHeight,
  36. RGBCOLOR *pDstImage, int dstWidth, int dstHeight );
  37. void CalcContributions(int srcSize, int destSize, double filterSize, bool wrap, double(*FilterProc)(double), FilterWeights contrib[]);
  38. template <typename T>
  39. void FilterResample(T *pSrcImage, int srcWidth, int srcHeight, T *pDstImage, int dstWidth, int dstHeight)
  40. {
  41. float xScale;
  42. float yScale;
  43. T *pSrcPixel;
  44. T *pDstPixel;
  45. xScale = (float)srcWidth / dstWidth;
  46. yScale = (float)srcHeight / dstHeight;
  47. for (int iRow = 0; iRow < dstHeight; iRow++)
  48. {
  49. for (int iCol = 0; iCol < dstWidth; iCol++)
  50. {
  51. int samples;
  52. int iFirstSampleRow;
  53. int iFirstSampleCol;
  54. int iLastSampleRow;
  55. int iLastSampleCol;
  56. float red;
  57. float green;
  58. float blue;
  59. float alpha;
  60. iFirstSampleRow = (int)(iRow * yScale);
  61. iLastSampleRow = (int)ceil(iFirstSampleRow + yScale - 1);
  62. if (iLastSampleRow >= srcHeight)
  63. {
  64. iLastSampleRow = srcHeight - 1;
  65. }
  66. iFirstSampleCol = (int)(iCol * xScale);
  67. iLastSampleCol = (int)ceil(iFirstSampleCol + xScale - 1);
  68. if (iLastSampleCol >= srcWidth)
  69. {
  70. iLastSampleCol = srcWidth - 1;
  71. }
  72. samples = 0;
  73. red = 0.f;
  74. green = 0.f;
  75. blue = 0.f;
  76. alpha = 0.f;
  77. for (int iSampleRow = iFirstSampleRow; iSampleRow <= iLastSampleRow; iSampleRow++)
  78. {
  79. for (int iSampleCol = iFirstSampleCol; iSampleCol <= iLastSampleCol; iSampleCol++)
  80. {
  81. pSrcPixel = pSrcImage + (iSampleRow * srcWidth + iSampleCol) * 4;
  82. red += static_cast<float>(pSrcPixel[0]);
  83. green += static_cast<float>(pSrcPixel[1]);
  84. blue += static_cast<float>(pSrcPixel[2]);
  85. alpha += static_cast<float>(pSrcPixel[3]);
  86. samples++;
  87. }
  88. }
  89. pDstPixel = pDstImage + (iRow * dstWidth + iCol) * 4;
  90. if (samples > 0)
  91. {
  92. pDstPixel[0] = static_cast<T>(red / samples);
  93. pDstPixel[1] = static_cast<T>(green / samples);
  94. pDstPixel[2] = static_cast<T>(blue / samples);
  95. pDstPixel[3] = static_cast<T>(alpha / samples);
  96. }
  97. else
  98. {
  99. pDstPixel[0] = static_cast<T>(red);
  100. pDstPixel[1] = static_cast<T>(green);
  101. pDstPixel[2] = static_cast<T>(blue);
  102. pDstPixel[3] = static_cast<T>(alpha);
  103. }
  104. }
  105. }
  106. }
  107. //**-------------------------------------------------------------------------
  108. //** Name: Filter_TwoPass( RGBCOLOR *pSrcImage,
  109. //** int srcWidth, int srcHeight,
  110. //** RGBCOLOR *pDestImage,
  111. //** int destWidth, int destHeight,
  112. //** double (*FilterProc)(double) )
  113. //** Returns: 0 on failure and 1 on success
  114. //** Description: Filters a 2d image with a two pass filter by averaging the
  115. //** weighted contributions of the pixels within the filter region. The
  116. //** contributions are determined by a weighting function parameter.
  117. //**-------------------------------------------------------------------------
  118. template <typename T>
  119. int FilterTwoPass(T *pSrcImage, int srcWidth, int srcHeight,
  120. T *pDestImage, int destWidth, int destHeight, unsigned int wrapFlags, double(*FilterProc)(double))
  121. {
  122. const int numComponents = 4;
  123. FilterWeights *contrib;
  124. T *pPixel;
  125. T *pTempImage;
  126. double dRed;
  127. double dGreen;
  128. double dBlue;
  129. double dAlpha;
  130. double filterSize = 3.0;
  131. int maxDim = (srcWidth>srcHeight) ? srcWidth : srcHeight;
  132. contrib = new FilterWeights[maxDim];
  133. //**------------------------------------------------------------------------
  134. //** Need to create a temporary image to stuff the horizontally scaled image
  135. //**------------------------------------------------------------------------
  136. pTempImage = new T[destWidth * srcHeight * numComponents];
  137. if (pTempImage == NULL)
  138. {
  139. return 0;
  140. }
  141. //**-------------------------------------------------------
  142. //** Horizontally filter the image into the temporary image
  143. //**-------------------------------------------------------
  144. bool bWrapHorizontal = !!(wrapFlags&FILTER_WRAP_X);
  145. CalcContributions(srcWidth, destWidth, filterSize, bWrapHorizontal, FilterProc, contrib);
  146. for (int iRow = 0; iRow < srcHeight; iRow++)
  147. {
  148. for (int iCol = 0; iCol < destWidth; iCol++)
  149. {
  150. dRed = 0;
  151. dGreen = 0;
  152. dBlue = 0;
  153. dAlpha = 0;
  154. for (int iWeight = 0; iWeight < contrib[iCol].numWeights; iWeight++)
  155. {
  156. int iSrcCol = iWeight + contrib[iCol].first;
  157. if(bWrapHorizontal)
  158. {
  159. iSrcCol = (iSrcCol < 0)?(srcWidth+iSrcCol):(iSrcCol >= srcWidth)?(iSrcCol-srcWidth):iSrcCol;
  160. }
  161. T* pSrcPixel = pSrcImage + ((iRow * srcWidth) + iSrcCol)*numComponents;
  162. dRed += contrib[iCol].weight[iWeight] * pSrcPixel[0];
  163. dGreen += contrib[iCol].weight[iWeight] * pSrcPixel[1];
  164. dBlue += contrib[iCol].weight[iWeight] * pSrcPixel[2];
  165. dAlpha += contrib[iCol].weight[iWeight] * pSrcPixel[3];
  166. }
  167. pPixel = pTempImage + ((iRow * destWidth) + iCol)*numComponents;
  168. pPixel[0] = static_cast<T>(std::max(0.0, std::min(255.0, dRed)));
  169. pPixel[1] = static_cast<T>(std::max(0.0, std::min(255.0, dGreen)));
  170. pPixel[2] = static_cast<T>(std::max(0.0, std::min(255.0, dBlue)));
  171. pPixel[3] = static_cast<T>(std::max(0.0, std::min(255.0, dAlpha)));
  172. }
  173. }
  174. //**-------------------------------------------------------
  175. //** Vertically filter the image into the destination image
  176. //**-------------------------------------------------------
  177. bool bWrapVertical = !!(wrapFlags&FILTER_WRAP_Y);
  178. CalcContributions(srcHeight, destHeight, filterSize, bWrapVertical, FilterProc, contrib);
  179. for (int iCol = 0; iCol < destWidth; iCol++)
  180. {
  181. for (int iRow = 0; iRow < destHeight; iRow++)
  182. {
  183. dRed = 0;
  184. dGreen = 0;
  185. dBlue = 0;
  186. dAlpha = 0;
  187. for (int iWeight = 0; iWeight < contrib[iRow].numWeights; iWeight++)
  188. {
  189. int iSrcRow = iWeight + contrib[iRow].first;
  190. if (bWrapVertical)
  191. {
  192. iSrcRow = (iSrcRow < 0) ? (srcHeight + iSrcRow) : (iSrcRow >= srcHeight) ? (iSrcRow - srcHeight) : iSrcRow;
  193. }
  194. T* pSrcPixel = pTempImage + ((iSrcRow * destWidth) + iCol)*numComponents;
  195. dRed += contrib[iRow].weight[iWeight] * pSrcPixel[0];
  196. dGreen += contrib[iRow].weight[iWeight] * pSrcPixel[1];
  197. dBlue += contrib[iRow].weight[iWeight] * pSrcPixel[2];
  198. dAlpha += contrib[iRow].weight[iWeight] * pSrcPixel[3];
  199. }
  200. pPixel = pDestImage + ((iRow * destWidth) + iCol)*numComponents;
  201. pPixel[0] = static_cast<T>(std::max(0.0, std::min(255.0, dRed)));
  202. pPixel[1] = static_cast<T>(std::max(0.0, std::min(255.0, dGreen)));
  203. pPixel[2] = static_cast<T>(std::max(0.0, std::min(255.0, dBlue)));
  204. pPixel[3] = static_cast<T>(std::max(0.0, std::min(255.0, dAlpha)));
  205. }
  206. }
  207. delete[] pTempImage;
  208. delete[] contrib;
  209. return 1;
  210. }
  211. }