Add method for downscaling by averaging nearby pixel values.

This commit is contained in:
Pavel Krajcevski 2013-10-03 14:12:41 -04:00
parent 8e555b8424
commit 160fbb5e39
3 changed files with 87 additions and 0 deletions

View File

@ -225,6 +225,66 @@ void Image::BilinearUpscale(uint32 xtimes, uint32 ytimes,
m_Height = newHeight;
}
static Pixel AveragePixels(const ::std::vector<Pixel> &pixels) {
if(pixels.size() == 0) {
return Pixel();
}
uint32 sum[4] = {0};
::std::vector<Pixel>::const_iterator it;
for(it = pixels.begin(); it != pixels.end(); it++) {
for(uint32 c = 0; c < 4; c++) {
sum[c] += (*it).Component(c);
}
}
Pixel result;
for(uint32 c = 0; c < 4; c++) {
result.Component(c) = sum[c] / pixels.size();
}
return result;
}
void Image::AverageDownscale(uint32 xtimes, uint32 ytimes, EWrapMode wrapMode) {
const uint32 w = GetWidth();
const uint32 h = GetHeight();
const uint32 newWidth = w >> xtimes;
const uint32 newHeight = h >> ytimes;
Pixel *downscaledPixels = new Pixel[newWidth * newHeight];
uint8 bitDepth[4];
m_Pixels[0].GetBitDepth(bitDepth);
uint32 pixelsX = 1 << xtimes;
uint32 pixelsY = 1 << ytimes;
::std::vector<Pixel> toAvg;
toAvg.reserve(pixelsX * pixelsY);
for(uint32 j = 0; j < newHeight; j++) {
for(uint32 i = 0; i < newWidth; i++) {
uint32 newIdx = j * newWidth + i;
toAvg.clear();
for(uint32 y = j * pixelsY; y < (j+1) * pixelsY; y++) {
for(uint32 x = i * pixelsX; x < (i+1) * pixelsX; x++) {
toAvg.push_back(GetPixel(x, y, wrapMode));
}
}
downscaledPixels[newIdx] = AveragePixels(toAvg);
}
}
delete m_Pixels;
m_Pixels = downscaledPixels;
m_Width = newWidth;
m_Height = newHeight;
}
void Image::ContentAwareDownscale(uint32 xtimes, uint32 ytimes,
EWrapMode wrapMode, bool bOffsetNewPixels) {
const uint32 w = GetWidth();

View File

@ -82,6 +82,10 @@ class Image {
EWrapMode wrapMode = eWrapMode_Wrap,
bool bOffsetNewPixels = false);
// Downscales the image by using a simple averaging of the neighboring pixel values
void AverageDownscale(uint32 xtimes, uint32 ytimes,
EWrapMode wrapMode = eWrapMode_Wrap);
void ComputeHessianEigenvalues(::std::vector<float> &eigOne,
::std::vector<float> &eigTwo,
EWrapMode wrapMode = eWrapMode_Wrap);

View File

@ -279,6 +279,29 @@ TEST(Image, BilinearUpscaleWrapped) {
}
}
TEST(Image, AverageDownscale) {
PVRTCC::Image img(8, 8);
for(uint32 j = 0; j < img.GetHeight(); j++) {
for(uint32 i = 0; i < img.GetWidth(); i++) {
if((i ^ j) & 1) {
img(i, j) = PVRTCC::Pixel(0xFF000000);
} else {
img(i, j) = PVRTCC::Pixel(0xFFFFFFFF);
}
}
}
img.AverageDownscale(1, 2);
EXPECT_EQ(img.GetWidth(), static_cast<uint32>(4));
EXPECT_EQ(img.GetHeight(), static_cast<uint32>(2));
for(uint32 j = 0; j < img.GetHeight(); j++) {
for(uint32 i = 0; i < img.GetWidth(); i++) {
EXPECT_EQ(PixelPrinter(0xFF7F7F7F), PixelPrinter(img(i, j).PackRGBA()));
}
}
}
TEST(Image, ContentAwareDownscale) {
PVRTCC::Image img(8, 8);
for(uint32 j = 0; j < img.GetHeight(); j++) {