//interp.c
/*
* Copyright (C) 2010 Marko Cebokli http://lea.hamradio.si/~s57uuu
* This file is a part of the Frei0r plugin "defish0r"
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*******************************************************************
* The remapping functions use a map array, which contains a pair
* of floating values of each pixel of the output image. These
* represent the location in the input image, from where the value
* of the given output pixel should be interpolated.
* They are given in pixels of the input image.
* If the output image is wo pixels wide, then the x coordinate
* of the pixel in row r and column c is at 2*(r*wo+c) in the map
* array, and y at 2*(r*wo+c)+1
*
* The map array is usually computation intensive to generate, and
* he purpose of the map array is to allow fast remapping of
* several images (video) using the same map array.
******************************************************************/
//compile: gcc -c -O2 -Wall -std=c99 -fPIC interp.c -o interp.o
// -std=c99 za roundf()
// -fPIC da lahko linkas v .so (za frei0r)
#include <math.h>
#include <stdio.h> /* za debug printoute */
#include <inttypes.h>
//--------------------------------------------------------
//pointer to an interpolating function
typedef int (*interpp)(unsigned char*, int, int, float, float, unsigned char*);
//************************************
//REMAP AN IMAGE
//--------------------------------------------------------
// vhs = vhodna slika velikosti wi x hi
// izs = izhodna slika velikosti wo x ho
// map = za vsak pixel izs pove, kje ga vzamemo is vhs
// bgc = background color
// interp = kazalec na interpolacijsko funkcijo
void remap(int wi, int hi, int wo, int ho, unsigned char *vhs, unsigned char *izs, float *map, unsigned char bgc, interpp interp)
{
int i,j;
float x,y;
for (i=0;i<ho;i++)
for (j=0;j<wo;j++)
{
x=map[2*(wo*i+j)];
y=map[2*(wo*i+j)+1];
if (x>0)
interp(vhs,wi,hi,x,y,&izs[wo*i+j]);
else
izs[wo*i+j]=bgc; //background fill
}
}
//--------------------------------------------------------
//for four byte (int, 32 bit) values (packed RGB color)
//little endian !!
// vhs = vhodna slika velikosti wi x hi
// izs = izhodna slika velikosti wo x ho
// map = za vsak pixel izs pove, kje ga vzamemo is vhs
// bgc = background color
// interp = kazalec na interpolacijsko funkcijo
void remap32(int wi, int hi, int wo, int ho, unsigned char *vhs, unsigned char *izs, float *map, uint32_t bgc, interpp interp)
{
int i,j;
float x,y;
for (i=0;i<ho;i++)
for (j=0;j<wo;j++)
{
x=map[2*(wo*i+j)];
y=map[2*(wo*i+j)+1];
if (x>0)
interp(vhs,wi,hi,x,y,&izs[4*(wo*i+j)]);
else //background fill
{
izs[4*(wo*i+j)]=bgc;
izs[4*(wo*i+j)+1]=bgc>>8;
izs[4*(wo*i+j)+2]=bgc>>16;
izs[4*(wo*i+j)+3]=bgc>>24;
}
}
}
//**************************************
//HERE BEGIN THE INTERPOLATION FUNCTIONS
#if defined(_MSC_VER) && _MSC_VER < 1800
__inline const float roundf(float x){
return (int)floor(x+0.5);
}
#endif /* _MSC_VER */
//------------------------------------------------------
//za debugging - z izpisovanjem
//interpolacija "najblizji sosed" (ni prava interpolacija)
//za byte (char) vrednosti
// *sl vhodni array (slika)
// w,h dimenzija slike je wxh
// x,y tocka, za katero izracuna interpolirano vrednost
// *v interpolirana vrednost
int interpNNpr_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
//printf("u=%5.2f v=%5.2f ",x,y);
printf("u=%5.3f v=%5.3f ",x/(w-1),y/(h-1));
//printf("U=%2d V=%2d ",(int)roundf(x),(int)roundf(y));
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
*v=sl[(int)roundf(x)+(int)roundf(y)*w];
return 0;
}
//------------------------------------------------------
//interpolacija "najblizji sosed" (ni prava interpolacija)
//za byte (char) vrednosti
// *sl vhodni array (slika)
// w,h dimenzija slike je wxh
// x,y tocka, za katero izracuna interpolirano vrednost
// *v interpolirana vrednost
int interpNN_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
*v=sl[(int)roundf(x)+(int)roundf(y)*w];
return 0;
}
//------------------------------------------------------
//interpolacija "najblizji sosed" (ni prava interpolacija)
//za byte (char) vrednosti v packed color 32 bitnem formatu
//little endian !!
// *sl vhodni array (slika)
// w,h dimenzija slike je wxh
// x,y tocka, za katero izracuna interpolirano vrednost
// *v interpolirana vrednost
int interpNN_b32(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
//int index = (int)(x+0.5f)*4+(int)(y+0.5f)*4*w; //fast rounding
int index = (int)roundf(x)*4+(int)roundf(y)*4*w; //call once
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
v[0]=sl[index];
v[1]=sl[index+1];
v[2]=sl[index+2];
v[3]=sl[index+3];
return 0;
}
//------------------------------------------------------
//bilinearna interpolacija
//za byte (char) vrednosti
// *sl vhodni array (slika)
// w,h dimenzija slike je wxh
// x,y tocka, za katero izracuna interpolirano vrednost
// *v interpolirana vrednost
int interpBL_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int m,n,k,l;
float a,b;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)floorf(x); n=(int)floorf(y);
k=n*w+m; l=(n+1)*w+m;
a=sl[k]+(sl[k+1]-sl[k])*(x-(float)m);
b=sl[l]+(sl[l+1]-sl[l])*(x-(float)m);
*v=a+(b-a)*(y-(float)n);
return 0;
}
//------------------------------------------------------
//bilinearna interpolacija
//za byte (char) vrednosti v packed color 32 bitnem formatu
int interpBL_b32(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int m,n,k,l,n1,l1,k1;
float a,b;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)floorf(x); n=(int)floorf(y);
k=n*w+m; l=(n+1)*w+m;
k1=4*(k+1); l1=4*(l+1); n1=4*((n+1)*w+m);
l=4*l; k=4*k;
a=sl[k]+(sl[k1]-sl[k])*(x-(float)m);
b=sl[l]+(sl[l1]-sl[n1])*(x-(float)m);
v[0]=a+(b-a)*(y-(float)n);
a=sl[k+1]+(sl[k1+1]-sl[k+1])*(x-(float)m);
b=sl[l+1]+(sl[l1+1]-sl[n1+1])*(x-(float)m);
v[1]=a+(b-a)*(y-(float)n);
a=sl[k+2]+(sl[k1+2]-sl[k+2])*(x-(float)m);
b=sl[l+2]+(sl[l1+2]-sl[n1+2])*(x-(float)m);
v[2]=a+(b-a)*(y-(float)n);
a=sl[k+3]+(sl[k1+3]-sl[k+3])*(x-(float)m);
b=sl[l+3]+(sl[l1+3]-sl[n1+3])*(x-(float)m);
v[3]=a+(b-a)*(y-(float)n);
return 0;
}
//------------------------------------------------------
//bikubicna interpolacija "smooth"
//za byte (char) vrednosti
//kar Aitken-Neville formula iz Bronstajna
// *sl vhodni array (slika)
// w,h dimenzija slike je wxh
// x,y tocka, za katero izracuna interpolirano vrednost
// *v interpolirana vrednost
int interpBC_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int i,j,l,m,n;
float k;
float p[4],p1[4],p2[4],p3[4],p4[4];
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
n=(int)ceilf(y)-2; if (n<0) n=0; if ((n+5)>h) n=h-4;
//njaprej po y (stiri stolpce)
for (i=0;i<4;i++)
{
l=m+(i+n)*w;
p1[i]=sl[l];
p2[i]=sl[l+1];
p3[i]=sl[l+2];
p4[i]=sl[l+3];
}
for (j=1;j<4;j++)
for (i=3;i>=j;i--)
{
k=(y-i-n)/j;
p1[i]=p1[i]+k*(p1[i]-p1[i-1]);
p2[i]=p2[i]+k*(p2[i]-p2[i-1]);
p3[i]=p3[i]+k*(p3[i]-p3[i-1]);
p4[i]=p4[i]+k*(p4[i]-p4[i-1]);
}
//zdaj pa po x
p[0]=p1[3]; p[1]=p2[3]; p[2]=p3[3]; p[3]=p4[3];
for (j=1;j<4;j++)
for (i=3;i>=j;i--)
p[i]=p[i]+(x-i-m)/j*(p[i]-p[i-1]);
if (p[3]<0.0) p[3]=0.0; //printf("p=%f ",p[3]);
if (p[3]>256.0) p[3]=255.0; //printf("p=%f ",p[3]);
*v=p[3];
return 0;
}
//------------------------------------------------------
//bikubicna interpolacija "smooth"
//za byte (char) vrednosti v packed color 32 bitnem formatu
int interpBC_b32(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int i,j,b,l,m,n;
float k;
float p[4],p1[4],p2[4],p3[4],p4[4];
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
n=(int)ceilf(y)-2; if (n<0) n=0; if ((n+5)>h) n=h-4;
for (b=0;b<4;b++)
{
//njaprej po y (stiri stolpce)
for (i=0;i<4;i++)
{
l=m+(i+n)*w;
p1[i]=sl[4*l+b];
p2[i]=sl[4*(l+1)+b];
p3[i]=sl[4*(l+2)+b];
p4[i]=sl[4*(l+3)+b];
}
for (j=1;j<4;j++)
for (i=3;i>=j;i--)
{
k=(y-i-n)/j;
p1[i]=p1[i]+k*(p1[i]-p1[i-1]);
p2[i]=p2[i]+k*(p2[i]-p2[i-1]);
p3[i]=p3[i]+k*(p3[i]-p3[i-1]);
p4[i]=p4[i]+k*(p4[i]-p4[i-1]);
}
//zdaj pa po x
p[0]=p1[3]; p[1]=p2[3]; p[2]=p3[3]; p[3]=p4[3];
for (j=1;j<4;j++)
for (i=3;i>=j;i--)
p[i]=p[i]+(x-i-m)/j*(p[i]-p[i-1]);
if (p[3]<0.0) p[3]=0.0;
if (p[3]>256.0) p[3]=255.0;
v[b]=p[3];
}
return 0;
}
//------------------------------------------------------
//bikubicna interpolacija "sharp"
//za byte (char) vrednosti
//Helmut Dersch polinom
// *sl vhodni array (slika)
// w,h dimenzija slike je wxh
// x,y tocka, za katero izracuna interpolirano vrednost
// *v interpolirana vrednost
//!!! ODKOD SUM??? (ze po eni rotaciji v interp_test !!)
//!!! v defish tega suma ni???
int interpBC2_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int i,k,l,m,n;
float pp,p[4],wx[4],wy[4],xx;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
n=(int)ceilf(y)-2; if (n<0) n=0; if ((n+5)>h) n=h-4;
//najprej po y (stiri stolpce)
xx=y-n; wy[0]=(-0.75*(xx-5.0)*xx-6.0)*xx+3.0;
xx=xx-1.0; wy[1]=(1.25*xx-2.25)*xx*xx+1.0;
xx=1.0-xx; wy[2]=(1.25*xx-2.25)*xx*xx+1.0;
xx=xx+1.0; wy[3]=(-0.75*(xx-5.0)*xx-6.0)*xx+3.0;
//se po x
xx=x-m; wx[0]=(-0.75*(xx-5.0)*xx-6.0)*xx+3.0;
xx=xx-1.0; wx[1]=(1.25*xx-2.25)*xx*xx+1.0;
xx=1.0-xx; wx[2]=(1.25*xx-2.25)*xx*xx+1.0;
xx=xx+1.0; wx[3]=(-0.75*(xx-5.0)*xx-6.0)*xx+3.0;
k=n*w+m;
for (i=0;i<4;i++)
{
p[i]=0.0;
l=k+i;
p[i]=wy[0]*sl[l]; l+=w;
p[i]+=wy[1]*sl[l]; l+=w;
p[i]+=wy[2]*sl[l]; l+=w;
p[i]+=wy[3]*sl[l];
}
pp=wx[0]*p[0];
pp+=wx[1]*p[1];
pp+=wx[2]*p[2];
pp+=wx[3]*p[3];
if (pp<0.0) pp=0.0;
if (pp>256.0) pp=255.0;
*v=pp;
return 0;
}
//------------------------------------------------------
//bikubicna interpolacija "sharp"
//za byte (char) vrednosti v packed color 32 bitnem formatu
//!!! ODKOD SUM??? (ze po eni rotaciji v interp_test !!)
//!!! v defish tega suma ni???
int interpBC2_b32(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int b,i,k,l,m,n,u;
float pp,p[4],wx[4],wy[4],xx;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
n=(int)ceilf(y)-2; if (n<0) n=0; if ((n+5)>h) n=h-4;
//najprej po y (stiri stolpce)
xx=y-n; wy[0]=(-0.75*(xx-5.0)*xx-6.0)*xx+3.0;
xx=xx-1.0; wy[1]=(1.25*xx-2.25)*xx*xx+1.0;
xx=1.0-xx; wy[2]=(1.25*xx-2.25)*xx*xx+1.0;
xx=xx+1.0; wy[3]=(-0.75*(xx-5.0)*xx-6.0)*xx+3.0;
//se po x
xx=x-m; wx[0]=(-0.75*(xx-5.0)*xx-6.0)*xx+3.0;
xx=xx-1.0; wx[1]=(1.25*xx-2.25)*xx*xx+1.0;
xx=1.0-xx; wx[2]=(1.25*xx-2.25)*xx*xx+1.0;
xx=xx+1.0; wx[3]=(-0.75*(xx-5.0)*xx-6.0)*xx+3.0;
k=4*(n*w+m); u=4*w;
for (b=0;b<4;b++)
{
for (i=0;i<4;i++)
{
p[i]=0.0;
l=k+4*i;
p[i]=wy[0]*sl[l]; l+=u;
p[i]+=wy[1]*sl[l]; l+=u;
p[i]+=wy[2]*sl[l]; l+=u;
p[i]+=wy[3]*sl[l];
}
k++;
pp=wx[0]*p[0];
pp+=wx[1]*p[1];
pp+=wx[2]*p[2];
pp+=wx[3]*p[3];
if (pp<0.0) pp=0.0;
if (pp>256.0) pp=255.0;
v[b]=pp;
}
return 0;
}
//------------------------------------------------------
//spline 4x4 interpolacija
//za byte (char) vrednosti
//Helmut Dersch polinom
// *sl vhodni array (slika)
// w,h dimenzija slike je wxh
// x,y tocka, za katero izracuna interpolirano vrednost
// *v interpolirana vrednost
int interpSP4_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int i,j,m,n;
float pp,p[4],wx[4],wy[4],xx;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
n=(int)ceilf(y)-2; if (n<0) n=0; if ((n+5)>h) n=h-4;
//najprej po y (stiri stolpce)
xx=y-n; wy[0]=((-0.333333*(xx-1.0)+0.8)*(xx-1.0)-0.466667)*(xx-1.0);
xx=xx-1.0; wy[1]=((xx-1.8)*xx-0.2)*xx+1.0;
xx=1.0-xx; wy[2]=((xx-1.8)*xx-0.2)*xx+1.0;
xx=xx+1.0; wy[3]=((-0.333333*(xx-1.0)+0.8)*(xx-1.0)-0.466667)*(xx-1.0);
//se po x
xx=x-m; wx[0]=((-0.333333*(xx-1.0)+0.8)*(xx-1.0)-0.466667)*(xx-1.0);
xx=xx-1.0; wx[1]=((xx-1.8)*xx-0.2)*xx+1.0;
xx=1.0-xx; wx[2]=((xx-1.8)*xx-0.2)*xx+1.0;
xx=xx+1.0; wx[3]=((-0.333333*(xx-1.0)+0.8)*(xx-1.0)-0.466667)*(xx-1.0);
for (i=0;i<4;i++)
{
p[i]=0.0;
for (j=0;j<4;j++)
{
p[i]=p[i]+wy[j]*sl[(j+n)*w+i+m];
}
}
pp=0.0;
for (i=0;i<4;i++)
pp=pp+wx[i]*p[i];
if (pp<0.0) pp=0.0;
if (pp>256.0) pp=255.0;
*v=pp;
return 0;
}
//------------------------------------------------------
//spline 4x4 interpolacija
//za byte (char) vrednosti v packed color 32 bitnem formatu
int interpSP4_b32(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int i,j,m,n,b;
float pp,p[4],wx[4],wy[4],xx;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
n=(int)ceilf(y)-2; if (n<0) n=0; if ((n+5)>h) n=h-4;
//najprej po y (stiri stolpce)
xx=y-n; wy[0]=((-0.333333*(xx-1.0)+0.8)*(xx-1.0)-0.466667)*(xx-1.0);
xx=xx-1.0; wy[1]=((xx-1.8)*xx-0.2)*xx+1.0;
xx=1.0-xx; wy[2]=((xx-1.8)*xx-0.2)*xx+1.0;
xx=xx+1.0; wy[3]=((-0.333333*(xx-1.0)+0.8)*(xx-1.0)-0.466667)*(xx-1.0);
//se po x
xx=x-m; wx[0]=((-0.333333*(xx-1.0)+0.8)*(xx-1.0)-0.466667)*(xx-1.0);
xx=xx-1.0; wx[1]=((xx-1.8)*xx-0.2)*xx+1.0;
xx=1.0-xx; wx[2]=((xx-1.8)*xx-0.2)*xx+1.0;
xx=xx+1.0; wx[3]=((-0.333333*(xx-1.0)+0.8)*(xx-1.0)-0.466667)*(xx-1.0);
for (b=0;b<4;b++)
{
for (i=0;i<4;i++)
{
p[i]=0.0;
for (j=0;j<4;j++)
{
p[i]=p[i]+wy[j]*sl[4*((j+n)*w+i+m)+b];
}
}
pp=0.0;
for (i=0;i<4;i++)
pp=pp+wx[i]*p[i];
if (pp<0.0) pp=0.0;
if (pp>256.0) pp=255.0;
v[b]=pp;
}
return 0;
}
//------------------------------------------------------
//spline 6x6 interpolacija
//za byte (char) vrednosti
//Helmut Dersch polinom
// *sl vhodni array (slika)
// w,h dimenzija slike je wxh
// x,y tocka, za katero izracuna interpolirano vrednost
// *v interpolirana vrednost
//!!! PAZI, TOLE NE DELA CISTO PRAV ??? belina se siri
//!!! zaenkrat sem dodal fudge factor...
int interpSP6_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int i,j,m,n;
float pp,p[6],wx[6],wy[6],xx;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-3; if (m<0) m=0; if ((m+7)>w) m=w-6;
n=(int)ceilf(y)-3; if (n<0) n=0; if ((n+7)>h) n=h-6;
//najprej po y (sest stolpcev)
xx=y-n;
wy[0]=((0.090909*(xx-2.0)-0.215311)*(xx-2.0)+0.124402)*(xx-2.0);
xx=xx-1.0;
wy[1]=((-0.545455*(xx-1.0)+1.291866)*(xx-1.0)-0.746411)*(xx-1.0);
xx=xx-1.0;
wy[2]=((1.181818*xx-2.167464)*xx+0.014354)*xx+1.0;
xx=1.0-xx;
wy[3]=((1.181818*xx-2.167464)*xx+0.014354)*xx+1.0;
xx=xx+1.0;
wy[4]=((-0.545455*(xx-1.0)+1.291866)*(xx-1.0)-0.746411)*(xx-1.0);
xx=xx+1.0;
wy[5]=((0.090909*(xx-2.0)-0.215311)*(xx-2.0)+0.124402)*(xx-2.0);
//se po x
xx=x-m;
wx[0]=((0.090909*(xx-2.0)-0.215311)*(xx-2.0)+0.124402)*(xx-2.0);
xx=xx-1.0;
wx[1]=((-0.545455*(xx-1.0)+1.291866)*(xx-1.0)-0.746411)*(xx-1.0);
xx=xx-1.0;
wx[2]=((1.181818*xx-2.167464)*xx+0.014354)*xx+1.0;
xx=1.0-xx;
wx[3]=((1.181818*xx-2.167464)*xx+0.014354)*xx+1.0;
xx=xx+1.0;
wx[4]=((-0.545455*(xx-1.0)+1.291866)*(xx-1.0)-0.746411)*(xx-1.0);
xx=xx+1.0;
wx[5]=((0.090909*(xx-2.0)-0.215311)*(xx-2.0)+0.124402)*(xx-2.0);
for (i=0;i<6;i++)
{
p[i]=0.0;
for (j=0;j<6;j++)
{
p[i]=p[i]+wy[j]*sl[(j+n)*w+i+m];
}
}
pp=0.0;
for (i=0;i<6;i++)
pp=pp+wx[i]*p[i];
pp=0.947*pp; //fudge factor...!!! cca 0.947...
if (pp<0.0) pp=0.0;
if (pp>256.0) pp=255.0;
*v=pp;
return 0;
}
//------------------------------------------------------
//spline 6x6 interpolacija
//za byte (char) vrednosti v packed color 32 bitnem formatu
//!!! PAZI, TOLE NE DELA CISTO PRAV ??? belina se siri
//!!! zaenkrat sem dodal fudge factor...
int interpSP6_b32(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int i,b,j,m,n;
float pp,p[6],wx[6],wy[6],xx;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-3; if (m<0) m=0; if ((m+7)>w) m=w-6;
n=(int)ceilf(y)-3; if (n<0) n=0; if ((n+7)>h) n=h-6;
//najprej po y (sest stolpcev)
xx=y-n;
wy[0]=((0.090909*(xx-2.0)-0.215311)*(xx-2.0)+0.124402)*(xx-2.0);
xx=xx-1.0;
wy[1]=((-0.545455*(xx-1.0)+1.291866)*(xx-1.0)-0.746411)*(xx-1.0);
xx=xx-1.0;
wy[2]=((1.181818*xx-2.167464)*xx+0.014354)*xx+1.0;
xx=1.0-xx;
wy[3]=((1.181818*xx-2.167464)*xx+0.014354)*xx+1.0;
xx=xx+1.0;
wy[4]=((-0.545455*(xx-1.0)+1.291866)*(xx-1.0)-0.746411)*(xx-1.0);
xx=xx+1.0;
wy[5]=((0.090909*(xx-2.0)-0.215311)*(xx-2.0)+0.124402)*(xx-2.0);
//se po x
xx=x-m;
wx[0]=((0.090909*(xx-2.0)-0.215311)*(xx-2.0)+0.124402)*(xx-2.0);
xx=xx-1.0;
wx[1]=((-0.545455*(xx-1.0)+1.291866)*(xx-1.0)-0.746411)*(xx-1.0);
xx=xx-1.0;
wx[2]=((1.181818*xx-2.167464)*xx+0.014354)*xx+1.0;
xx=1.0-xx;
wx[3]=((1.181818*xx-2.167464)*xx+0.014354)*xx+1.0;
xx=xx+1.0;
wx[4]=((-0.545455*(xx-1.0)+1.291866)*(xx-1.0)-0.746411)*(xx-1.0);
xx=xx+1.0;
wx[5]=((0.090909*(xx-2.0)-0.215311)*(xx-2.0)+0.124402)*(xx-2.0);
for (b=0;b<4;b++)
{
for (i=0;i<6;i++)
{
p[i]=0.0;
for (j=0;j<6;j++)
{
p[i]=p[i]+wy[j]*sl[4*((j+n)*w+i+m)+b];
}
}
pp=0.0;
for (i=0;i<6;i++)
pp=pp+wx[i]*p[i];
pp=0.947*pp; //fudge factor...!!! cca 0.947...
if (pp<0.0) pp=0.0;
if (pp>256.0) pp=255.0;
v[b]=pp;
}
return 0;
}
//------------------------------------------------------
//truncated sinc "lanczos" 16x16 interpolacija
//za byte (char) vrednosti
// *sl vhodni array (slika)
// w,h dimenzija slike je wxh
// x,y tocka, za katero izracuna interpolirano vrednost
// *v interpolirana vrednost
int interpSC16_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int i,j,m,n;
float pp,p[16],wx[16],wy[16],xx,xxx,x1;
float PI=3.141592654;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-8; if (m<0) m=0; if ((m+17)>w) m=w-16;
n=(int)ceilf(y)-8; if (n<0) n=0; if ((n+17)>h) n=h-16;
//najprej po y
xx=y-n;
for (i=7;i>=0;i--)
{
x1=xx*PI;
wy[7-i]=(x1!=0)?(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125)):1.0;
xxx=(float)(2*i+1)-xx;
x1=xxx*PI;
wy[8+i]=(x1!=0)?(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125)):1.0;
xx=xx-1.0;
}
//se po x
xx=x-m;
for (i=7;i>=0;i--)
{
x1=xx*PI;
wx[7-i]=(x1!=0)?(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125)):1.0;
xxx=(float)(2*i+1)-xx;
x1=xxx*PI;
wx[8+i]=(x1!=0)?(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125)):1.0;
xx=xx-1.0;
}
for (i=0;i<16;i++)
{
p[i]=0.0;
for (j=0;j<16;j++)
{
p[i]=p[i]+wy[j]*sl[(j+n)*w+i+m];
}
}
pp=0.0;
for (i=0;i<16;i++)
pp=pp+wx[i]*p[i];
if (pp<0.0) pp=0.0;
if (pp>256.0) pp=255.0;
*v=pp;
return 0;
}
//------------------------------------------------------
//truncated sinc "lanczos" 16x16 interpolacija
//za byte (char) vrednosti v packed color 32 bitnem formatu
int interpSC16_b32(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
{
int i,j,m,b,n;
float pp,p[16],wx[16],wy[16],xx,xxx,x1;
float PI=3.141592654;
#ifdef TEST_XY_LIMITS
if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
#endif
m=(int)ceilf(x)-8; if (m<0) m=0; if ((m+17)>w) m=w-16;
n=(int)ceilf(y)-8; if (n<0) n=0; if ((n+17)>h) n=h-16;
//najprej po y
xx=y-n;
for (i=7;i>=0;i--)
{
x1=xx*PI;
wy[7-i]=(x1!=0)?(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125)):1.0;
xxx=(float)(2*i+1)-xx;
x1=xxx*PI;
wy[8+i]=(x1!=0)?(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125)):1.0;
xx=xx-1.0;
}
//se po x
xx=x-m;
for (i=7;i>=0;i--)
{
x1=xx*PI;
wx[7-i]=(x1!=0)?(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125)):1.0;
xxx=(float)(2*i+1)-xx;
x1=xxx*PI;
wx[8+i]=(x1!=0)?(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125)):1.0;
xx=xx-1.0;
}
for (b=0;b<4;b++)
{
for (i=0;i<16;i++)
{
p[i]=0.0;
for (j=0;j<16;j++)
{
p[i]=p[i]+wy[j]*sl[4*((j+n)*w+i+m)+b];
}
}
pp=0.0;
for (i=0;i<16;i++)
pp=pp+wx[i]*p[i];
if (pp<0.0) pp=0.0;
if (pp>256.0) pp=255.0;
v[b]=pp;
}
return 0;
}