Linear Methods for Image Interpolation
lkernels.c
Go to the documentation of this file.
00001 
00016 #include <math.h>
00017 #include <string.h>
00018 #include "lkernels.h"
00019 
00020 #ifndef M_PI
00021 
00022 #define M_PI    3.14159265358979323846264338327950288
00023 #endif
00024 
00026 #define NUMEL(x)    (sizeof(x)/sizeof(*(x)))
00027 
00028 
00034 float NearestNeighborKernel(float x)
00035 {
00036     if(-0.5f <= x && x < 0.5f)
00037         return 1;
00038     else
00039         return 0;
00040 }
00041 
00042 
00044 static float BilinearKernel(float x)
00045 {
00046     x = fabs(x);
00047 
00048     if(x < 1)
00049         return 1 - x;
00050     else
00051         return 0;
00052 }
00053 
00054 
00056 static float BicubicKernel(float x)
00057 {
00058     const float alpha = -0.5f;
00059 
00060     x = fabs(x);
00061 
00062     if(x < 2)
00063     {
00064         if(x <= 1)
00065             return ((alpha + 2)*x - (alpha + 3))*x*x + 1;
00066         else
00067             return ((alpha*x - 5*alpha)*x + 8*alpha)*x - 4*alpha;
00068     }
00069     else
00070         return 0;
00071 }
00072 
00073 
00075 static float Lanczos2Kernel(float x)
00076 {
00077     if(-2 < x && x < 2)
00078     {
00079         if(x != 0)
00080             return sin(M_PI*x)*sin((M_PI/2)*x) / ((M_PI*M_PI/2)*x*x);
00081         else
00082             return 1;
00083     }
00084     else
00085         return 0;
00086 }
00087 
00088 
00090 static float Lanczos3Kernel(float x)
00091 {
00092     if(-3 < x && x < 3)
00093     {
00094         if(x != 0)
00095             return sin(M_PI*x)*sin((M_PI/3)*x) / ((M_PI*M_PI/3)*x*x);
00096         else
00097             return 1;
00098     }
00099     else
00100         return 0;
00101 }
00102 
00103 
00105 static float Lanczos4Kernel(float x)
00106 {
00107     if(-4 < x && x < 4)
00108     {
00109         if(x != 0)
00110             return sin(M_PI*x)*sin((M_PI/4)*x) / ((M_PI*M_PI/4)*x*x);
00111         else
00112             return 1;
00113     }
00114     else
00115         return 0;
00116 }
00117 
00118 
00120 static const float BSpline2Prefilter[1] =
00121     {-1.715728752538099e-1}; /* exact value: -3 + sqrt(8) */
00122 
00124 static float BSpline2Kernel(float x)
00125 {
00126     x = fabs(x);
00127 
00128     if(x <= 0.5f)
00129         return 0.75f - x*x;
00130     else if(x < 1.5f)
00131     {
00132         x = 1.5f - x;
00133         return x*x/2;
00134     }
00135     else
00136         return 0;
00137 }
00138 
00139 
00141 static float Schaum2Kernel(float x)
00142 {
00143     x = fabs(x);
00144 
00145     /* This kernel is discontinuous.  At discontinuous points, it takes the
00146     average value of the left and right limits. */
00147     if(x < 0.5f)
00148         return 1 - x*x;
00149     else if(x == 0.5f)
00150         return 0.5625;
00151     else if(x < 1.5f)
00152         return (x - 3)*x/2 + 1;
00153     else if(x == 1.5f)
00154         return -0.0625;
00155     else
00156         return 0;
00157 }
00158 
00159 
00161 static float Schaum3Kernel(float x)
00162 {
00163     x = fabs(x);
00164 
00165     if(x <= 1)
00166         return ((x - 2)*x - 1)*x/2 + 1;
00167     else if(x < 2)
00168         return ((-x + 6)*x - 11)*x/6 + 1;
00169     else
00170         return 0;
00171 }
00172 
00173 
00174 
00176 static const float BSpline3Prefilter[1] =
00177     {-2.679491924311227e-1}; /* exact value: -2 + sqrt(3) */
00178 
00180 static float BSpline3Kernel(float x)
00181 {
00182     x = fabs(x);
00183 
00184     if(x < 1)
00185         return (x/2 - 1)*x*x + 0.66666666666666667f;
00186     else if(x < 2)
00187     {
00188         x = 2 - x;
00189         return x*x*x/6;
00190     }
00191     else
00192         return 0;
00193 }
00194 
00195 
00197 static const float BSpline5Prefilter[2] =
00198     {-4.309628820326465e-2, /* exact: sqrt(13*sqrt(105)+135)/sqrt(2)-sqrt(105)/2-13/2.0 */
00199     -4.305753470999738e-1}; /* exact: sqrt(105)/2+sqrt(135-13*sqrt(105))/sqrt(2)-13/2.0 */
00200 
00202 static float BSpline5Kernel(float x)
00203 {
00204     x = fabs(x);
00205 
00206     if(x <= 1)
00207     {
00208         float xSqr = x*x;
00209         return (((-10*x + 30)*xSqr - 60)*xSqr + 66) / 120;
00210     }
00211     else if(x < 2)
00212     {
00213         x = 2 - x;
00214         return (1 + (5 + (10 + (10 + (5 - 5*x)*x)*x)*x)*x) / 120;
00215     }
00216     else if(x < 3)
00217     {
00218         float xSqr;
00219         x = 3 - x;
00220         xSqr = x*x;
00221         return xSqr*xSqr*x / 120;
00222     }
00223     else
00224         return 0;
00225 }
00226 
00227 
00229 static const float BSpline7Prefilter[3] =
00230     {-9.148694809608277e-3, -1.225546151923267e-1, -5.352804307964382e-1};
00231 
00233 static float BSpline7Kernel(float x)
00234 {
00235     x = fabs(x);
00236 
00237     if(x <= 1)
00238     {
00239         float xSqr = x*x;
00240         return ((((35*x - 140)*xSqr + 560)*xSqr - 1680)*xSqr + 2416) / 5040;
00241     }
00242     else if(x <= 2)
00243     {
00244         x = 2 - x;
00245         return (120 + (392 + (504 + (280 + (-84 + (-42 +
00246             21*x)*x)*x*x)*x)*x)*x) / 5040;
00247     }
00248     else if(x < 3)
00249     {
00250         x = 3 - x;
00251         return (((((((-7*x + 7)*x + 21)*x + 35)*x + 35)*x
00252             + 21)*x + 7)*x + 1) / 5040;
00253     }
00254     else if(x < 4)
00255     {
00256         float xSqr;
00257         x = 4 - x;
00258         xSqr = x*x;
00259         return xSqr*xSqr*xSqr*x / 5040;
00260     }
00261     else
00262         return 0;
00263 }
00264 
00265 
00267 static const float BSpline9Prefilter[4] =
00268     {-2.121306903180818e-3, -4.322260854048175e-2,
00269     -2.017505201931532e-1, -6.079973891686259e-1};
00270 
00272 static float BSpline9Kernel(float x)
00273 {
00274     x = fabs(x);
00275 
00276     if(x <= 1)
00277     {
00278         float xSqr = x*x;
00279         return (((((-63*x + 315)*xSqr - 2100)*xSqr + 11970)*xSqr
00280             - 44100)*xSqr + 78095) / 181440;
00281     }
00282     else if(x <= 2)
00283     {
00284         x = 2 - x;
00285         return (14608 + (36414 + (34272 + (11256 + (-4032 + (-4284 + (-672
00286             + (504 + (252 - 84*x)*x)*x)*x)*x)*x)*x)*x)*x) / 362880;
00287     }
00288     else if(x <= 3)
00289     {
00290         x = 3 - x;
00291         return (502 + (2214 + (4248 + (4536 + (2772 + (756 + (-168 + (-216
00292             + (-72 + 36*x)*x)*x)*x)*x)*x)*x)*x)*x) / 362880;
00293     }
00294     else if(x < 4)
00295     {
00296         x = 4 - x;
00297         return (1 + (9 + (36 + (84 + (126 + (126 + (84 + (36 + (9
00298             - 9*x)*x)*x)*x)*x)*x)*x)*x)*x) / 362880;
00299     }
00300     else if(x < 5)
00301     {
00302         float xCube;
00303         x = 5 - x;
00304         xCube = x*x*x;
00305         return xCube*xCube*xCube / 362880;
00306     }
00307     else
00308         return 0;
00309 }
00310 
00311 
00313 static const float BSpline11Prefilter[5] =
00314     {-5.105575344465021e-4, -1.666962736623466e-2, -8.975959979371331e-2,
00315     -2.721803492947859e-1, -6.612660689007345e-1};
00316 
00318 static float BSpline11Kernel(float x)
00319 {
00320     x = fabs(x);
00321 
00322     if(x <= 1)
00323     {
00324         float xSqr = x*x;
00325         return (15724248 + (-7475160 + (1718640 + (-255024 + (27720
00326             + (-2772 + 462*x)*xSqr)*xSqr)*xSqr)*xSqr)*xSqr) / 39916800;
00327     }
00328     else if(x <= 2)
00329     {
00330         x = 2 - x;
00331         return (2203488 + (4480872 + (3273600 + (574200 + (-538560
00332             + (-299376 + (39600 + (7920 + (-2640 + (-1320
00333             + 330*x)*x)*x)*x)*x*x)*x)*x)*x)*x)*x) / 39916800;
00334     }
00335     else if(x <= 3)
00336     {
00337         x = 3 - x;
00338         return (152637 + (515097 + (748275 + (586575 + (236610 + (12474
00339             + (-34650 + (-14850 + (-495 + (1485
00340             + (495-165*x)*x)*x)*x)*x)*x)*x)*x)*x)*x)*x) / 39916800;
00341     }
00342     else if(x < 4)
00343     {
00344         x = 4 - x;
00345         return (2036 + (11132 + (27500 + (40260 + (38280 + (24024 + (9240
00346             + (1320 + (-660 + (-440 + (-110
00347             + 55*x)*x)*x)*x)*x)*x)*x)*x)*x)*x)*x) / 39916800;
00348     }
00349     else if(x < 5)
00350     {
00351         x = 5 - x;
00352         return (1 + (11 + (55 + (165 + (330 + (462 + (462 + (330 + (165
00353             + (55 + (11 - 11*x)*x)*x)*x)*x)*x)*x)*x)*x)*x)*x) / 39916800;
00354     }
00355     else if(x < 6)
00356     {
00357         float xSqr, xPow4;
00358         x = 6 - x;
00359         xSqr = x*x;
00360         xPow4 = xSqr*xSqr;
00361         return xPow4*xPow4*xSqr*x / 39916800;
00362     }
00363     else
00364         return 0;
00365 }
00366 
00367 
00369 static const float OMoms3Prefilter[1] =
00370     {-3.441311542550502e-1}; /* exact: (sqrt(105) - 13)/8 */
00371 
00373 static float OMoms3Kernel(float x)
00374 {
00375     x = fabs(x);
00376 
00377     if(x < 1)
00378         return ((x/2 - 1)*x + 1/14.0f)*x + 13/21.0f;
00379     else if(x < 2)
00380         return ((-x/6 + 1)*x - 85/42.0f)*x + 29/21.0f;
00381     else
00382         return 0;
00383 }
00384 
00385 
00387 static const float OMoms5Prefilter[2] =
00388     {-7.092571896868541e-2, -4.758127100084396e-1};
00389 
00391 static float OMoms5Kernel(float x)
00392 {
00393     x = fabs(x);
00394 
00395     if(x <= 1)
00396         return (((((-10*x + 30)*x - (200/33.0f))*x
00397             - (540/11.0f))*x - (5/33.0f))*x + (687/11.0)) / 120;
00398     else if(x < 2)
00399         return (((((330*x - 2970)*x + 10100)*x
00400             - 14940)*x + 6755)*x + 2517)/7920;
00401     else if(x < 3)
00402     {
00403         float xSqr;
00404         x = 3 - x;
00405         xSqr = x*x;
00406         return ((xSqr + (20/33.0f))*xSqr + (1/66.0f))*x / 120;
00407     }
00408     else
00409         return 0;
00410 }
00411 
00413 static const float OMoms7Prefilter[3] =
00414     {-1.976842538386140e-2, -1.557007746773578e-1, -5.685376180022930e-1};
00415 
00417 static float OMoms7Kernel(float x)
00418 {
00419     x = fabs(x);
00420 
00421     if(x <= 1)
00422         return (((((((15015*x - 60060)*x + 21021)*x + 180180)*x + 2695)*x
00423             - 629244)*x + 21)*x + 989636) / 2162160;
00424     else if(x <= 2)
00425     {
00426         x = 2 - x;
00427         return (x*(x*(x*(x*(x*(x*(5005*x - 10010) - 13013) - 10010) + 54285)
00428             + 119350) + 106267) + 36606) / 1201200;
00429     }
00430     else if(x <= 3)
00431     {
00432         x = 3 - x;
00433         return (x*(x*(x*(x*(x*(x*(-15015*x + 15015) + 24024) + 90090)
00434             + 102410) + 76230) + 31164) + 5536) / 10810800;
00435     }
00436     else if(x < 4)
00437     {
00438         float xSqr;
00439         x = 4 - x;
00440         xSqr = x*x;
00441         return (x*(xSqr*(xSqr*(2145*xSqr + 3003) + 385) + 3)) / 10810800;
00442     }
00443     else
00444         return 0;
00445 }
00446 
00447 
00449 static interpmethod InterpMethodTable[] =
00450     {{"nearest", NearestNeighborKernel, 0.51f, 0, 0, 0, 1},
00451     {"bilinear", BilinearKernel, 1, 0, 0, 0, 1},
00452     {"bicubic", BicubicKernel, 2, 0, 0, 0, 1},
00453     {"lanczos2", Lanczos2Kernel, 2, 1, 0, 0, 1},
00454     {"lanczos3", Lanczos3Kernel, 3, 1, 0, 0, 1},
00455     {"lanczos4", Lanczos4Kernel, 4, 1, 0, 0, 1},
00456     {"schaum2", Schaum2Kernel, 1.51f, 0, 0, 0, 1},
00457     {"schaum3", Schaum3Kernel, 2, 0, 0, 0, 1},
00458     {"bspline2", BSpline2Kernel, 1.5f, 0,
00459         NUMEL(BSpline2Prefilter), BSpline2Prefilter, 8},
00460     {"bspline3", BSpline3Kernel, 2, 0,
00461         NUMEL(BSpline3Prefilter), BSpline3Prefilter, 6},
00462     {"bspline5", BSpline5Kernel, 3, 0,
00463         NUMEL(BSpline5Prefilter), BSpline5Prefilter, 120},
00464     {"bspline7", BSpline7Kernel, 4, 0,
00465         NUMEL(BSpline7Prefilter), BSpline7Prefilter, 5040},
00466     {"bspline9", BSpline9Kernel, 5, 0,
00467         NUMEL(BSpline9Prefilter), BSpline9Prefilter, 362880},
00468     {"bspline11", BSpline11Kernel, 6, 0,
00469         NUMEL(BSpline11Prefilter), BSpline11Prefilter, 39916800},
00470     {"omoms3", OMoms3Kernel, 2, 0,
00471         NUMEL(OMoms3Prefilter), OMoms3Prefilter, 21/4.0f},
00472     {"omoms5", OMoms5Kernel, 3, 0,
00473         NUMEL(OMoms5Prefilter), OMoms5Prefilter, 7920/107.0f},
00474     {"omoms7", OMoms7Kernel, 4, 0,
00475         NUMEL(OMoms7Prefilter), OMoms7Prefilter, 675675/346.0f}};
00476 
00477 
00492 interpmethod *GetInterpMethod(const char *Name)
00493 {
00494     int i;
00495 
00496     for(i = 0; i < (int)NUMEL(InterpMethodTable); i++)
00497         if(!strcmp(InterpMethodTable[i].Name, Name))
00498             return &InterpMethodTable[i];
00499 
00500     return 0;
00501 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines