Hacking Fast Smoothing Algorithm

BassAceGold

Testicles
OP
Member
Joined
Aug 14, 2006
Messages
496
Trophies
1
XP
441
Country
Canada
While working on my new menu, I needed someway of improving the image quality of downscaled images. The easiest way for reducing the pixeling that occurs in downscaling is pixel smoothing, or averaging. However this can require a lot of power and end up being really slow if one decides to implement such feature the easy way i.e. unpacking color channels, averaging, then repacking.

I initially had implemented the easy method to my library and was appalled at the drastic performance hit. At 396mhz, I could not stream mp3, and redraw the album cover at full speed with the smoothing enabled. This new algorithm, is drastically faster, almost to the point where it's performance hit is negligible on the lowest CPU speed (60mhz), at least in comparison to looping through all the pixels to draw an image.

Here is an image to illustrate the results:

Far right, image with no smoothing: full speed on lowest CPU speed
Far left, image with easy smoothing solution, lags on 396mhz cpu speed
Middle image, new smoothing function, full speed on 60mhz cpu speed
fastsmooth-1.png


Now for the code! It is relatively easy to add to any project:

Code:
typedef struct SmoothPixel{
u16 *buf;//pointer to image buffer
int x, y, wd, ht;//pixel you are drawing X, Y, image width, height
char corners;//set to non-zero for 8 pixel averaging, or 0 for 4 pixels
}SmoothPixel;

//these will average 15 bit colors, without unpacking
//method found from http://www.slack.net/~ant/info/rgb_mixing.html
#define PIXAVG_R5G5B5(a,b) ((a + b + ((a ^ b) & 0x0421)) >> 1)
//this is used for weighting the corner pixel averages
#define PIXAVG_R5G5B5_HALF(a,b) ((a + b + ((a ^ b) & 0x0421)) >> 2)

//only one branch statement used, could be split into two functions if necessary (one for 4 pixel avg, 8 pixel avg)
u16 BAG_Effects_PixSmoothing(const SmoothPixel *smooth){
register int curColor[9];
register int  x = smooth->x, y = smooth->y, wd = smooth->wd, ht = smooth->ht;

//center pixel
curColor[0] = smooth->buf[x + y * wd];
//left pixel
x--;
x += (x < 0);
curColor[1] = smooth->buf[x + y * wd];
//right pixel
x+=2;
x -= (x > wd);
curColor[2] = smooth->buf[x + y * wd];
//reset x to main pix
x--;
//up pixel
y--;
y += (y < 0);
curColor[3] = smooth->buf[x + y * wd];
//down pixel
y+=2;
y -= (y > ht);
curColor[4] = smooth->buf[x + y * wd];
if(smooth->corners){
//reset pos to center pixel
y--;
//left corners
x--;
x += (x < 0);
//left top
y--;
y += (y < 0);
curColor[5] = smooth->buf[x + y * wd];  
//left bottom
y+=2;
y -= (y > ht);
curColor[6] = smooth->buf[x + y * wd];
//right corners
x+=2;
x -= (x > wd);
//right bottom
curColor[7] = smooth->buf[x + y * wd];
//right yop
y-=2;
y += (y < 0);
curColor[8] = smooth->buf[x + y * wd];
//8 pixel average(lol)
return PIXAVG_R5G5B5(curColor[0], PIXAVG_R5G5B5(curColor[1], PIXAVG_R5G5B5(curColor[2], PIXAVG_R5G5B5(curColor[3],
//last normal pixel.......now the corner pixels
PIXAVG_R5G5B5(curColor[4], PIXAVG_R5G5B5_HALF(curColor[5], PIXAVG_R5G5B5_HALF(curColor[6],
PIXAVG_R5G5B5_HALF(curColor[7], curColor[8]))))))));
}
//4 pixel average
return PIXAVG_R5G5B5(curColor[0], PIXAVG_R5G5B5(curColor[1], PIXAVG_R5G5B5(curColor[2], PIXAVG_R5G5B5(curColor[3], curColor[4]))));
}

And that is all there is too it. Hopefully this becomes of use to others as it has been for me.

PS. I have tried applying it to NDSSFC emulator, but the performance hit of looping through each pixel is too high to bother adding this smoothing functionality to.
 
  • Like
Reactions: Margen67

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
  • K3Nv2 @ K3Nv2:
    Looks like you got yellow text on your pants
  • kijetesantakalu042 @ kijetesantakalu042:
    Looks like you got small text in your pants
  • K3Nv2 @ K3Nv2:
    Stop getting hard over text sir
  • kijetesantakalu042 @ kijetesantakalu042:
    Miku irl:
    lOl
    l
    0l
  • JollyBaker @ JollyBaker:
    Guys, is this picture of my, uhhh, I think they call it a waifu(?), suitable for the conscientious objector in tf2 (the sign melee)?
    erect-jpg.474368
  • LightyKD @ LightyKD:
    Hopefully the admins have noticed the Trading section.
  • lwiz @ lwiz:
    ...or soon seven pages of recent "quality" postings. From someone claiming to be 39 o.O
  • LightyKD @ LightyKD:
    NVM it's worse than I thought 🤦🏾‍♂️
  • Crass @ Crass:
    WTF is going on, who
    is @yaykittykitty
  • LightyKD @ LightyKD:
    My phone went crazy while the site was being attacked.
  • lwiz @ lwiz:
    Earlyish Euro morning tends to be slower in staff responses - usually the time when I see spammers getting through to site as well. This time "spammer" has been member for a while
  • Sicklyboy @ Sicklyboy:
    Yeah I'm working on it
  • Sicklyboy @ Sicklyboy:
    There is so fucking much to clean up from this motherfucker
  • Sicklyboy @ Sicklyboy:
    Sigh. Should all be cleaned up now. If there's anything I missed please report it and someone will grab it once they see it
  • lwiz @ lwiz:
    cheers!
    +1
  • Sicklyboy @ Sicklyboy:
    Just gonna keep on drinking my tequila spiked apple cider now lol
    +1
  • Sicklyboy @ Sicklyboy:
    @K3Nv2, intrigued, until he added the wine 🤢
  • K3Nv2 @ K3Nv2:
    Not ghetto enough to pour out the 40
  • Sicklyboy @ Sicklyboy:
    man now I have to keep refreshing the homepage because I'm expecting this dickhead to make an alt
    Sicklyboy @ Sicklyboy: man now I have to keep refreshing the homepage because I'm expecting this dickhead to make an alt