]> git.sesse.net Git - mlt/blobdiff - src/modules/plus/interp.h
Refactor movit.convert, movit.mix, and movit.overlay.
[mlt] / src / modules / plus / interp.h
index 25aae4bbe16574db3a22765d7e28b049aecf1aa7..b223db974b41242b895972bce8890331f57cf4a3 100644 (file)
 #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
-       }
-}
 
+//#define TEST_XY_LIMITS
 
 //--------------------------------------------------------
-//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;
-               }
-       }
-}
+//pointer to an interpolating function
+//parameters:
+//  source image
+//  source width
+//  source height
+//  X coordinate
+//  Y coordinate
+//  opacity
+//  destination image
+//  flag to overwrite alpha channel
+typedef int (*interpp)(unsigned char*, int, int, float, float, float, unsigned char*, int);
 
 //**************************************
 //HERE BEGIN THE INTERPOLATION FUNCTIONS
@@ -114,15 +69,16 @@ void remap32(int wi, int hi, int wo, int ho, unsigned char *vhs, unsigned char *
 //     *sl vhodni array (slika)
 //     w,h dimenzija slike je wxh
 //     x,y tocka, za katero izracuna interpolirano vrednost
+//  o opacity
 //     *v interpolirana vrednost
-int interpNNpr_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
+int interpNNpr_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        //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)rintf(x),(int)rintf(y));
 
 #ifdef TEST_XY_LIMITS
-       if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        *v=sl[(int)rintf(x)+(int)rintf(y)*w];
@@ -135,11 +91,12 @@ int interpNNpr_b(unsigned char *sl, int w, int h, float x, float y, unsigned cha
 //     *sl vhodni array (slika)
 //     w,h dimenzija slike je wxh
 //     x,y tocka, za katero izracuna interpolirano vrednost
+//  o opacity
 //     *v interpolirana vrednost
-int interpNN_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
+int interpNN_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
 #ifdef TEST_XY_LIMITS
-       if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        *v=sl[(int)rintf(x)+(int)rintf(y)*w];
@@ -153,17 +110,19 @@ int interpNN_b(unsigned char *sl, int w, int h, float x, float y, unsigned char
 //     *sl vhodni array (slika)
 //     w,h dimenzija slike je wxh
 //     x,y tocka, za katero izracuna interpolirano vrednost
+//  o opacity
 //     *v interpolirana vrednost
-int interpNN_b32(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
+int interpNN_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
 #ifdef TEST_XY_LIMITS
-       if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
-       v[3]= sl[(int)rintf(x)*4+(int)rintf(y)*4*w+3];
-       float alpha = (float) v[3] / 255.0;
-       v[0]= v[0] * (1.0 - alpha) + sl[(int)rintf(x)*4+(int)rintf(y)*4*w] * alpha;
-       v[1]= v[1] * (1.0 - alpha) + sl[(int)rintf(x)*4+(int)rintf(y)*4*w+1] * alpha;
-       v[2]= v[2] * (1.0 - alpha) + sl[(int)rintf(x)*4+(int)rintf(y)*4*w+2] * alpha;
+       int p = (int) rintf(x) * 4 + (int) rintf(y) * 4 * w;
+       float alpha = (float) sl[p + 3] / 255.0 * o;
+       v[0]= v[0] * (1.0 - alpha) + sl[p] * alpha;
+       v[1]= v[1] * (1.0 - alpha) + sl[p + 1] * alpha;
+       v[2]= v[2] * (1.0 - alpha) + sl[p + 2] * alpha;
+       if (is_alpha) v[3] = sl[p +3];
 
        return 0;
 }
@@ -174,14 +133,15 @@ int interpNN_b32(unsigned char *sl, int w, int h, float x, float y, unsigned cha
 //     *sl vhodni array (slika)
 //     w,h dimenzija slike je wxh
 //     x,y tocka, za katero izracuna interpolirano vrednost
+//  o opacity
 //     *v interpolirana vrednost
-int interpBL_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
+int interpBL_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int m,n,k,l;
        float a,b;
 
 #ifdef TEST_XY_LIMITS
-       if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)floorf(x); n=(int)floorf(y);
@@ -195,13 +155,13 @@ int interpBL_b(unsigned char *sl, int w, int h, float x, float y, unsigned char
 //------------------------------------------------------
 //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 interpBL_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)floorf(x); n=(int)floorf(y);
@@ -211,8 +171,9 @@ int interpBL_b32(unsigned char *sl, int w, int h, float x, float y, unsigned cha
 
        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;
+       float alpha = a+(b-a)*(y-(float)n);
+       if (is_alpha) v[3] = alpha;
+       alpha = alpha / 255.0 * o;
 
        a=sl[k]+(sl[k1]-sl[k])*(x-(float)m);
        b=sl[l]+(sl[l1]-sl[n1])*(x-(float)m);
@@ -236,15 +197,16 @@ int interpBL_b32(unsigned char *sl, int w, int h, float x, float y, unsigned cha
 //     *sl vhodni array (slika)
 //     w,h dimenzija slike je wxh
 //     x,y tocka, za katero izracuna interpolirano vrednost
+//  o opacity
 //     *v interpolirana vrednost
-int interpBC_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
+int interpBC_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
@@ -286,7 +248,7 @@ int interpBC_b(unsigned char *sl, int w, int h, float x, float y, unsigned char
 //------------------------------------------------------
 //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 interpBC_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,j,b,l,m,n;
        float k;
@@ -294,7 +256,7 @@ int interpBC_b32(unsigned char *sl, int w, int h, float x, float y, unsigned cha
        float alpha = 1.0;
 
 #ifdef TEST_XY_LIMITS
-       if ((x<0)||(x>w)||(y<0)||(y>h)) return -1;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
@@ -329,10 +291,14 @@ int interpBC_b32(unsigned char *sl, int w, int h, float x, float y, unsigned cha
                                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;
+               if (p[3]>255.0) p[3]=255.0;
 
-               v[b]= v[b] * (1.0 - alpha) + p[3] * alpha;
-               if (b == 3) alpha = v[b] / 255.0;
+               if (b == 3) {
+                       alpha = p[3] / 255.0 * o;
+                       if (is_alpha) v[3] = p[3];
+               } else {
+                       v[b] = v[b] * (1.0 - alpha) + p[3] * alpha;
+               }
        }
 
        return 0;
@@ -345,16 +311,17 @@ int interpBC_b32(unsigned char *sl, int w, int h, float x, float y, unsigned cha
 //     *sl vhodni array (slika)
 //     w,h dimenzija slike je wxh
 //     x,y tocka, za katero izracuna interpolirano vrednost
+//  o opacity
 //     *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 interpBC2_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
@@ -400,13 +367,13 @@ int interpBC2_b(unsigned char *sl, int w, int h, float x, float y, unsigned char
 //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 interpBC2_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
@@ -458,14 +425,15 @@ int interpBC2_b32(unsigned char *sl, int w, int h, float x, float y, unsigned ch
 //     *sl vhodni array (slika)
 //     w,h dimenzija slike je wxh
 //     x,y tocka, za katero izracuna interpolirano vrednost
+//  o opacity
 //     *v interpolirana vrednost
-int interpSP4_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
+int interpSP4_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
@@ -505,13 +473,13 @@ int interpSP4_b(unsigned char *sl, int w, int h, float x, float y, unsigned char
 //------------------------------------------------------
 //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 interpSP4_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-2; if (m<0) m=0; if ((m+5)>w) m=w-4;
@@ -559,16 +527,17 @@ int interpSP4_b32(unsigned char *sl, int w, int h, float x, float y, unsigned ch
 //     *sl vhodni array (slika)
 //     w,h dimenzija slike je wxh
 //     x,y tocka, za katero izracuna interpolirano vrednost
+//  o opacity
 //     *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 interpSP6_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-3; if (m<0) m=0; if ((m+7)>w) m=w-6;
@@ -628,13 +597,13 @@ int interpSP6_b(unsigned char *sl, int w, int h, float x, float y, unsigned char
 //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 interpSP6_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-3; if (m<0) m=0; if ((m+7)>w) m=w-6;
@@ -699,15 +668,16 @@ int interpSP6_b32(unsigned char *sl, int w, int h, float x, float y, unsigned ch
 //     *sl vhodni array (slika)
 //     w,h dimenzija slike je wxh
 //     x,y tocka, za katero izracuna interpolirano vrednost
+//  o opacity
 //     *v interpolirana vrednost
-int interpSC16_b(unsigned char *sl, int w, int h, float x, float y, unsigned char *v)
+int interpSC16_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-8; if (m<0) m=0; if ((m+17)>w) m=w-16;
@@ -759,14 +729,14 @@ int interpSC16_b(unsigned char *sl, int w, int h, float x, float y, unsigned cha
 //------------------------------------------------------
 //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 interpSC16_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        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;
+       if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
 
        m=(int)ceilf(x)-8; if (m<0) m=0; if ((m+17)>w) m=w-16;