Change the Pandora code to all integers.
The code no longer uses the floating point emulation. The output still differs slightly from the original algorithm, but that might also be floating point rounding issues in the original algorithm. Note I still want to try some other things as well, therefore no comment yet.
This commit is contained in:
parent
fcc5e09153
commit
3f9ce95fd2
1 changed files with 62 additions and 35 deletions
|
@ -313,7 +313,7 @@ surface stretch_surface_vertical(
|
|||
|
||||
#ifdef PANDORA
|
||||
static void
|
||||
scale_surface_down(surface& dst, const surface& src, const int w, const int h)
|
||||
scale_surface_down(surface& dst, const surface& src, const int w_dst, const int h_dst)
|
||||
{
|
||||
const_surface_lock src_lock(src);
|
||||
surface_lock dst_lock(dst);
|
||||
|
@ -321,54 +321,81 @@ scale_surface_down(surface& dst, const surface& src, const int w, const int h)
|
|||
const Uint32* const src_pixels = src_lock.pixels();
|
||||
Uint32* const dst_pixels = dst_lock.pixels();
|
||||
|
||||
tfloat xratio = tfloat(src->w) / w;
|
||||
tfloat yratio = tfloat(src->h) / h;
|
||||
int y_dst = 0; // The current y in the destination surface
|
||||
|
||||
tfloat ysrc;
|
||||
for(int ydst = 0; ydst != h; ++ydst, ysrc += yratio) {
|
||||
tfloat xsrc;
|
||||
for(int xdst = 0; xdst != w; ++xdst, xsrc += xratio) {
|
||||
tfloat red, green, blue, alpha;
|
||||
int y_src = 0; // The current y in the source surface
|
||||
int y_src_next = 0; // The next y in the source surface
|
||||
int y_step = 0; // The y stepper
|
||||
int h_src = src->h; // The height of the source surface
|
||||
|
||||
tfloat summation;
|
||||
for( ; y_dst != h_dst; ++y_dst, y_src = y_src_next) {
|
||||
|
||||
y_step += h_src;
|
||||
do {
|
||||
++y_src_next;
|
||||
y_step -= h_dst;
|
||||
} while(y_step >= h_dst);
|
||||
|
||||
int x_dst = 0; // The current x in the destination surface
|
||||
|
||||
int x_src = 0; // The current x in the source surface
|
||||
int x_src_next = 0; // The next x in the source surface
|
||||
int x_step = 0; // The x stepper
|
||||
int w_src = src->w; // The width of the source surface
|
||||
|
||||
for( ; x_dst != w_dst; ++x_dst, x_src = x_src_next) {
|
||||
|
||||
x_step += w_src;
|
||||
do {
|
||||
++x_src_next;
|
||||
x_step -= w_dst;
|
||||
} while(x_step >= w_dst);
|
||||
|
||||
int r_sum = 0, g_sum = 0, b_sum = 0, a_sum = 0;
|
||||
int samples = 0;
|
||||
|
||||
// We now have a rectangle, (xsrc,ysrc,xratio,yratio)
|
||||
// which we want to derive the pixel from
|
||||
for(tfloat xloc = xsrc; xloc < xsrc+xratio; xloc += 1) {
|
||||
const tfloat xsize = std::min<tfloat>(floor(xloc + 1)-xloc,xsrc+xratio-xloc);
|
||||
for(tfloat yloc = ysrc; yloc < ysrc+yratio; yloc += 1) {
|
||||
const int xsrcint = std::max<int>(0,std::min<int>(src->w-1,xsrc.to_int()));
|
||||
const int ysrcint = std::max<int>(0,std::min<int>(src->h-1,ysrc.to_int()));
|
||||
for(int x = x_src; x < x_src_next; ++x) {
|
||||
for(int y = y_src; y < y_src_next; ++y) {
|
||||
|
||||
const tfloat ysize = std::min<tfloat>(floor(yloc+1)-yloc,ysrc+yratio-yloc);
|
||||
++samples;
|
||||
|
||||
Uint8 r,g,b,a;
|
||||
|
||||
SDL_GetRGBA(src_pixels[ysrcint*src->w + xsrcint],src->format,&r,&g,&b,&a);
|
||||
tfloat value = xsize * ysize;
|
||||
summation += value;
|
||||
if (!a) continue;
|
||||
value *= a;
|
||||
alpha += value;
|
||||
red += r * value;
|
||||
green += g * value;
|
||||
blue += b * value;
|
||||
SDL_GetRGBA(src_pixels[y_src * w_src + x_src], src->format, &r, &g, &b, &a);
|
||||
if(a) {
|
||||
a_sum += a;
|
||||
r_sum += r * a;
|
||||
g_sum += g * a;
|
||||
b_sum += b * a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha != 0) {
|
||||
red = red / alpha + 0.5;
|
||||
green = green / alpha + 0.5;
|
||||
blue = blue / alpha + 0.5;
|
||||
alpha = alpha / summation + 0.5;
|
||||
if(a_sum) {
|
||||
|
||||
const int adjustment = (a_sum + (a_sum > 1)) >> 1;
|
||||
r_sum += adjustment;
|
||||
g_sum += adjustment;
|
||||
b_sum += adjustment;
|
||||
|
||||
r_sum /= a_sum;
|
||||
g_sum /= a_sum;
|
||||
b_sum /= a_sum;
|
||||
|
||||
assert(samples == (x_src_next - x_src) * (y_src_next - y_src));
|
||||
if(samples != 1) {
|
||||
a_sum += (samples + 1) >> 1;
|
||||
a_sum /= samples;
|
||||
}
|
||||
}
|
||||
|
||||
dst_pixels[ydst*dst->w + xdst] = SDL_MapRGBA(
|
||||
dst_pixels[y_dst * w_dst + x_dst] = SDL_MapRGBA(
|
||||
dst->format
|
||||
, red.to_int()
|
||||
, green.to_int()
|
||||
, blue.to_int()
|
||||
, alpha.to_int());
|
||||
, r_sum
|
||||
, g_sum
|
||||
, b_sum
|
||||
, a_sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue