| #pragma once |
| |
| #ifndef TCG_IMAGE_OPS_HPP |
| #define TCG_IMAGE_OPS_HPP |
| |
| |
| #include "../image_ops.h" |
| #include "../pixel.h" |
| #include "../unique_ptr.h" |
| |
| |
| #include <assert.h> |
| #include <memory> |
| |
| namespace tcg { |
| namespace image_ops { |
| |
| |
| |
| |
| |
| template <typename PtrIn, typename PtrOut, typename PixSum> |
| void _flatFilterLine(PtrIn in, PtrOut out, int lx, int addIn, int addOut, |
| int radius, PixSum *sums) { |
| typedef typename std::iterator_traits<PtrIn> trIn; |
| typedef typename trIn::value_type pixIn_type; |
| |
| struct locals { |
| inline static void fillSums(int lx, int radius, PtrIn lineIn, |
| PixSum *pixsum, int addIn, int addSum) { |
| using namespace pixel_ops; |
| |
| PtrIn newPixIn = lineIn; |
| |
| PixSum sum; |
| |
| |
| int x, xNew, xEnd = tmin(radius, lx); |
| |
| for (xNew = 0; xNew != xEnd; ++xNew, newPixIn += addIn) |
| sum = sum + *newPixIn; |
| |
| |
| |
| |
| |
| for (x = 0; xNew != lx; |
| ++x, ++xNew, lineIn += addIn, newPixIn += addIn, pixsum += addSum) { |
| sum = (sum + *newPixIn) - *lineIn; |
| *pixsum = *pixsum + sum; |
| } |
| |
| |
| for (; x != lx; ++x, lineIn += addIn, pixsum += addSum) { |
| sum = sum - *lineIn; |
| *pixsum = *pixsum + sum; |
| } |
| } |
| }; |
| |
| memset(sums, 0, lx * sizeof(PixSum)); |
| |
| |
| locals::fillSums(lx, radius, in, sums, addIn, |
| 1); |
| locals::fillSums(lx, radius, in + addIn * (lx - 1), sums + lx - 1, -addIn, |
| -1); |
| |
| |
| int diameter = 2 * radius + 1; |
| |
| for (int x = 0; x != lx; ++x, in += addIn, out += addOut, ++sums) { |
| using namespace pixel_ops; |
| |
| pixIn_type pix(*in); |
| pixel_ops::assign( |
| pix, (*sums + pix) / diameter); |
| |
| *out = pix; |
| } |
| } |
| |
| |
| |
| template <typename PtrIn, typename PtrOut, typename PixSum, |
| typename SelectorFunc> |
| void _flatFilterLine(PtrIn in, PtrOut out, int lx, int addIn, int addOut, |
| SelectorFunc selector, int radius, PixSum *sums, |
| int *counts) { |
| typedef typename std::iterator_traits<PtrIn> trIn; |
| typedef typename trIn::value_type pixIn_type; |
| |
| struct locals { |
| inline static void fillSums(int lx, int radius, PtrIn lineIn, |
| PixSum *pixsum, int *pixcount, int addIn, |
| int addSum, SelectorFunc selector) { |
| using namespace pixel_ops; |
| |
| PtrIn newPixIn = lineIn; |
| |
| PixSum sum; |
| int count = 0; |
| |
| |
| int x, xNew, xEnd = tmin(radius, lx); |
| |
| for (xNew = 0; xNew != xEnd; ++xNew, newPixIn += addIn) { |
| const pixIn_type &npi = *newPixIn; |
| |
| if (selector(npi)) sum = sum + npi, ++count; |
| } |
| |
| |
| |
| |
| |
| for (x = 0; xNew != lx; ++x, ++xNew, lineIn += addIn, newPixIn += addIn, |
| pixsum += addSum, pixcount += addSum) { |
| const pixIn_type &npi = *newPixIn, &li = *lineIn; |
| |
| if (selector(npi)) sum = sum + npi, ++count; |
| if (selector(li)) sum = sum - li, --count; |
| |
| *pixsum = *pixsum + sum, *pixcount += count; |
| } |
| |
| |
| for (; x != lx; |
| ++x, lineIn += addIn, pixsum += addSum, pixcount += addSum) { |
| const pixIn_type &li = *lineIn; |
| |
| if (selector(li)) sum = sum - li, --count; |
| |
| *pixsum = *pixsum + sum, *pixcount += count; |
| } |
| } |
| }; |
| |
| memset(sums, 0, lx * sizeof(PixSum)); |
| memset(counts, 0, lx * sizeof(int)); |
| |
| |
| locals::fillSums(lx, radius, in, sums, counts, addIn, 1, selector); |
| locals::fillSums(lx, radius, in + addIn * (lx - 1), sums + lx - 1, |
| counts + lx - 1, -addIn, -1, selector); |
| |
| |
| for (int x = 0; x != lx; ++x, in += addIn, out += addOut, ++sums, ++counts) { |
| using namespace pixel_ops; |
| |
| assert(*counts >= 0); |
| |
| pixIn_type pix(*in); |
| pixel_ops::assign(pix, (*sums + pix) / (*counts + 1)); |
| |
| *out = pix; |
| } |
| } |
| |
| |
| |
| template <typename ImgIn, typename ImgOut, typename Scalar> |
| void blurRows(const ImgIn &imgIn, ImgOut &imgOut, int radius, Scalar) { |
| typedef typename image_traits<ImgIn>::pixel_ptr_type PtrIn; |
| typedef typename image_traits<ImgOut>::pixel_ptr_type PtrOut; |
| typedef tcg::Pixel<Scalar, image_traits<ImgIn>::pixel_category> PixSum; |
| |
| |
| int inLx = image_traits<ImgIn>::width(imgIn), |
| inLy = image_traits<ImgIn>::height(imgIn); |
| int outLx = image_traits<ImgOut>::width(imgOut), |
| outLy = image_traits<ImgOut>::height(imgOut); |
| |
| assert(inLx == outLx && inLy == outLy); |
| |
| int inWrap = image_traits<ImgIn>::wrap(imgIn), |
| outWrap = image_traits<ImgOut>::wrap(imgOut); |
| |
| |
| tcg::unique_ptr<PixSum[]> sums(new PixSum[inLx]); |
| |
| |
| for (int y = 0; y != inLy; ++y) { |
| PtrIn lineIn = image_traits<ImgIn>::pixel(imgIn, 0, y); |
| PtrOut lineOut = image_traits<ImgOut>::pixel(imgOut, 0, y); |
| |
| _flatFilterLine(lineIn, lineOut, inLx, 1, 1, radius, sums.get()); |
| } |
| } |
| |
| |
| |
| template <typename ImgIn, typename ImgOut, typename SelectorFunc, |
| typename Scalar> |
| void blurRows(const ImgIn &imgIn, ImgOut &imgOut, int radius, |
| SelectorFunc selector, Scalar) { |
| typedef typename image_traits<ImgIn>::pixel_ptr_type PtrIn; |
| typedef typename image_traits<ImgOut>::pixel_ptr_type PtrOut; |
| typedef tcg::Pixel<Scalar, image_traits<ImgIn>::pixel_category> PixSum; |
| |
| |
| int inLx = image_traits<ImgIn>::width(imgIn), |
| inLy = image_traits<ImgIn>::height(imgIn); |
| int outLx = image_traits<ImgOut>::width(imgOut), |
| outLy = image_traits<ImgOut>::height(imgOut); |
| |
| assert(inLx == outLx && inLy == outLy); |
| |
| int inWrap = image_traits<ImgIn>::wrap(imgIn), |
| outWrap = image_traits<ImgOut>::wrap(imgOut); |
| |
| |
| tcg::unique_ptr<PixSum[]> sums(new PixSum[inLx]); |
| tcg::unique_ptr<int[]> counts(new int[inLx]); |
| |
| |
| for (int y = 0; y != inLy; ++y) { |
| PtrIn lineIn = image_traits<ImgIn>::pixel(imgIn, 0, y); |
| PtrOut lineOut = image_traits<ImgOut>::pixel(imgOut, 0, y); |
| |
| _flatFilterLine(lineIn, lineOut, inLx, 1, 1, selector, radius, sums.get(), |
| counts.get()); |
| } |
| } |
| |
| |
| |
| template <typename ImgIn, typename ImgOut, typename Scalar> |
| void blurCols(const ImgIn &imgIn, ImgOut &imgOut, int radius, Scalar) { |
| typedef typename image_traits<ImgIn>::pixel_ptr_type PtrIn; |
| typedef typename image_traits<ImgOut>::pixel_ptr_type PtrOut; |
| typedef tcg::Pixel<Scalar, typename image_traits<ImgIn>::pixel_category> |
| PixSum; |
| |
| |
| int inLx = image_traits<ImgIn>::width(imgIn), |
| inLy = image_traits<ImgIn>::height(imgIn); |
| int outLx = image_traits<ImgOut>::width(imgOut), |
| outLy = image_traits<ImgOut>::height(imgOut); |
| |
| assert(inLx == outLx && inLy == outLy); |
| |
| int inWrap = image_traits<ImgIn>::wrap(imgIn), |
| outWrap = image_traits<ImgOut>::wrap(imgOut); |
| |
| |
| tcg::unique_ptr<PixSum[]> sums(new PixSum[inLy]); |
| |
| |
| for (int x = 0; x != inLx; ++x) { |
| PtrIn lineIn = image_traits<ImgIn>::pixel(imgIn, x, 0); |
| PtrOut lineOut = image_traits<ImgOut>::pixel(imgOut, x, 0); |
| |
| _flatFilterLine(lineIn, lineOut, inLy, inWrap, outWrap, radius, sums.get()); |
| } |
| } |
| |
| |
| |
| template <typename ImgIn, typename ImgOut, typename SelectorFunc, |
| typename Scalar> |
| void blurCols(const ImgIn &imgIn, ImgOut &imgOut, int radius, |
| SelectorFunc selector, Scalar) { |
| typedef typename image_traits<ImgIn>::pixel_ptr_type PtrIn; |
| typedef typename image_traits<ImgOut>::pixel_ptr_type PtrOut; |
| typedef tcg::Pixel<Scalar, typename image_traits<ImgIn>::pixel_category> |
| PixSum; |
| |
| |
| int inLx = image_traits<ImgIn>::width(imgIn), |
| inLy = image_traits<ImgIn>::height(imgIn); |
| int outLx = image_traits<ImgOut>::width(imgOut), |
| outLy = image_traits<ImgOut>::height(imgOut); |
| |
| assert(inLx == outLx && inLy == outLy); |
| |
| int inWrap = image_traits<ImgIn>::wrap(imgIn), |
| outWrap = image_traits<ImgOut>::wrap(imgOut); |
| |
| |
| tcg::unique_ptr<PixSum[]> sums(new PixSum[inLy]); |
| tcg::unique_ptr<int[]> counts(new int[inLy]); |
| |
| |
| for (int x = 0; x != inLx; ++x) { |
| PtrIn lineIn = image_traits<ImgIn>::pixel(imgIn, x, 0); |
| PtrOut lineOut = image_traits<ImgOut>::pixel(imgOut, x, 0); |
| |
| _flatFilterLine(lineIn, lineOut, inLy, inWrap, outWrap, selector, radius, |
| sums.get(), counts.get()); |
| } |
| } |
| |
| |
| |
| template <typename ImgIn, typename ImgOut, typename Scalar> |
| void blur(const ImgIn &imgIn, ImgOut &imgOut, int radius, Scalar) { |
| blurRows(imgIn, imgOut, radius, Scalar); |
| blurCols(imgOut, imgOut, radius, Scalar); |
| } |
| |
| |
| |
| template <typename ImgIn, typename ImgOut, typename SelectorFunc, |
| typename Scalar> |
| void blur(const ImgIn &imgIn, ImgOut &imgOut, int radius, SelectorFunc selector, |
| Scalar) { |
| blurRows(imgIn, imgOut, radius, selector, Scalar); |
| blurCols(imgOut, imgOut, radius, selector, Scalar); |
| } |
| } |
| } |
| |
| #endif |