001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 *  image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause 
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 
006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009
010package imagingbook.lib.interpolation;
011
012import imagingbook.lib.image.ImageAccessor;
013
014public class BicubicInterpolator extends PixelInterpolator {
015        
016        private final double a;         // sharpness value
017        
018        public BicubicInterpolator() {
019                this(0.5);
020        }
021        
022        public BicubicInterpolator(double a) {
023                this.a = a;
024        }
025        
026        @Override
027        public float getInterpolatedValue(ImageAccessor.Scalar ia, double x, double y) {
028                final int u0 = (int) Math.floor(x);     //use floor to handle negative coordinates too
029                final int v0 = (int) Math.floor(y);
030                double q = 0;
031                for (int j = 0; j <= 3; j++) {
032                        int v = v0 - 1 + j;
033                        double p = 0;
034                        for (int i = 0; i <= 3; i++) {
035                                int u = u0 - 1 + i;
036                                float pixval = ia.getVal(u, v); 
037                                p = p + pixval * w_cub(x - u, a);
038                        }
039                        q = q + p * w_cub(y - v, a);
040                }
041                return (float) q;
042        }
043        
044        private final double w_cub(double x, double a) {
045                if (x < 0)
046                        x = -x;
047                double z = 0;
048                if (x < 1)
049                        z = (-a + 2) * x * x * x + (a - 3) * x * x + 1;
050                else if (x < 2)
051                        z = -a * x * x * x + 5 * a * x * x - 8 * a * x + 4 * a;
052                return z;
053        }
054
055
056}