mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2024-11-28 00:54:23 +01:00
Decouple upscale directions so that we can non-uniformly scale images.
This commit is contained in:
parent
7184d49ccd
commit
b3f8fcd454
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user