Skip to content

Instantly share code, notes, and snippets.

@Shtille
Created December 9, 2016 13:37
Show Gist options
  • Save Shtille/b4ceac8a7a05d3b1f6838c82e7963082 to your computer and use it in GitHub Desktop.
Save Shtille/b4ceac8a7a05d3b1f6838c82e7963082 to your computer and use it in GitHub Desktop.
Make POT bitmap from NPOT bitmap using bilinear interpolation
template <typename T>
static T RoundToPowerOfTwo(T x)
{
T n = 1;
while (n < x)
n <<= 1;
return n;
}
static int InterpolateColor(int c1, int c2, float alpha)
{
int a1 = (c1 & 0xff000000) >> 24;
int b1 = (c1 & 0xff0000) >> 16;
int g1 = (c1 & 0x00ff00) >> 8;
int r1 = (c1 & 0x0000ff);
int a2 = (c2 & 0xff000000) >> 24;
int b2 = (c2 & 0xff0000) >> 16;
int g2 = (c2 & 0x00ff00) >> 8;
int r2 = (c2 & 0x0000ff);
int r = r1 + (int)((r2-r1)*alpha);
int g = g1 + (int)((g2-g1)*alpha);
int b = b1 + (int)((b2-b1)*alpha);
int a = a1 + (int)((a2-a1)*alpha);
return (a << 24) | (b << 16) | (g << 8) | r;
}
static void MakePotTextureFromNpot(int& width, int& height, std::vector<unsigned char>& vdata)
{
if (((width & (width-1)) != 0) || ((height & (height-1)) != 0))
{
// Need to make POT
unsigned int * data = reinterpret_cast<unsigned int*>(&vdata[0]);
int w2 = RoundToPowerOfTwo(width);
int h2 = RoundToPowerOfTwo(height);
// Rescale image to power of 2
int new_size = w2 * h2;
std::vector<unsigned char> new_vdata;
new_vdata.resize(new_size*4);
unsigned int * new_data = reinterpret_cast<unsigned int*>(&new_vdata[0]);
for (int dh2 = 0; dh2 < h2; ++dh2)
{
float rh = (float)dh2 / (float)h2;
float y = rh * (float)height;
int dh = (int)y;
int dh1 = std::min<int>(dh+1, height-1);
float ry = y - (float)dh; // fract part of y
for (int dw2 = 0; dw2 < w2; ++dw2)
{
float rw = (float)dw2 / (float)w2;
float x = rw * (float)width;
int dw = (int)x;
int dw1 = std::min<int>(dw+1, width-1);
float rx = x - (float)dw; // fract part of x
// We will use bilinear interpolation
int sample1 = (int) data[dw +width*dh ];
int sample2 = (int) data[dw1+width*dh ];
int sample3 = (int) data[dw +width*dh1];
int sample4 = (int) data[dw1+width*dh1];
int color1 = InterpolateColor(sample1, sample2, rx);
int color2 = InterpolateColor(sample3, sample4, rx);;
int color3 = InterpolateColor(color1, color2, ry);
new_data[dw2+w2*dh2] = (unsigned int)color3;
}
}
// Finally
width = w2;
height = h2;
vdata.swap(new_vdata);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment