mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2024-11-28 00:24:18 +01:00
Add utility function for splitting images into images of pixel channels.
This commit is contained in:
parent
34f90c07a2
commit
325a2ac96d
@ -125,6 +125,11 @@ namespace FasTC {
|
|||||||
|
|
||||||
extern void GenerateGaussianKernel(Image<IPixel> &out, uint32 size, float sigma);
|
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
|
} // namespace FasTC
|
||||||
|
|
||||||
#endif // __TEXCOMP_IMAGE_H__
|
#endif // __TEXCOMP_IMAGE_H__
|
||||||
|
@ -59,6 +59,11 @@ static inline T sad( const T &a, const T &b ) {
|
|||||||
return (a > b)? a - b : b - a;
|
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
|
// wtf
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
template<typename T> T log2(T x) { return static_cast<T>(log((long double)x) / log(2.0)); }
|
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>
|
template<typename PixelType>
|
||||||
void Image<PixelType>::Filter(const Image<IPixel> &kernel) {
|
void Image<PixelType>::Filter(const Image<IPixel> &kernel) {
|
||||||
Image<IPixel> k(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
|
} // namespace FasTC
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "FasTC/Color.h"
|
||||||
#include "FasTC/Image.h"
|
#include "FasTC/Image.h"
|
||||||
#include "FasTC/IPixel.h"
|
#include "FasTC/IPixel.h"
|
||||||
#include "FasTC/Pixel.h"
|
#include "FasTC/Pixel.h"
|
||||||
@ -167,3 +168,46 @@ TEST(Image, ComputeMSSIM) {
|
|||||||
double SSIM = img.ComputeSSIM(&img);
|
double SSIM = img.ComputeSSIM(&img);
|
||||||
EXPECT_EQ(SSIM, 1.0);
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user