Revision 5f23fb0b6e1d50d996ac54daaa7e637e5d8decaf authored by Software Heritage on 05 May 2020, 00:00:00 UTC, committed by Software Heritage on 27 June 2020, 00:00:00 UTC
0 parent
Raw File
bilinear_interpolation.c
/*
* bilinear_interpolation.c
*
* Copyright (C) 2019, Enric Meinhardt-Llopis, CMLA, ÉNS Paris-Saclay.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

static inline
float evaluate_bilinear_cell(float a, float b, float c, float d,
                             float x, float y)
{
    float r = 0;
    r += a * (1-x) * (1-y);
    r += b * ( x ) * (1-y);
    r += c * (1-x) * ( y );
    r += d * ( x ) * ( y );
    return r;
}

static inline
float getsamplec(float *fx, int w, int h, int pd, int i, int j, int l)
{
    if (i < 0) i = 0;
    if (j < 0) j = 0;
    if (l < 0) l = 0;
    if (i >= w) i = w-1;
    if (j >= h) j = h-1;
    if (l >= pd) l = pd-1;

    return fx[(i+j*w)*pd + l];
}

static inline
void bilinear_interpolation_vec_at(float *result,
                                   float *x, int w, int h, int pd,
                                   float p, float q)
{
    int ip = p;
    int iq = q;
    for (int l = 0; l < pd; l++)
    {
        float a = getsamplec(x, w, h, pd, ip, iq, l);
        float b = getsamplec(x, w, h, pd, ip+1, iq, l);
        float c = getsamplec(x, w, h, pd, ip, iq+1, l);
        float d = getsamplec(x, w, h, pd, ip+1, iq+1, l);
        float r = evaluate_bilinear_cell(a, b, c, d, p-ip, q-iq);
        result[l] = r;
    }
}

void
bilinear_interpolant_vec(float *y, int yw, int yh, float *x, int xw, int xh, int pd)
{
    float wfactor = xw/(float)yw;
    float hfactor = xh/(float)yh;
    for (int j = 0; j < yh; j++)
        for (int i = 0; i < yw; i++)
        {
            float p = i*wfactor;
            float q = j*hfactor;

            bilinear_interpolation_vec_at(y + (j*yw+i)*pd, x, xw, xh, pd, p, q);
        }
}
back to top