--- /dev/null
+//interp.c
+/*
+ * Copyright (C) 2010 Marko Cebokli http://lea.hamradio.si/~s57uuu
+ * This file is a part of the Frei0r plugin "c0rners"
+ *
+ * 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 aray, which contains a pair
+ * of floating values fo 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
+
+//------------------------------------------------------
+//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)
+{
+#ifdef TEST_XY_LIMITS
+ if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
+#endif
+ v[3]= sl[(int)roundf(x)*4+(int)roundf(y)*4*w+3];
+ float alpha = (float) v[3] / 255.0;
+ v[0]= v[0] * (1.0 - alpha) + sl[(int)roundf(x)*4+(int)roundf(y)*4*w] * alpha;
+ v[1]= v[1] * (1.0 - alpha) + sl[(int)roundf(x)*4+(int)roundf(y)*4*w+1] * alpha;
+ v[2]= v[2] * (1.0 - alpha) + sl[(int)roundf(x)*4+(int)roundf(y)*4*w+2] * alpha;
+
+ 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+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);
+ float alpha = (float) v[3] / 255.0;
+
+ a=sl[k]+(sl[k1]-sl[k])*(x-(float)m);
+ b=sl[l]+(sl[l1]-sl[n1])*(x-(float)m);
+ v[0]= v[0] * (1.0 - alpha) + (a+(b-a)*(y-(float)n)) * alpha;
+
+ 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]= v[1] * (1.0 - alpha) + (a+(b-a)*(y-(float)n)) * alpha;
+
+ 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]= v[2] * (1.0 - alpha) + (a+(b-a)*(y-(float)n)) * alpha;
+
+ 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];
+ float alpha = 1.0;
+
+#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=3;b>-1;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]= v[b] * (1.0 - alpha) + p[3] * alpha;
+ if (b == 3) alpha = v[b] / 255.0;
+ }
+
+ 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]=(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125));
+ xxx=(float)(2*i+1)-xx;
+ x1=xxx*PI;
+ wy[8+i]=(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125));
+ xx=xx-1.0;
+ }
+ //se po x
+ xx=x-m;
+ for (i=7;i>=0;i--)
+ {
+ x1=xx*PI;
+ wx[7-i]=(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125));
+ xxx=(float)(2*i+1)-xx;
+ x1=xxx*PI;
+ wx[8+i]=(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125));
+ 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]=(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125));
+ xxx=(float)(2*i+1)-xx;
+ x1=xxx*PI;
+ wy[8+i]=(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125));
+ xx=xx-1.0;
+ }
+ //se po x
+ xx=x-m;
+ for (i=7;i>=0;i--)
+ {
+ x1=xx*PI;
+ wx[7-i]=(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125));
+ xxx=(float)(2*i+1)-xx;
+ x1=xxx*PI;
+ wx[8+i]=(sin(x1)/(x1))*(sin(x1*0.125)/(x1*0.125));
+ 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;
+}
/*
* transition_affine.c -- affine transformations
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2010 Ushodaya Enterprises Limited
* Author: Charles Yates <charles.yates@pandora.be>
+ * Author: Dan Dennedy <dan@dennedy.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <string.h>
#include <math.h>
+#include "interp.h"
+
/** Calculate real geometry.
*/
affine_multiply( this, affine );
}
-static void affine_offset( float this[3][3], int x, int y )
+static void affine_offset( float this[3][3], float x, float y )
{
this[0][2] += x;
this[1][2] += y;
}
// Obtain the mapped x coordinate of the input
-static inline double MapX( float this[3][3], int x, int y )
+static inline double MapX( float this[3][3], float x, float y )
{
return this[0][0] * x + this[0][1] * y + this[0][2];
}
// Obtain the mapped y coordinate of the input
-static inline double MapY( float this[3][3], int x, int y )
+static inline double MapY( float this[3][3], float x, float y )
{
return this[1][0] * x + this[1][1] * y + this[1][2];
}
-static inline double MapZ( float this[3][3], int x, int y )
+static inline double MapZ( float this[3][3], float x, float y )
{
return this[2][0] * x + this[2][1] * y + this[2][2];
}
#define MAX( x, y ) x > y ? x : y
#define MIN( x, y ) x < y ? x : y
-static void affine_max_output( float this[3][3], float *w, float *h, float dz )
+static void affine_max_output( float this[3][3], float *w, float *h, float dz, float max_width, float max_height )
{
- int tlx = MapX( this, -720, 576 ) / dz;
- int tly = MapY( this, -720, 576 ) / dz;
- int trx = MapX( this, 720, 576 ) / dz;
- int try = MapY( this, 720, 576 ) / dz;
- int blx = MapX( this, -720, -576 ) / dz;
- int bly = MapY( this, -720, -576 ) / dz;
- int brx = MapX( this, 720, -576 ) / dz;
- int bry = MapY( this, 720, -576 ) / dz;
+ int tlx = MapX( this, -max_width, max_height ) / dz;
+ int tly = MapY( this, -max_width, max_height ) / dz;
+ int trx = MapX( this, max_width, max_height ) / dz;
+ int try = MapY( this, max_width, max_height ) / dz;
+ int blx = MapX( this, -max_width, -max_height ) / dz;
+ int bly = MapY( this, -max_width, -max_height ) / dz;
+ int brx = MapX( this, max_width, -max_height ) / dz;
+ int bry = MapY( this, max_width, -max_height ) / dz;
int max_x;
int max_y;
min_y = MIN( min_y, bly );
min_y = MIN( min_y, bry );
- *w = ( float )( max_x - min_x + 1 ) / 1440.0;
- *h = ( float )( max_y - min_y + 1 ) / 1152.0;
+ *w = ( float )( max_x - min_x + 1 ) / max_width / 2.0;
+ *h = ( float )( max_y - min_y + 1 ) / max_height / 2.0;
}
#define IN_RANGE( v, r ) ( v >= - r / 2 && v < r / 2 )
{
mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
int keyed = mlt_properties_get_int( properties, "keyed" );
- affine_init( affine->matrix );
if ( keyed == 0 )
{
// Image, format, width, height and image for the b frame
uint8_t *b_image = NULL;
- mlt_image_format b_format = mlt_image_yuv422;
+ mlt_image_format b_format = mlt_image_rgb24a;
int b_width;
int b_height;
int normalised_width = mlt_properties_get_int( a_props, "normalised_width" );
int normalised_height = mlt_properties_get_int( a_props, "normalised_height" );
- double consumer_ar = mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) ;
+ double consumer_ar = mlt_properties_get_double( a_props, "consumer_aspect_ratio" );
+ const char *interps = mlt_properties_get( b_props, "rescale.interp" );
+ mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE(this) );
// Structures for geometry
struct mlt_geometry_item_s result;
position = abs( position - length );
// Fetch the a frame image
- *format = mlt_image_yuv422;
+ *format = mlt_image_rgb24a;
mlt_frame_get_image( a_frame, image, format, width, height, 1 );
// Calculate the region now
composite_calculate( this, &result, normalised_width, normalised_height, ( float )position );
// Fetch the b frame image
- result.w = ( int )( result.w * *width / normalised_width );
- result.h = ( int )( result.h * *height / normalised_height );
- result.x = ( int )( result.x * *width / normalised_width );
- result.y = ( int )( result.y * *height / normalised_height );
- //result.w -= ( int )abs( result.w ) % 2;
- //result.x -= ( int )abs( result.x ) % 2;
- b_width = result.w;
- b_height = result.h;
-
- if ( mlt_properties_get_double( b_props, "aspect_ratio" ) == 0.0 )
- mlt_properties_set_double( b_props, "aspect_ratio", consumer_ar );
-
- if ( !strcmp( mlt_properties_get( a_props, "rescale.interp" ), "none" ) )
+ result.w = ( result.w * *width / normalised_width );
+ result.h = ( result.h * *height / normalised_height );
+ result.x = ( result.x * *width / normalised_width );
+ result.y = ( result.y * *height / normalised_height );
+ b_width = mlt_properties_get_int(b_props, "real_width");
+ b_height = mlt_properties_get_int(b_props, "real_height");
+ if ( 0 && b_width > result.w * 2 && b_height > result.h * 2 )
{
- mlt_properties_set( b_props, "rescale.interp", "nearest" );
- mlt_properties_set_double( b_props, "consumer_aspect_ratio", consumer_ar );
+ // This downscale can reduce aliasing by acting as a low pass filter.
+ b_width = b_width / 2;
+ b_height = b_height / 2;
}
- else
+ mlt_properties_set_int( b_props, "rescale_width", b_width );
+ mlt_properties_set_int( b_props, "rescale_height", b_height );
+ if ( mlt_properties_get_double( b_props, "aspect_ratio" ) == 0.0 )
+ mlt_properties_set_double( b_props, "aspect_ratio", consumer_ar );
+ mlt_properties_set_int( b_props, "progressive", 1 );
+ if ( interps == NULL || !strcmp( interps, "none" ) )
{
- mlt_properties_set( b_props, "rescale.interp", mlt_properties_get( a_props, "rescale.interp" ) );
+ mlt_properties_set( b_props, "rescale.interp", "bilinear" );
mlt_properties_set_double( b_props, "consumer_aspect_ratio", consumer_ar );
}
-
- mlt_properties_set_int( b_props, "distort", mlt_properties_get_int( properties, "distort" ) );
mlt_frame_get_image( b_frame, &b_image, &b_format, &b_width, &b_height, 0 );
- result.w = b_width;
- result.h = b_height;
// Check that both images are of the correct format and process
- if ( *format == mlt_image_yuv422 && b_format == mlt_image_yuv422 )
+ if ( *format == mlt_image_rgb24a && b_format == mlt_image_rgb24a )
{
- register int x, y;
- register int dx, dy;
- double dz;
+ float x, y;
+ float dx, dy;
+ float dz;
float sw, sh;
+ uint8_t *p = *image;
// Get values from the transition
float scale_x = mlt_properties_get_double( properties, "scale_x" );
float scale_y = mlt_properties_get_double( properties, "scale_y" );
int scale = mlt_properties_get_int( properties, "scale" );
-
- uint8_t *p = *image;
- uint8_t *q = *image;
-
- int cx = result.x + ( b_width >> 1 );
- int cy = result.y + ( b_height >> 1 );
- cx -= cx % 2;
-
- int lower_x = 0 - cx;
- int upper_x = *width - cx;
- int lower_y = 0 - cy;
- int upper_y = *height - cy;
-
- int b_stride = b_width << 1;
- int a_stride = *width << 1;
- int x_offset = ( int )result.w >> 1;
- int y_offset = ( int )result.h >> 1;
-
- uint8_t *alpha = mlt_frame_get_alpha_mask( b_frame );
- uint8_t *mask = mlt_frame_get_alpha_mask( a_frame );
- uint8_t *pmask = mask;
- float mix;
-
+ float sar = (float) profile->sample_aspect_num / profile->sample_aspect_den;
+ float geom_scale_x = (float) b_width / result.w / sar;
+ float geom_scale_y = (float) b_height / result.h * sar;
+ float cx = result.x + result.w / 2.0;
+ float cy = result.y + result.h / 2.0;
+ float lower_x = - cx;
+ float upper_x = (float) *width - cx;
+ float lower_y = - cy;
+ float upper_y = (float) *height - cy;
+ float x_offset = (float) b_width / 2.0;
+ float y_offset = (float) b_height / 2.0;
+ float sar_affine[3][3];
affine_t affine;
+ interpp interp = interpBL_b32;
- get_affine( &affine, this, ( float )position );
+ affine_init( affine.matrix );
- q = *image;
+ // Factor aspect ratio into transforms
+ affine_init( sar_affine);
+ sar_affine[0][0] /= sar;
+ affine_multiply( affine.matrix, sar_affine );
+ // Compute the affine transform
+ get_affine( &affine, this, ( float )position );
dz = MapZ( affine.matrix, 0, 0 );
+ if ( ( int )abs( dz * 1000 ) < 25 )
+ return 0;
- if ( mask == NULL )
+ // Factor scaling into the transformation based on output resolution.
+ if ( mlt_properties_get_int( properties, "distort" ) )
{
- mask = mlt_pool_alloc( *width * *height );
- pmask = mask;
- memset( mask, 255, *width * *height );
+ scale_x = geom_scale_x * ( scale_x == 0 ? 1 : scale_x );
+ scale_y = geom_scale_y / sar * ( scale_y == 0 ? 1 : scale_y );
+ }
+ else
+ {
+ float scaling = MIN( geom_scale_x, geom_scale_y );
+ if ( b_height / scaling > result.h / sar )
+ scaling = geom_scale_y / sar;
+ else if ( b_width / scaling > result.w * sar )
+ scaling = geom_scale_x * sar;
+ scale_x = scaling * ( scale_x == 0 ? 1 : scale_x );
+ scale_y = scaling * ( scale_y == 0 ? 1 : scale_y );
}
-
- if ( ( int )abs( dz * 1000 ) < 25 )
- goto getout;
-
if ( scale )
{
- affine_max_output( affine.matrix, &sw, &sh, dz );
- affine_scale( affine.matrix, sw, sh );
+ affine_max_output( affine.matrix, &sw, &sh, dz, profile->width, profile->height );
+ affine_scale( affine.matrix, sw * MIN( geom_scale_x, geom_scale_y ), sh * MIN( geom_scale_x, geom_scale_y ) );
}
else if ( scale_x != 0 && scale_y != 0 )
{
affine_scale( affine.matrix, scale_x, scale_y );
}
- if ( alpha == NULL )
- {
- for ( y = lower_y; y < upper_y; y ++ )
- {
- p = q;
-
- for ( x = lower_x; x < upper_x; x ++ )
- {
- dx = MapX( affine.matrix, x, y ) / dz + x_offset;
- dy = MapY( affine.matrix, x, y ) / dz + y_offset;
-
- if ( dx >= 0 && dx < b_width && dy >=0 && dy < b_height )
- {
- pmask ++;
- dx -= dx & 1;
- *p ++ = *( b_image + dy * b_stride + ( dx << 1 ) );
- *p ++ = *( b_image + dy * b_stride + ( dx << 1 ) + ( ( x & 1 ) << 1 ) + 1 );
- }
- else
- {
- p += 2;
- pmask ++;
- }
- }
-
- q += a_stride;
- }
- }
- else
+ // Invert transform aspect ratio factor
+ sar_affine[0][0] *= sar; // return to identity matrix
+ sar_affine[0][0] *= sar; // reverse the sample aspect adjustment
+ affine_multiply( affine.matrix, sar_affine );
+
+ // Set the interpolation function
+ if ( interps == NULL || strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 )
+ interp = interpNN_b32;
+ else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 )
+ interp = interpNN_b32;
+ else if ( strcmp( interps, "bilinear" ) == 0 )
+ interp = interpBL_b32;
+ else if ( strcmp( interps, "bicubic" ) == 0 )
+ interp = interpBC_b32;
+ // TODO: lanczos 8x8
+ else if ( strcmp( interps, "hyper" ) == 0 || strcmp( interps, "sinc" ) == 0 || strcmp( interps, "lanczos" ) == 0 )
+ interp = interpBC_b32;
+ else if ( strcmp( interps, "spline" ) == 0 ) // TODO: spline 4x4 or 6x6
+ interp = interpBC_b32;
+
+ // Do the transform with interpolation
+ for ( y = lower_y; y < upper_y; y ++ )
{
- for ( y = lower_y; y < upper_y; y ++ )
+ for ( x = lower_x; x < upper_x; x ++ )
{
- p = q;
-
- for ( x = lower_x; x < upper_x; x ++ )
- {
- dx = MapX( affine.matrix, x, y ) / dz + x_offset;
- dy = MapY( affine.matrix, x, y ) / dz + y_offset;
-
- if ( dx >= 0 && dx < b_width && dy >=0 && dy < b_height )
- {
- *pmask ++ = *( alpha + dy * b_width + dx );
- mix = ( float )*( alpha + dy * b_width + dx ) / 255.0;
- dx -= dx & 1;
- *p = *p * ( 1 - mix ) + mix * *( b_image + dy * b_stride + ( dx << 1 ) );
- p ++;
- *p = *p * ( 1 - mix ) + mix * *( b_image + dy * b_stride + ( dx << 1 ) + ( ( x & 1 ) << 1 ) + 1 );
- p ++;
- }
- else
- {
- p += 2;
- pmask ++;
- }
- }
-
- q += a_stride;
+ dx = MapX( affine.matrix, x, y ) / dz + x_offset;
+ dy = MapY( affine.matrix, x, y ) / dz + y_offset;
+ if ( dx >= 0 && dx < b_width && dy >=0 && dy < b_height )
+ interp( b_image, b_width, b_height, dx, dy, p );
+ p += 4;
}
}
-
-getout:
- a_frame->get_alpha_mask = NULL;
- mlt_properties_set_data( a_props, "alpha", mask, 0, mlt_pool_release, NULL );
}
return 0;
mlt_transition transition = mlt_transition_new( );
if ( transition != NULL )
{
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "sx", 1 );
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "sy", 1 );
mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "distort", 0 );
mlt_properties_set( MLT_TRANSITION_PROPERTIES( transition ), "geometry", "0,0:100%x100%" );
// Inform apps and framework that this is a video only transition