Add downscale test and fix a few bugs and formatting.

This commit is contained in:
Pavel Krajcevski 2013-09-19 17:47:36 -04:00
parent 1d58ea2385
commit 995c237e5e
2 changed files with 52 additions and 36 deletions

View file

@ -282,45 +282,32 @@ void Image::ContentAwareDownscale(uint32 xtimes, uint32 ytimes,
// Use central differences to calculate Ix, Iy, Ixx, Iyy...
for(uint32 j = 0; j < h; j++) {
for(uint32 i = 0; i < w; i++) {
uint32 hm2xidx = GetPixelIndex(i-2, j);
uint32 hm1xidx = GetPixelIndex(i-1, j);
uint32 hp1xidx = GetPixelIndex(i+1, j);
uint32 hp2xidx = GetPixelIndex(i+2, j);
uint32 xmhidx = GetPixelIndex(i-1, j);
uint32 xphidx = GetPixelIndex(i+1, j);
uint32 hm2yidx = GetPixelIndex(i, j-2);
uint32 hm1yidx = GetPixelIndex(i, j-1);
uint32 hp1yidx = GetPixelIndex(i, j+1);
uint32 hp2yidx = GetPixelIndex(i, j+2);
uint32 ymhidx = GetPixelIndex(i, j-1);
uint32 yphidx = GetPixelIndex(i, j+1);
uint32 idx = GetPixelIndex(i, j);
Ix[4][idx] = (I[hm2xidx] - 8*I[hm1xidx] + 8*I[hp1xidx] - I[hp2xidx]) / 12.0f;
Iy[idx] = (I[hm2yidx] - 8*I[hm1yidx] + 8*I[hp1yidx] - I[hp2yidx]) / 12.0f;
uint32 upidx = GetPixelIndex(i + 1, j + 1);
uint32 downidx = GetPixelIndex(i - 1, j - 1);
Ix[4][idx] = (I[xphidx] - I[xmhidx]) / 2.0f;
Iy[idx] = (I[yphidx] - I[ymhidx]) / 2.0f;
for(uint32 c = 0; c <= 3; c++) {
#define CPNT(dx) ConvertChannelToFloat(m_Pixels[dx].Component(c), bitDepth[c])
Ix[c][idx] = (CPNT(hm2xidx) - 8*CPNT(hm1xidx) + 8*CPNT(hp1xidx) - CPNT(hp2xidx)) / 12.0f;
Ixx[c][idx] = (-CPNT(hm2xidx) + 16*CPNT(hm1xidx) - 30*CPNT(idx) + 16*CPNT(hp1xidx) - CPNT(hp2xidx)) / 12.0f;
Iyy[c][idx] = (-CPNT(hm2yidx) + 16*CPNT(hm1yidx) - 30*CPNT(idx) + 16*CPNT(hp1yidx) - CPNT(hp2yidx)) / 12.0f;
Ix[c][idx] = (CPNT(xphidx) - CPNT(xmhidx)) / 2.0f;
Ixx[c][idx] = (CPNT(xphidx) - 2.0f*CPNT(idx) + CPNT(xmhidx)) / 2.0f;
Iyy[c][idx] = (CPNT(yphidx) - 2.0f*CPNT(idx) + CPNT(ymhidx)) / 2.0f;
Ixy[c][idx] = (CPNT(upidx) - CPNT(xphidx) - CPNT(yphidx) + 2.0f*CPNT(idx) -
CPNT(xmhidx) - CPNT(ymhidx) + CPNT(downidx)) / 2.0f;
#undef CPNT
}
}
}
// Finally, compute Ixy
for(uint32 j = 0; j < h; j++) {
for(uint32 i = 0; i < w; i++) {
uint32 hm2y = GetPixelIndex(i, j-2);
uint32 hm1y = GetPixelIndex(i, j-1);
uint32 hp1y = GetPixelIndex(i, j+1);
uint32 hp2y = GetPixelIndex(i, j+2);
uint32 idx = GetPixelIndex(i, j);
for(uint32 c = 0; c <= 3; c++) {
Ixy[c][idx] = (Ix[c][hm2y] - 8*Ix[c][hm1y] + 8*Ix[c][hp1y] - Ix[c][hp2y]) / 12.0f;
}
}
}
// Now, for each pixel that we take into consideration, use
// a smoothing step that is taken from the anisotropic diffusion
// equation:
@ -354,10 +341,12 @@ void Image::ContentAwareDownscale(uint32 xtimes, uint32 ytimes,
float I0 = ConvertChannelToFloat(current.Component(c), bitDepth[c]);
float It = Ixx[c][idx] + Iyy[c][idx];
if(fabs(denom) > 1e-6) {
It -= (Ixsq*Ixx[c][idx] + 2*Ix[4][idx]*Iy[idx]*Ixy[c][idx] + Iysq*Iyy[c][idx]);
It -= (Ixsq * Ixx[c][idx] +
2 * Ix[4][idx] * Iy[idx] * Ixy[c][idx] +
Iysq * Iyy[c][idx]) / denom;
}
float pxScale = static_cast<float>((1 << bitDepth[c]) - 1);
result.Component(c) = static_cast<uint8>(((I0 + 0.25*It) + 0.5) * pxScale);
float scale = static_cast<float>((1 << bitDepth[c]) - 1);
result.Component(c) = static_cast<uint8>((I0 + 0.25*It) * scale + 0.5);
}
downscaledPixels[j * newHeight + i] = result;
@ -448,7 +437,7 @@ const uint32 Image::GetPixelIndex(int32 i, int32 j, EWrapMode wrapMode) const {
}
}
int32 idx = j * GetWidth() + i;
uint32 idx = j * GetWidth() + i;
assert(idx >= 0);
assert(idx < GetWidth() * GetHeight());
return idx;

View file

@ -161,8 +161,8 @@ TEST(Image, BilinearUpscaleMaintainsPixels) {
const uint32 h = 4;
PVRTCC::Pixel pxs[16];
for(int i = 0; i < w; i++) {
for(int j = 0; j < h; j++) {
for(uint32 i = 0; i < w; i++) {
for(uint32 j = 0; j < h; j++) {
pxs[j*w + i].R() = rand() % 256;
pxs[j*w + i].G() = rand() % 256;
pxs[j*w + i].B() = rand() % 256;
@ -191,8 +191,8 @@ TEST(Image, NonuniformBilinearUpscale) {
const uint32 kHeight = 8;
PVRTCC::Pixel pxs[kWidth * kHeight];
for(int i = 0; i < kWidth; i++) {
for(int j = 0; j < kHeight; j++) {
for(uint32 i = 0; i < kWidth; i++) {
for(uint32 j = 0; j < kHeight; j++) {
pxs[j*kWidth + i].R() = i*4;
pxs[j*kWidth + i].G() = j*2;
}
@ -279,6 +279,33 @@ TEST(Image, BilinearUpscaleWrapped) {
}
}
TEST(Image, ContentAwareDownscale) {
PVRTCC::Image img(8, 8);
for(uint32 j = 0; j < img.GetHeight(); j++) {
for(uint32 i = 0; i < img.GetWidth(); i++) {
if(j < 4) {
img(i, j) = PVRTCC::Pixel( 0xFF000000 );
} else {
img(i, j) = PVRTCC::Pixel( 0xFF0000FF );
}
}
}
img.ContentAwareDownscale(1, 1);
EXPECT_EQ(img.GetWidth(), static_cast<uint32>(4));
EXPECT_EQ(img.GetHeight(), static_cast<uint32>(4));
for(uint32 j = 0; j < img.GetHeight(); j++) {
for(uint32 i = 0; i < img.GetWidth(); i++) {
if(j < 2) {
EXPECT_EQ(img(i, j).R(), 0);
} else {
EXPECT_EQ(img(i, j).R(), 255);
}
}
}
}
TEST(Image, ChangeBitDepth) {
PVRTCC::Image img(4, 4);