Reintroduce NN-based scaling in a separate function.
(Was removed in 2013-01-23T11:51:49Z!lipkab@zoho.com)
This commit is contained in:
parent
51d837cf65
commit
462afa50b4
2 changed files with 110 additions and 0 deletions
|
@ -572,6 +572,103 @@ surface scale_surface(const surface &surf, int w, int h, bool optimize)
|
|||
return optimize ? create_optimized_surface(dst) : dst;
|
||||
}
|
||||
|
||||
surface scale_surface_sharp(const surface& surf, int w, int h, bool optimize)
|
||||
{
|
||||
// Since SDL version 1.1.5 0 is transparent, before 255 was transparent.
|
||||
assert(SDL_ALPHA_TRANSPARENT==0);
|
||||
|
||||
if(surf == NULL)
|
||||
return NULL;
|
||||
|
||||
if(w == surf->w && h == surf->h) {
|
||||
return surf;
|
||||
}
|
||||
assert(w >= 0);
|
||||
assert(h >= 0);
|
||||
|
||||
surface dst(create_neutral_surface(w,h));
|
||||
|
||||
if (w == 0 || h ==0) {
|
||||
std::cerr << "Create an empty image\n";
|
||||
return create_optimized_surface(dst);
|
||||
}
|
||||
|
||||
surface src(make_neutral_surface(surf));
|
||||
// Now both surfaces are always in the "neutral" pixel format
|
||||
|
||||
if(src == NULL || dst == NULL) {
|
||||
std::cerr << "Could not create surface to scale onto\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef PANDORA
|
||||
scale_surface_down(dst);
|
||||
#else
|
||||
{
|
||||
const_surface_lock src_lock(src);
|
||||
surface_lock dst_lock(dst);
|
||||
|
||||
const Uint32* const src_pixels = src_lock.pixels();
|
||||
Uint32* const dst_pixels = dst_lock.pixels();
|
||||
|
||||
tfloat xratio = tfloat(surf->w) / w;
|
||||
tfloat yratio = tfloat(surf->h) / h;
|
||||
|
||||
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;
|
||||
|
||||
tfloat summation;
|
||||
|
||||
// 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()));
|
||||
const tfloat ysize = std::min<tfloat>(floor(yloc+1)-yloc,ysrc+yratio-yloc);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha != 0) {
|
||||
red = red / alpha + 0.5;
|
||||
green = green / alpha + 0.5;
|
||||
blue = blue / alpha + 0.5;
|
||||
alpha = alpha / summation + 0.5;
|
||||
}
|
||||
|
||||
dst_pixels[ydst*dst->w + xdst] = SDL_MapRGBA(
|
||||
dst->format
|
||||
, red.to_int()
|
||||
, green.to_int()
|
||||
, blue.to_int()
|
||||
, alpha.to_int());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return optimize ? create_optimized_surface(dst) : dst;
|
||||
}
|
||||
|
||||
|
||||
surface tile_surface(const surface& surf, int w, int h, bool optimize)
|
||||
{
|
||||
if (surf->w == w && surf->h == h) {
|
||||
|
|
|
@ -198,6 +198,19 @@ surface stretch_surface_vertical(
|
|||
*/
|
||||
surface scale_surface(const surface &surf, int w, int h, bool optimize=true);
|
||||
|
||||
/** Scale a surface using modified nearest neighbour algorithm. Use only if
|
||||
* preserving sharp edges is a priority (e.g. minimap).
|
||||
* @param surf The source surface.
|
||||
* @param w The width of the resulting surface.
|
||||
* @param h The height of the resulting surface.
|
||||
* @param optimize Should the return surface be RLE optimized.
|
||||
* @return A surface containing the scaled version of the source.
|
||||
* @retval 0 Returned upon error.
|
||||
* @retval surf Returned if w == surf->w and h == surf->h
|
||||
* note this ignores the optimize flag.
|
||||
*/
|
||||
surface scale_surface_sharp(const surface& surf, int w, int h, bool optimize=true);
|
||||
|
||||
/** Tile a surface
|
||||
* @param surf The source surface.
|
||||
* @param w The width of the resulting surface.
|
||||
|
|
Loading…
Add table
Reference in a new issue