diff --git a/Base/include/FasTC/Image.h b/Base/include/FasTC/Image.h index 6554604..b1ad2aa 100644 --- a/Base/include/FasTC/Image.h +++ b/Base/include/FasTC/Image.h @@ -125,6 +125,11 @@ namespace FasTC { extern void GenerateGaussianKernel(Image &out, uint32 size, float sigma); + template + extern void SplitChannels(const Image &in, + Image *channelOne, + Image *channelTwo, + Image *channelThree); } // namespace FasTC #endif // __TEXCOMP_IMAGE_H__ diff --git a/Base/src/Image.cpp b/Base/src/Image.cpp index 681b97d..480273e 100644 --- a/Base/src/Image.cpp +++ b/Base/src/Image.cpp @@ -59,6 +59,11 @@ static inline T sad( const T &a, const T &b ) { return (a > b)? a - b : b - a; } +template +static inline T Clamp(const T &v, const T &a, const T &b) { + return ::std::min(::std::max(a, v), b); +} + // wtf #ifdef _MSC_VER template T log2(T x) { return static_cast(log((long double)x) / log(2.0)); } @@ -485,11 +490,6 @@ void Image::SetImageData(uint32 width, uint32 height, PixelType *data } } - template - static inline T Clamp(const T &v, const T &a, const T &b) { - return ::std::min(::std::max(a, v), b); - } - template void Image::Filter(const Image &kernel) { Image k(kernel); @@ -565,4 +565,49 @@ void GenerateGaussianKernel(Image &out, uint32 size, float sigma) { } } +template +void SplitChannelsImpl(const Image &in, + Image *channelOne, + Image *channelTwo, + Image *channelThree) { + assert(channelOne != NULL); + assert(channelTwo != NULL); + assert(channelThree != NULL); + assert(in.GetWidth() == channelOne->GetWidth()); + assert(in.GetHeight() == channelOne->GetHeight()); + assert(in.GetWidth() == channelTwo->GetWidth()); + assert(in.GetHeight() == channelTwo->GetHeight()); + assert(in.GetWidth() == channelThree->GetWidth()); + assert(in.GetHeight() == channelThree->GetHeight()); + + Image &i1 = *channelOne; + Image &i2 = *channelTwo; + Image &i3 = *channelThree; + + for (uint32 j = 0; j < in.GetHeight(); j++) { + for(uint32 i = 0; i < in.GetWidth(); i++) { + T c = in(i, j); + i1(i, j) = c.R(); + i2(i, j) = c.G(); + i3(i, j) = c.B(); + } + } +} + +template <> +void SplitChannels(const Image &in, + Image *channelOne, + Image *channelTwo, + Image *channelThree) { + SplitChannelsImpl(in, channelOne, channelTwo, channelThree); +} + +template <> +void SplitChannels(const Image &in, + Image *channelOne, + Image *channelTwo, + Image *channelThree) { + SplitChannelsImpl(in, channelOne, channelTwo, channelThree); +} + } // namespace FasTC diff --git a/Base/test/TestImage.cpp b/Base/test/TestImage.cpp index a874a31..3890a4a 100644 --- a/Base/test/TestImage.cpp +++ b/Base/test/TestImage.cpp @@ -51,6 +51,7 @@ */ #include "gtest/gtest.h" +#include "FasTC/Color.h" #include "FasTC/Image.h" #include "FasTC/IPixel.h" #include "FasTC/Pixel.h" @@ -167,3 +168,46 @@ TEST(Image, ComputeMSSIM) { double SSIM = img.ComputeSSIM(&img); EXPECT_EQ(SSIM, 1.0); } + +TEST(Image, SplitImage) { + + const uint32 w = 16; + const uint32 h = 16; + + FasTC::Image img(w, h); + for(uint32 j = 0; j < h; j++) { + for(uint32 i = 0; i < w; i++) { + img(i, j) = FasTC::Pixel(i, j, i+j, 255); + } + } + + FasTC::Image i1(w, h); + FasTC::Image i2(w, h); + FasTC::Image i3(w, h); + FasTC::SplitChannels(img, &i1, &i2, &i3); + + for(uint32 j = 0; j < h; j++) { + for(uint32 i = 0; i < w; i++) { + EXPECT_EQ(i1(i, j), img(i, j).R()); + EXPECT_EQ(i2(i, j), img(i, j).G()); + EXPECT_EQ(i3(i, j), img(i, j).B()); + } + } + + FasTC::Image img2(w, h); + for(uint32 j = 0; j < h; j++) { + for(uint32 i = 0; i < w; i++) { + img2(i, j) = FasTC::Color(j, i, i*j, 255); + } + } + + FasTC::SplitChannels(img2, &i1, &i2, &i3); + + for(uint32 j = 0; j < h; j++) { + for(uint32 i = 0; i < w; i++) { + EXPECT_EQ(i1(i, j), img2(i, j).R()); + EXPECT_EQ(i2(i, j), img2(i, j).G()); + EXPECT_EQ(i3(i, j), img2(i, j).B()); + } + } +}