Skip to main content
gamedev.net
🔒 Locked

Image interpolation algorithms

Started by alexandro_81 6 replies 1k views
Original Post
alexandro_81
alexandro_81
Hello everybody, I'm searching the web to find the various classic algorithms in the form of pseudocode, for image scaling. I'm searching for: - nearest neighbor - linear interpolation - cubic interpolation - spline interpolation I didn't find anything useful... does anyone have these algorithms? It is very important for me... Thanks to everyone reply to this post, Alessandro
bluntman
bluntman
Well I'll have ago seeing as no one else is! Heres my code to get an interpolated pixel value from an image:
<TYPE> Image::Interpolate(float x, float y){    // linear interpolation    <TYPE> col;    int base_x, base_y;    float dx, dy, value;    base_x = (int)floor(x);    base_y = (int)floor(y);    if(base_x < 0 || base_y < 0 || base_x+1 >= m_Width || base_y+1 >= m_Height)        return(0.0f);    dx = x - base_x;    dy = y - base_y;    col = ((1-dx) * (1-dy) * (float)m_Image[base_y][base_x] +        (1-dx) * (dy) * (float)m_Image[base_y+1][base_x] +        (dx) * (1-dy) * (float)m_Image[base_y][base_x+1] +        (dx) * (dy) * (float)m_Image[base_y + 1][base_x + 1]);    return col;}


Heres the code for the resizing (I use FreeImage myself, so this code is off the top of my head):

void Image::Resize(int newwid, int newhgt, Image &dest){    int x, y;    float x2, y2, dx, dy;        dx = m_nWidth / newwid;    dy = m_nHeight / newhgt;    for(y=0, y2=0; y<newhgt; y++, y2+=dy)    {        for(x=0, x2=0; x<newwid; x++, x2+=dx)        {             dest.m_Image[y][x] = Interpolate(x2, y2);        }    }}


I am pretty sure this is NOT optimal for image minification (because source pixels will be skipped, instead of averaged), but should be good for magnification. Maybe this will give you a good start though.
To change the interpolation type just adjust the Interpolate() function. I think bicubic uses a 16 pixel sampling area, linear a 4 pixel one (like the current function). Not sure about spline interpolation, but hermite code is pretty easy to find.
HTH
alexandro_81
alexandro_81
Thanks... I appreciate very much your replies... The network is a great place where "live" smart and kind people... Bye!
Extrarius
Extrarius
For downscaling to a factor of 50% or less, the best algorithm IME is a box averaging filter - you just average all the filters in a M*N box where M is the factor of vertical reduction and N is the horizontal. For example, to reduce an image to 1/3 of it's original size, you just average the pixels in a 3x3 box for each pixel in the smaller image.
For factors between 100% and 50%, other algorithms will sometimes produce better results.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
haegarr
haegarr
From a technical point of view, scaling an image is a process of a 2D re-sampling. If zooming in, you want to do a net "super-sampling" (or "up sampling"), else a net "sub-sampling" (or "down sampling"). I said "net" here since mixed forms may be used for fractional scale factors.

You may try to search for these terms in the internet. In all cases there is the need of filtering, e.g. to avoid alias in the case of sub-sampling, to do it right. Which filter to use is just a question of quality you want to yield. E.g. the mentioned interpolators named in the original post by alexandro_81 are in fact such filters.

For very high quality scale ups (or very high scale factors), methods exist that perform some feature recognition and enhancement, e.g. sharpening of edges. But may be such things are out of range of what you want.
alexandro_81
alexandro_81
Again on bicubic interpolation...

I found this Delphi-like procedure:

Function Bicubic ( x,y: real) : byte
var j,k: integer;
var a,b: real;
var dest: real;
var ti,t2,t3,t4: real;

Begin
j := round(x);
k := round(y);

a := x - j;
b := y - k;

t1 := -a* (1-a)*Pixel[j-1,k-1]+
(1-2*a*a+a*a*a)* Pixel[j,k-1] +
a*(1+a-a*a)*Pixel[j+1,k-1] -
a*a*(1-a)*Pixel[j+2,k-1]

t2 := -a* (1-a)*Pixel[j-1,k]+
(1-2*a*a+a*a*a)* Pixel[j,k] +
a*(1+a-a*a)*Pixel[j+1,k] -
a*a*(1-a)*Pixel[j+2,k]

t3 := -a* (1-a)*Pixel[j-1,k+1]+
(1-2*a*a+a*a*a)* Pixel[j,k+1] +
a*(1+a-a*a)*Pixel[j+1,k+1] -
a*a*(1-a)*Pixel[j+2,k+1]

t4 := -a* (1-a)*Pixel[j-1,k+2]+
(1-2*a*a+a*a*a)* Pixel[j,k+2] +
a*(1+a-a*a)*Pixel[j+1,k+2] -
a*a*(1-a)*Pixel[j+2,k+2]

pixel := -b* (1-b)*t1 +
(1-2*b*b+b*b*b)* t2 +
b*(1+b-b*b)* t3 -
b*b*(1-b)*t4
end


I can't why the weights of the average are calculated in that way? does anybody know it?
Emmanuel Deloget
Emmanuel Deloget
Hello,
Since you are interested in the subject: Aramini's paper is one of the simpler bicubic resampling algorithm I found on the net (mostly because it cut the problem in smaller pieces using bicbic splines, and because the math is simple enough :D). The code is somewhat simple to write, and it can be easily (and heavily) optimized.

HTH,

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.