123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- #pragma once
- #include <stdint.h>
- #include <algorithm>
- namespace Etc
- {
- enum FilterEnums
- {
- MaxFilterSize = 32
- };
- enum WrapFlags
- {
- FILTER_WRAP_NONE = 0,
- FILTER_WRAP_X = 0x1,
- FILTER_WRAP_Y = 0x2
- };
- typedef struct tagFilterWeights
- {
- int first;
- int numWeights;
- double weight[MaxFilterSize * 2 + 1];
- } FilterWeights;
- typedef struct tagRGBCOLOR
- {
- union
- {
- uint32_t ulColor;
- uint8_t rgba[4];
- };
- } RGBCOLOR;
- double FilterBox( double t );
- double FilterLinear( double t );
- double FilterLanczos3( double t );
- int FilterTwoPass( RGBCOLOR *pSrcImage, int srcWidth, int srcHeight,
- RGBCOLOR *pDestImage, int destWidth, int destHeight, unsigned int wrapFlags, double (*FilterProc)(double) );
- void FilterResample( RGBCOLOR *pSrcImage, int srcWidth, int srcHeight,
- RGBCOLOR *pDstImage, int dstWidth, int dstHeight );
- void CalcContributions(int srcSize, int destSize, double filterSize, bool wrap, double(*FilterProc)(double), FilterWeights contrib[]);
- template <typename T>
- void FilterResample(T *pSrcImage, int srcWidth, int srcHeight, T *pDstImage, int dstWidth, int dstHeight)
- {
- float xScale;
- float yScale;
- T *pSrcPixel;
- T *pDstPixel;
- xScale = (float)srcWidth / dstWidth;
- yScale = (float)srcHeight / dstHeight;
- for (int iRow = 0; iRow < dstHeight; iRow++)
- {
- for (int iCol = 0; iCol < dstWidth; iCol++)
- {
- int samples;
- int iFirstSampleRow;
- int iFirstSampleCol;
- int iLastSampleRow;
- int iLastSampleCol;
- float red;
- float green;
- float blue;
- float alpha;
- iFirstSampleRow = (int)(iRow * yScale);
- iLastSampleRow = (int)ceil(iFirstSampleRow + yScale - 1);
- if (iLastSampleRow >= srcHeight)
- {
- iLastSampleRow = srcHeight - 1;
- }
- iFirstSampleCol = (int)(iCol * xScale);
- iLastSampleCol = (int)ceil(iFirstSampleCol + xScale - 1);
- if (iLastSampleCol >= srcWidth)
- {
- iLastSampleCol = srcWidth - 1;
- }
- samples = 0;
- red = 0.f;
- green = 0.f;
- blue = 0.f;
- alpha = 0.f;
- for (int iSampleRow = iFirstSampleRow; iSampleRow <= iLastSampleRow; iSampleRow++)
- {
- for (int iSampleCol = iFirstSampleCol; iSampleCol <= iLastSampleCol; iSampleCol++)
- {
- pSrcPixel = pSrcImage + (iSampleRow * srcWidth + iSampleCol) * 4;
- red += static_cast<float>(pSrcPixel[0]);
- green += static_cast<float>(pSrcPixel[1]);
- blue += static_cast<float>(pSrcPixel[2]);
- alpha += static_cast<float>(pSrcPixel[3]);
- samples++;
- }
- }
- pDstPixel = pDstImage + (iRow * dstWidth + iCol) * 4;
- if (samples > 0)
- {
- pDstPixel[0] = static_cast<T>(red / samples);
- pDstPixel[1] = static_cast<T>(green / samples);
- pDstPixel[2] = static_cast<T>(blue / samples);
- pDstPixel[3] = static_cast<T>(alpha / samples);
- }
- else
- {
- pDstPixel[0] = static_cast<T>(red);
- pDstPixel[1] = static_cast<T>(green);
- pDstPixel[2] = static_cast<T>(blue);
- pDstPixel[3] = static_cast<T>(alpha);
- }
- }
- }
- }
- //**-------------------------------------------------------------------------
- //** Name: Filter_TwoPass( RGBCOLOR *pSrcImage,
- //** int srcWidth, int srcHeight,
- //** RGBCOLOR *pDestImage,
- //** int destWidth, int destHeight,
- //** double (*FilterProc)(double) )
- //** Returns: 0 on failure and 1 on success
- //** Description: Filters a 2d image with a two pass filter by averaging the
- //** weighted contributions of the pixels within the filter region. The
- //** contributions are determined by a weighting function parameter.
- //**-------------------------------------------------------------------------
- template <typename T>
- int FilterTwoPass(T *pSrcImage, int srcWidth, int srcHeight,
- T *pDestImage, int destWidth, int destHeight, unsigned int wrapFlags, double(*FilterProc)(double))
- {
- const int numComponents = 4;
- FilterWeights *contrib;
- T *pPixel;
- T *pTempImage;
- double dRed;
- double dGreen;
- double dBlue;
- double dAlpha;
- double filterSize = 3.0;
- int maxDim = (srcWidth>srcHeight) ? srcWidth : srcHeight;
- contrib = new FilterWeights[maxDim];
- //**------------------------------------------------------------------------
- //** Need to create a temporary image to stuff the horizontally scaled image
- //**------------------------------------------------------------------------
- pTempImage = new T[destWidth * srcHeight * numComponents];
- if (pTempImage == NULL)
- {
- return 0;
- }
- //**-------------------------------------------------------
- //** Horizontally filter the image into the temporary image
- //**-------------------------------------------------------
- bool bWrapHorizontal = !!(wrapFlags&FILTER_WRAP_X);
- CalcContributions(srcWidth, destWidth, filterSize, bWrapHorizontal, FilterProc, contrib);
- for (int iRow = 0; iRow < srcHeight; iRow++)
- {
- for (int iCol = 0; iCol < destWidth; iCol++)
- {
- dRed = 0;
- dGreen = 0;
- dBlue = 0;
- dAlpha = 0;
- for (int iWeight = 0; iWeight < contrib[iCol].numWeights; iWeight++)
- {
- int iSrcCol = iWeight + contrib[iCol].first;
- if(bWrapHorizontal)
- {
- iSrcCol = (iSrcCol < 0)?(srcWidth+iSrcCol):(iSrcCol >= srcWidth)?(iSrcCol-srcWidth):iSrcCol;
- }
- T* pSrcPixel = pSrcImage + ((iRow * srcWidth) + iSrcCol)*numComponents;
- dRed += contrib[iCol].weight[iWeight] * pSrcPixel[0];
- dGreen += contrib[iCol].weight[iWeight] * pSrcPixel[1];
- dBlue += contrib[iCol].weight[iWeight] * pSrcPixel[2];
- dAlpha += contrib[iCol].weight[iWeight] * pSrcPixel[3];
- }
- pPixel = pTempImage + ((iRow * destWidth) + iCol)*numComponents;
- pPixel[0] = static_cast<T>(std::max(0.0, std::min(255.0, dRed)));
- pPixel[1] = static_cast<T>(std::max(0.0, std::min(255.0, dGreen)));
- pPixel[2] = static_cast<T>(std::max(0.0, std::min(255.0, dBlue)));
- pPixel[3] = static_cast<T>(std::max(0.0, std::min(255.0, dAlpha)));
- }
- }
- //**-------------------------------------------------------
- //** Vertically filter the image into the destination image
- //**-------------------------------------------------------
- bool bWrapVertical = !!(wrapFlags&FILTER_WRAP_Y);
- CalcContributions(srcHeight, destHeight, filterSize, bWrapVertical, FilterProc, contrib);
- for (int iCol = 0; iCol < destWidth; iCol++)
- {
- for (int iRow = 0; iRow < destHeight; iRow++)
- {
- dRed = 0;
- dGreen = 0;
- dBlue = 0;
- dAlpha = 0;
- for (int iWeight = 0; iWeight < contrib[iRow].numWeights; iWeight++)
- {
- int iSrcRow = iWeight + contrib[iRow].first;
- if (bWrapVertical)
- {
- iSrcRow = (iSrcRow < 0) ? (srcHeight + iSrcRow) : (iSrcRow >= srcHeight) ? (iSrcRow - srcHeight) : iSrcRow;
- }
- T* pSrcPixel = pTempImage + ((iSrcRow * destWidth) + iCol)*numComponents;
- dRed += contrib[iRow].weight[iWeight] * pSrcPixel[0];
- dGreen += contrib[iRow].weight[iWeight] * pSrcPixel[1];
- dBlue += contrib[iRow].weight[iWeight] * pSrcPixel[2];
- dAlpha += contrib[iRow].weight[iWeight] * pSrcPixel[3];
- }
- pPixel = pDestImage + ((iRow * destWidth) + iCol)*numComponents;
- pPixel[0] = static_cast<T>(std::max(0.0, std::min(255.0, dRed)));
- pPixel[1] = static_cast<T>(std::max(0.0, std::min(255.0, dGreen)));
- pPixel[2] = static_cast<T>(std::max(0.0, std::min(255.0, dBlue)));
- pPixel[3] = static_cast<T>(std::max(0.0, std::min(255.0, dAlpha)));
- }
- }
- delete[] pTempImage;
- delete[] contrib;
- return 1;
- }
- }
|