Decouple upscale directions so that we can non-uniformly scale images.

This commit is contained in:
Pavel Krajcevski 2013-09-12 14:44:54 -04:00
parent 7184d49ccd
commit b3f8fcd454
4 changed files with 63 additions and 20 deletions

View File

@ -168,8 +168,8 @@ namespace PVRTCC {
}
// Bilinearly upscale the images.
imgA.BilinearUpscale(2, wrapMode);
imgB.BilinearUpscale(2, wrapMode);
imgA.BilinearUpscale(2, 2, wrapMode);
imgB.BilinearUpscale(2, 2, wrapMode);
// Change the bitdepth to full resolution
imgA.ExpandTo8888();

View File

@ -127,12 +127,16 @@ static bool CompareBitDepths(const uint8 (&depth1)[4],
}
#endif
void Image::BilinearUpscale(uint32 times, EWrapMode wrapMode) {
const uint32 newWidth = m_Width << times;
const uint32 newHeight = m_Height << times;
void Image::BilinearUpscale(uint32 xtimes, uint32 ytimes,
EWrapMode wrapMode) {
const uint32 newWidth = m_Width << xtimes;
const uint32 newHeight = m_Height << ytimes;
const uint32 scale = 1 << times;
const uint32 offset = scale >> 1;
const uint32 xscale = 1 << xtimes;
const uint32 xoffset = xscale >> 1;
const uint32 yscale = 1 << ytimes;
const uint32 yoffset = yscale >> 1;
Pixel *upscaledPixels = new Pixel[newWidth * newHeight];
@ -147,15 +151,15 @@ void Image::BilinearUpscale(uint32 times, EWrapMode wrapMode) {
Pixel &p = upscaledPixels[pidx];
Pixel &fp = m_FractionalPixels[pidx];
const int32 highXIdx = (i + offset) / scale;
const int32 highXIdx = (i + xoffset) / xscale;
const int32 lowXIdx = highXIdx - 1;
const int32 highYIdx = (j + offset) / scale;
const int32 highYIdx = (j + yoffset) / yscale;
const int32 lowYIdx = highYIdx - 1;
const uint32 highXWeight = (i + offset) % scale;
const uint32 lowXWeight = scale - highXWeight;
const uint32 highYWeight = (j + offset) % scale;
const uint32 lowYWeight = scale - highYWeight;
const uint32 highXWeight = (i + xoffset) % xscale;
const uint32 lowXWeight = xscale - highXWeight;
const uint32 highYWeight = (j + yoffset) % yscale;
const uint32 lowYWeight = yscale - highYWeight;
const uint32 topLeftWeight = lowXWeight * lowYWeight;
const uint32 topRightWeight = highXWeight * lowYWeight;
@ -186,9 +190,9 @@ void Image::BilinearUpscale(uint32 times, EWrapMode wrapMode) {
#endif // NDEBUG
// bilerp each channel....
const uint16 scaleMask = (scale * scale) - 1;
const uint16 scaleMask = (xscale * yscale) - 1;
uint8 fpDepths[4];
for(uint32 c = 0; c < 4; c++) fpDepths[c] = times * times;
for(uint32 c = 0; c < 4; c++) fpDepths[c] = xtimes + ytimes;
fp.ChangeBitDepth(fpDepths);
for(uint32 c = 0; c < 4; c++) {
@ -198,7 +202,7 @@ void Image::BilinearUpscale(uint32 times, EWrapMode wrapMode) {
const uint32 br = bottomRight.Component(c) * bottomRightWeight;
const uint32 sum = tl + tr + bl + br;
fp.Component(c) = sum & scaleMask;
p.Component(c) = sum / (scale * scale);
p.Component(c) = sum / (xscale * yscale);
}
}
}

View File

@ -68,7 +68,8 @@ class Image {
Image &operator=(const Image &);
~Image();
void BilinearUpscale(uint32 times, EWrapMode wrapMode = eWrapMode_Clamp);
void BilinearUpscale(uint32 xtimes, uint32 ytimes,
EWrapMode wrapMode = eWrapMode_Clamp);
void ChangeBitDepth(const uint8 (&depths)[4]);
void ExpandTo8888();

View File

@ -131,7 +131,7 @@ TEST(Image, BilinearUpscale) {
}
PVRTCC::Image img(4, 4, pxs);
img.BilinearUpscale(1);
img.BilinearUpscale(1, 1);
EXPECT_EQ(img.GetWidth(), static_cast<uint32>(8));
EXPECT_EQ(img.GetHeight(), static_cast<uint32>(8));
@ -171,7 +171,7 @@ TEST(Image, BilinearUpscaleMaintainsPixels) {
}
PVRTCC::Image img(w, h, pxs);
img.BilinearUpscale(2);
img.BilinearUpscale(2, 2);
EXPECT_EQ(img.GetWidth(), w << 2);
EXPECT_EQ(img.GetHeight(), h << 2);
@ -184,6 +184,44 @@ TEST(Image, BilinearUpscaleMaintainsPixels) {
}
}
TEST(Image, NonuniformBilinearUpscale) {
const uint32 kWidth = 4;
const uint32 kHeight = 8;
PVRTCC::Pixel pxs[kWidth * kHeight];
for(int i = 0; i < kWidth; i++) {
for(int j = 0; j < kHeight; j++) {
pxs[j*kWidth + i].R() = i*4;
pxs[j*kWidth + i].G() = j*2;
}
}
PVRTCC::Image img(kHeight, kWidth, pxs);
img.BilinearUpscale(2, 1);
EXPECT_EQ(img.GetWidth(), static_cast<uint32>(kWidth << 2));
EXPECT_EQ(img.GetHeight(), static_cast<uint32>(kHeight << 1));
for(uint32 i = 0; i < img.GetWidth(); i++) {
for(uint32 j = 0; j < img.GetHeight(); j++) {
if(i <= 2) {
EXPECT_EQ(img(i, j).R(), 0);
} else if(i == 15) {
EXPECT_EQ(img(i, j).R(), 12);
} else {
EXPECT_EQ(img(i, j).R(), i-2);
}
if(j == 0) {
EXPECT_EQ(img(i, j).G(), 0);
} else {
EXPECT_EQ(img(i, j).G(), j-1);
}
}
}
}
TEST(Image, BilinearUpscaleWrapped) {
PVRTCC::Pixel pxs[16];
@ -201,7 +239,7 @@ TEST(Image, BilinearUpscaleWrapped) {
}
PVRTCC::Image img(4, 4, pxs);
img.BilinearUpscale(2, PVRTCC::eWrapMode_Wrap);
img.BilinearUpscale(2, 2, PVRTCC::eWrapMode_Wrap);
EXPECT_EQ(img.GetWidth(), static_cast<uint32>(16));
EXPECT_EQ(img.GetHeight(), static_cast<uint32>(16));