Add utility function for splitting images into images of pixel channels.

This commit is contained in:
Pavel Krajcevski 2015-01-26 17:27:35 -05:00
parent 34f90c07a2
commit 325a2ac96d
3 changed files with 99 additions and 5 deletions

View file

@ -125,6 +125,11 @@ namespace FasTC {
extern void GenerateGaussianKernel(Image<IPixel> &out, uint32 size, float sigma);
template <typename PixelType>
extern void SplitChannels(const Image<PixelType> &in,
Image<IPixel> *channelOne,
Image<IPixel> *channelTwo,
Image<IPixel> *channelThree);
} // namespace FasTC
#endif // __TEXCOMP_IMAGE_H__

View file

@ -59,6 +59,11 @@ static inline T sad( const T &a, const T &b ) {
return (a > b)? a - b : b - a;
}
template<typename T>
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<typename T> T log2(T x) { return static_cast<T>(log((long double)x) / log(2.0)); }
@ -485,11 +490,6 @@ void Image<PixelType>::SetImageData(uint32 width, uint32 height, PixelType *data
}
}
template<typename T>
static inline T Clamp(const T &v, const T &a, const T &b) {
return ::std::min(::std::max(a, v), b);
}
template<typename PixelType>
void Image<PixelType>::Filter(const Image<IPixel> &kernel) {
Image<IPixel> k(kernel);
@ -565,4 +565,49 @@ void GenerateGaussianKernel(Image<IPixel> &out, uint32 size, float sigma) {
}
}
template <typename T>
void SplitChannelsImpl(const Image<T> &in,
Image<IPixel> *channelOne,
Image<IPixel> *channelTwo,
Image<IPixel> *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<IPixel> &i1 = *channelOne;
Image<IPixel> &i2 = *channelTwo;
Image<IPixel> &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<Color>(const Image<Color> &in,
Image<IPixel> *channelOne,
Image<IPixel> *channelTwo,
Image<IPixel> *channelThree) {
SplitChannelsImpl(in, channelOne, channelTwo, channelThree);
}
template <>
void SplitChannels<Pixel>(const Image<Pixel> &in,
Image<IPixel> *channelOne,
Image<IPixel> *channelTwo,
Image<IPixel> *channelThree) {
SplitChannelsImpl(in, channelOne, channelTwo, channelThree);
}
} // namespace FasTC

View file

@ -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<FasTC::Pixel> 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<FasTC::IPixel> i1(w, h);
FasTC::Image<FasTC::IPixel> i2(w, h);
FasTC::Image<FasTC::IPixel> 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<FasTC::Color> 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());
}
}
}