add binfolder path relative filters, fix gbrp color model, vwdw timebar tweaks, title...
[goodguy/history.git] / cinelerra-5.1 / cinelerra / affine.C
index f5f90a7c8228c7ee8680a8576e61e2fd31b02953..a59d6e3ee9997372f5b9c4eede18f44ac0d96a17 100644 (file)
@@ -25,6 +25,7 @@
 #endif
 
 #include "affine.h"
+#include "interp.h"
 #include "clip.h"
 #include "vframe.h"
 
@@ -144,6 +145,38 @@ void AffineMatrix::copy_from(AffineMatrix *src)
        memcpy(&values[0][0], &src->values[0][0], sizeof(values));
 }
 
+void AffineMatrix::set_matrix(
+       double in_x1, double in_y1, double in_x2, double in_y2,
+       double out_x1, double out_y1, double out_x2, double out_y2,
+       double out_x3, double out_y3, double out_x4, double out_y4)
+{
+       double scalex = in_x2 > in_x1 ? 1./(in_x2 - in_x1) : 1.0;
+       double scaley = in_y2 > in_y1 ? 1./(in_y2 - in_y1) : 1.0;
+       double dx1 = out_x2 - out_x4, dx2 = out_x3 - out_x4;
+       double dx3 = out_x1 - out_x2 + out_x4 - out_x3;
+
+       double dy1 = out_y2 - out_y4, dy2 = out_y3 - out_y4;
+       double dy3 = out_y1 - out_y2 + out_y4 - out_y3;
+       double det = dx1 * dy2 - dy1 * dx2;
+       if( !det ) { identity();  return; }
+
+       AffineMatrix m;
+       m.values[2][0] = (dx3 * dy2 - dy3 * dx2) / det;
+       m.values[2][1] = (dx1 * dy3 - dy1 * dx3) / det;
+       m.values[0][0] = out_x2 - out_x1 + m.values[2][0] * out_x2;
+       m.values[0][1] = out_x3 - out_x1 + m.values[2][1] * out_x3;
+       m.values[0][2] = out_x1;
+       m.values[1][0] = out_y2 - out_y1 + m.values[2][0] * out_y2;
+       m.values[1][1] = out_y3 - out_y1 + m.values[2][1] * out_y3;
+       m.values[1][2] = out_y1;
+       m.values[2][2] = 1.0;
+
+       identity();
+       translate(-in_x1, -in_y1);
+       scale(scalex, scaley);
+       m.multiply(this);
+}
+
 void AffineMatrix::transform_point(float x,
        float y,
        float *newx,
@@ -185,91 +218,6 @@ AffineUnit::AffineUnit(AffineEngine *server)
 }
 
 
-
-
-
-
-
-
-
-void AffineUnit::calculate_matrix(
-       double in_x1, double in_y1, double in_x2, double in_y2,
-       double out_x1, double out_y1, double out_x2, double out_y2,
-       double out_x3, double out_y3, double out_x4, double out_y4,
-       AffineMatrix *result)
-{
-       AffineMatrix matrix;
-       double scalex;
-       double scaley;
-
-       scalex = scaley = 1.0;
-
-       if( (in_x2 - in_x1) > 0 )
-               scalex = 1.0 / (double)(in_x2 - in_x1);
-
-       if( (in_y2 - in_y1) > 0 )
-               scaley = 1.0 / (double)(in_y2 - in_y1);
-
-/* Determine the perspective transform that maps from
- * the unit cube to the transformed coordinates
- */
-       double dx1, dx2, dx3, dy1, dy2, dy3;
-       double det1, det2;
-
-       dx1 = out_x2 - out_x4;
-       dx2 = out_x3 - out_x4;
-       dx3 = out_x1 - out_x2 + out_x4 - out_x3;
-
-       dy1 = out_y2 - out_y4;
-       dy2 = out_y3 - out_y4;
-       dy3 = out_y1 - out_y2 + out_y4 - out_y3;
-// printf("AffineUnit::calculate_matrix %f %f %f %f %f %f\n",
-//  dx1, dx2, dx3, dy1, dy2, dy3 );
-
-/*  Is the mapping affine?  */
-       if((dx3 == 0.0) && (dy3 == 0.0)) {
-               matrix.values[0][0] = out_x2 - out_x1;
-               matrix.values[0][1] = out_x4 - out_x2;
-               matrix.values[0][2] = out_x1;
-               matrix.values[1][0] = out_y2 - out_y1;
-               matrix.values[1][1] = out_y4 - out_y2;
-               matrix.values[1][2] = out_y1;
-               matrix.values[2][0] = 0.0;
-               matrix.values[2][1] = 0.0;
-       }
-       else {
-               det1 = dx3 * dy2 - dy3 * dx2;
-               det2 = dx1 * dy2 - dy1 * dx2;
-               matrix.values[2][0] = det1 / det2;
-               det1 = dx1 * dy3 - dy1 * dx3;
-               det2 = dx1 * dy2 - dy1 * dx2;
-               matrix.values[2][1] = det1 / det2;
-
-               matrix.values[0][0] = out_x2 - out_x1 + matrix.values[2][0] * out_x2;
-               matrix.values[0][1] = out_x3 - out_x1 + matrix.values[2][1] * out_x3;
-               matrix.values[0][2] = out_x1;
-
-               matrix.values[1][0] = out_y2 - out_y1 + matrix.values[2][0] * out_y2;
-               matrix.values[1][1] = out_y3 - out_y1 + matrix.values[2][1] * out_y3;
-               matrix.values[1][2] = out_y1;
-       }
-
-       matrix.values[2][2] = 1.0;
-
-// printf("AffineUnit::calculate_matrix 1 %f %f\n", dx3, dy3);
-// matrix.dump();
-
-       result->identity();
-       result->translate(-in_x1, -in_y1);
-       result->scale(scalex, scaley);
-       matrix.multiply(result);
-// double test[3][3] = 
-// { { 0.0896, 0.0, 0.0 },  { 0.0, 0.0896, 0.0 },  { -0.00126, 0.0, 1.0 } };
-// memcpy(&result->values[0][0], test, sizeof(test));
-// printf("AffineUnit::calculate_matrix 4 %p\n", result);
-// result->dump();
-}
-
 static inline float transform_cubic(float dx,
                float p0, float p1, float p2, float p3)
 {
@@ -409,12 +357,11 @@ void AffineUnit::process_package(LoadPackage *package)
 
 
                if( server->mode != AffineEngine::TRANSFORM ) {
-                       calculate_matrix( server->in_x, server->in_y,
+                       matrix.set_matrix(server->in_x, server->in_y,
                                server->in_x + server->in_w,
                                server->in_y + server->in_h,
                                out_x1, out_y1, out_x2, out_y2,
-                               out_x3, out_y3, out_x4, out_y4,
-                               &matrix);
+                               out_x3, out_y3, out_x4, out_y4);
                }
                else {
                        matrix.copy_from(&server->matrix);
@@ -429,7 +376,6 @@ void AffineUnit::process_package(LoadPackage *package)
                float xinc, yinc, winc;
                AffineMatrix m, im;
                float ttx = 0, tty = 0;
-               int itx = 0, ity = 0;
                int tx1 = 0, ty1 = 0, tx2 = 0, ty2 = 0;
 
                if(reverse) {
@@ -491,9 +437,7 @@ void AffineUnit::process_package(LoadPackage *package)
 
                        server->output->to_texture();
                        server->output->enable_opengl();
-                       unsigned int frag_shader = VFrame::make_shader(0,
-                                       affine_frag,
-                                       0);
+                       unsigned int frag_shader = VFrame::make_shader(0, affine_frag, 0);
                        if( frag_shader > 0 ) {
                                glUseProgram(frag_shader);
                                glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0);
@@ -555,172 +499,15 @@ void AffineUnit::process_package(LoadPackage *package)
 //printf("AffineUnit::process_package %d %d %d %d %d\n",
 // __LINE__, min_in_x, max_in_x, min_in_y, max_in_y);
 
-#define CUBIC_ROW(in_row, chroma_offset) ( !in_row ? 0 : transform_cubic(dx, \
-               cp>=min_in_x && cp<max_in_x ? in_row[cp*comps]-chroma_offset : 0, \
-               c0>=min_in_x && c0<max_in_x ? in_row[c0*comps]-chroma_offset : 0, \
-               c1>=min_in_x && c1<max_in_x ? in_row[c1*comps]-chroma_offset : 0, \
-               c2>=min_in_x && c2<max_in_x ? in_row[c2*comps]-chroma_offset : 0) )
-
-
-#define DO_CUBIC(tag, components, type, temp_type, chroma_offset, max) \
-case tag: { \
-    type **inp_rows = (type**)server->input->get_rows(); \
-    type **out_rows = (type**)server->output->get_rows(); \
-    float round_factor = sizeof(type) < 4 ? 0.5 : 0; \
-    int comps = components; \
-    for( int y=ty1; y<ty2; ++y ) { \
-        type *out_row = (type*)out_rows[y]; \
- \
-        int x1 = tx1, x2 = tx2; \
-        if( x1 < min_out_x ) x1 = min_out_x; \
-        if( x2 > max_out_x ) x2 = max_out_x; \
-        tx = xinc * x1 + m.values[0][1] * (y + pivot_offset_y) + m.values[0][2] \
-            + pivot_offset_x * xinc; \
-        ty = yinc * x1 + m.values[1][1] * (y + pivot_offset_y) + m.values[1][2] \
-            + pivot_offset_x * yinc; \
-        tw = winc * x1 + m.values[2][1] * (y + pivot_offset_y) + m.values[2][2] \
-            + pivot_offset_x * winc; \
-        type *out = out_row + x1 * comps; \
-        for( int x=x1; x<x2; ++x ) { \
-/* Normalize homogeneous coords */ \
-            if( tw == 0.0 ) { ttx = 0.0; tty = 0.0; } \
-            else { ttx = tx / tw; tty = ty / tw; } \
-            itx = (int)ttx;  ity = (int)tty; \
-/* the fractional error */ \
-            float dx = ttx - itx, dy = tty - ity; \
-            if( dx < 0 ) dx += 1; \
-            if( dy < 0 ) dy += 1; \
-/* row/col index */ \
-            int cp = itx-1, c0 = itx+0, c1 = itx+1, c2 = itx+2; \
-            int rp = ity-1, r0 = ity+0, r1 = ity+1, r2 = ity+2; \
-            type *rpp, *r0p, *r1p, *r2p; \
-            rpp = rp>=min_in_y && rp<max_in_y ? inp_rows[rp] : 0; \
-            r0p = r0>=min_in_y && r0<max_in_y ? inp_rows[r0] : 0; \
-            r1p = r1>=min_in_y && r1<max_in_y ? inp_rows[r1] : 0; \
-            r2p = r2>=min_in_y && r2<max_in_y ? inp_rows[r2] : 0; \
-            temp_type r, g, b, a; \
-            r = (temp_type)(transform_cubic(dy, \
-                CUBIC_ROW(rpp, 0x0), CUBIC_ROW(r0p, 0x0), \
-                CUBIC_ROW(r1p, 0x0), CUBIC_ROW(r2p, 0x0)) \
-                + round_factor); \
-            if(rpp) ++rpp;  if(r0p) ++r0p;  if(r1p) ++r1p;  if(r2p) ++r2p; \
-            g = (temp_type)(transform_cubic(dy, \
-                CUBIC_ROW(rpp, chroma_offset), CUBIC_ROW(r0p, chroma_offset), \
-                CUBIC_ROW(r1p, chroma_offset), CUBIC_ROW(r2p, chroma_offset)) \
-                + round_factor) + chroma_offset; \
-            if(rpp) ++rpp;  if(r0p) ++r0p;  if(r1p) ++r1p;  if(r2p) ++r2p; \
-            b = (temp_type)(transform_cubic(dy, \
-                CUBIC_ROW(rpp, chroma_offset), CUBIC_ROW(r0p, chroma_offset), \
-                CUBIC_ROW(r1p, chroma_offset), CUBIC_ROW(r2p, chroma_offset)) \
-                + round_factor) + chroma_offset; \
-            if( components == 4 ) { \
-                if(rpp) ++rpp;  if(r0p) ++r0p;  if(r1p) ++r1p;  if(r2p) ++r2p; \
-                a = (temp_type)(transform_cubic(dy, \
-                    CUBIC_ROW(rpp, 0x0), CUBIC_ROW(r0p, 0x0), \
-                    CUBIC_ROW(r1p, 0x0), CUBIC_ROW(r2p, 0x0)) \
-                    + round_factor); \
-            } \
-            if( sizeof(type) < 4 ) { \
-                *out++ = CLIP(r, 0, max); \
-                *out++ = CLIP(g, 0, max); \
-                *out++ = CLIP(b, 0, max); \
-                if( components == 4 ) *out++ = CLIP(a, 0, max); \
-            } \
-            else { \
-                *out++ = r; \
-                *out++ = g; \
-                *out++ = b; \
-                if( components == 4 ) *out++ = a; \
-            } \
- \
-/*  increment the transformed coordinates  */ \
-            tx += xinc;  ty += yinc;  tw += winc; \
-        } \
-    } \
-} break
-
-#define LINEAR_ROW(in_row, chroma_offset) ( !in_row ? 0 : transform_linear(dx, \
-               c0>=min_in_x && c0<max_in_x ? in_row[c0*comps]-chroma_offset : 0, \
-               c1>=min_in_x && c1<max_in_x ? in_row[c1*comps]-chroma_offset : 0) )
-
-#define DO_LINEAR(tag, components, type, temp_type, chroma_offset, max) \
+#define DO_INTERP(tag, interp, components, type, temp_type, chroma, max) \
 case tag: { \
     type **inp_rows = (type**)server->input->get_rows(); \
     type **out_rows = (type**)server->output->get_rows(); \
-    int comps = components; \
     float round_factor = sizeof(type) < 4 ? 0.5 : 0; \
-    for( int y=ty1; y<ty2; ++y ) { \
-        type *out_row = (type*)out_rows[y]; \
- \
-        int x1 = tx1, x2 = tx2; \
-        if( x1 < min_out_x ) x1 = min_out_x; \
-        if( x2 > max_out_x ) x2 = max_out_x; \
-        tx = xinc * x1 + m.values[0][1] * (y + pivot_offset_y) + m.values[0][2] \
-            + pivot_offset_x * xinc; \
-        ty = yinc * x1 + m.values[1][1] * (y + pivot_offset_y) + m.values[1][2] \
-            + pivot_offset_x * yinc; \
-        tw = winc * x1 + m.values[2][1] * (y + pivot_offset_y) + m.values[2][2] \
-            + pivot_offset_x * winc; \
-        type *out = out_row + x1 * comps; \
-        for( int x=x1; x<x2; ++x ) { \
-/* Normalize homogeneous coords */ \
-            if( tw == 0.0 ) { ttx = 0.0; tty = 0.0; } \
-            else { ttx = tx / tw; tty = ty / tw; } \
-            itx = (int)ttx;  ity = (int)tty; \
-/* the fractional error */ \
-            float dx = ttx - itx, dy = tty - ity; \
-            if( dx < 0 ) dx += 1; \
-            if( dy < 0 ) dy += 1; \
-/* row/col index */ \
-            int c0 = itx+0, c1 = itx+1; \
-            int r0 = ity+0, r1 = ity+1; \
-            type *r0p, *r1p; \
-            r0p = r0>=min_in_y && r0<max_in_y ? inp_rows[r0] : 0; \
-            r1p = r1>=min_in_y && r1<max_in_y ? inp_rows[r1] : 0; \
-            temp_type r, g, b, a; \
-            r = (temp_type)(transform_linear(dy, \
-                LINEAR_ROW(r0p, 0x0), LINEAR_ROW(r1p, 0x0)) \
-                + round_factor); \
-            if(r0p) ++r0p;  if(r1p) ++r1p; \
-            g = (temp_type)(transform_linear(dy, \
-                LINEAR_ROW(r0p, chroma_offset), LINEAR_ROW(r1p, chroma_offset)) \
-                + round_factor) + chroma_offset; \
-            if(r0p) ++r0p;  if(r1p) ++r1p; \
-            b = (temp_type)(transform_linear(dy, \
-                LINEAR_ROW(r0p, chroma_offset), LINEAR_ROW(r1p, chroma_offset)) \
-                + round_factor) + chroma_offset; \
-            if( components == 4 ) { \
-                if(r0p) ++r0p;  if(r1p) ++r1p; \
-                a = (temp_type)(transform_linear(dy, \
-                    LINEAR_ROW(r0p, 0x0), LINEAR_ROW(r1p, 0x0)) \
-                    + round_factor); \
-            } \
-            if( sizeof(type) < 4 ) { \
-                *out++ = CLIP(r, 0, max); \
-                *out++ = CLIP(g, 0, max); \
-                *out++ = CLIP(b, 0, max); \
-                if( components == 4 ) *out++ = CLIP(a, 0, max); \
-            } \
-            else { \
-                *out++ = r; \
-                *out++ = g; \
-                *out++ = b; \
-                if( components == 4 ) *out++ = a; \
-            } \
+    INTERP_SETUP(inp_rows, max, min_in_x,min_in_y, max_in_x,max_in_y); \
  \
-/*  increment the transformed coordinates  */ \
-            tx += xinc;  ty += yinc;  tw += winc; \
-        } \
-    } \
-} break
-
-#define DO_NEAREST(tag, components, type, temp_type, chroma_offset, max) \
-case tag: { \
-    type **inp_rows = (type**)server->input->get_rows(); \
-    type **out_rows = (type**)server->output->get_rows(); \
     for( int y=ty1; y<ty2; ++y ) { \
         type *out_row = (type*)out_rows[y]; \
- \
         int x1 = tx1, x2 = tx2; \
         if( x1 < min_out_x ) x1 = min_out_x; \
         if( x2 > max_out_x ) x2 = max_out_x; \
@@ -731,25 +518,21 @@ case tag: { \
         tw = winc * x1 + m.values[2][1] * (y + pivot_offset_y) + m.values[2][2] \
             + pivot_offset_x * winc; \
         type *out = out_row + x1 * components; \
+ \
         for( int x=x1; x<x2; ++x ) { \
 /* Normalize homogeneous coords */ \
             if( tw == 0.0 ) { ttx = 0.0; tty = 0.0; } \
             else { ttx = tx / tw; tty = ty / tw; } \
-            itx = (int)ttx;  ity = (int)tty; \
-/* row/col index */ \
-            type *rp = ity>=min_in_y && ity<max_in_y ? inp_rows[ity] : 0; \
-            temp_type r, g, b, a; \
-            r = (temp_type)( rp && itx>=min_in_x && itx<max_in_x ? rp[itx*components] : 0 ); \
-            if(rp) ++rp; \
-            g = (temp_type)( rp && itx>=min_in_x && itx<max_in_x ? rp[itx*components] : 0 ); \
-            if(rp) ++rp; \
-            b = (temp_type)( rp && itx>=min_in_x && itx<max_in_x ? rp[itx*components] : 0 ); \
+            interp##_SETUP(type, components, ttx, tty); \
+            *out++ = ((temp_type)interp##_interp(0, 0) + round_factor); \
+            interp##_next(); \
+            *out++ = ((temp_type)interp##_interp(chroma, chroma) + round_factor); \
+            interp##_next(); \
+            *out++ = ((temp_type)interp##_interp(chroma, chroma) + round_factor); \
             if( components == 4 ) { \
-                if(rp) ++rp; \
-                a = (temp_type)( rp && itx>=min_in_x && itx<max_in_x ? rp[itx*components] : 0 ); \
+                interp##_next(); \
+                *out++ = ((temp_type)interp##_interp(0, 0) + round_factor); \
             } \
-            *out++ = r;  *out++ = g;  *out++ = b; \
-            if( components == 4 ) *out++ = a; \
  \
 /*  increment the transformed coordinates  */ \
             tx += xinc;  ty += yinc;  tw += winc; \
@@ -763,45 +546,45 @@ case tag: { \
                switch( server->interpolation ) {
                case AffineEngine::AF_NEAREST:
                        switch( server->input->get_color_model() ) {
-                       DO_NEAREST( BC_RGB_FLOAT, 3, float, float, 0x0, 1.0);
-                       DO_NEAREST( BC_RGB888, 3, unsigned char, int, 0x0, 0xff);
-                       DO_NEAREST( BC_RGBA_FLOAT, 4, float, float, 0x0, 1.0);
-                       DO_NEAREST( BC_RGBA8888, 4, unsigned char, int, 0x0, 0xff);
-                       DO_NEAREST( BC_YUV888, 3, unsigned char, int, 0x80, 0xff);
-                       DO_NEAREST( BC_YUVA8888, 4, unsigned char, int, 0x80, 0xff);
-                       DO_NEAREST( BC_RGB161616, 3, uint16_t, int, 0x0, 0xffff);
-                       DO_NEAREST( BC_RGBA16161616, 4, uint16_t, int, 0x0, 0xffff);
-                       DO_NEAREST( BC_YUV161616, 3, uint16_t, int, 0x8000, 0xffff);
-                       DO_NEAREST( BC_YUVA16161616, 4, uint16_t, int, 0x8000, 0xffff);
+                       DO_INTERP( BC_RGB_FLOAT, nearest, 3, float, float, 0x0, 1.0);
+                       DO_INTERP( BC_RGB888, nearest, 3, unsigned char, int, 0x0, 0xff);
+                       DO_INTERP( BC_RGBA_FLOAT, nearest, 4, float, float, 0x0, 1.0);
+                       DO_INTERP( BC_RGBA8888, nearest, 4, unsigned char, int, 0x0, 0xff);
+                       DO_INTERP( BC_YUV888, nearest, 3, unsigned char, int, 0x80, 0xff);
+                       DO_INTERP( BC_YUVA8888, nearest, 4, unsigned char, int, 0x80, 0xff);
+                       DO_INTERP( BC_RGB161616, nearest, 3, uint16_t, int, 0x0, 0xffff);
+                       DO_INTERP( BC_RGBA16161616, nearest, 4, uint16_t, int, 0x0, 0xffff);
+                       DO_INTERP( BC_YUV161616, nearest, 3, uint16_t, int, 0x8000, 0xffff);
+                       DO_INTERP( BC_YUVA16161616, nearest, 4, uint16_t, int, 0x8000, 0xffff);
                        }
                        break;
                case AffineEngine::AF_LINEAR:
                        switch( server->input->get_color_model() ) {
-                       DO_LINEAR( BC_RGB_FLOAT, 3, float, float, 0x0, 1.0);
-                       DO_LINEAR( BC_RGB888, 3, unsigned char, int, 0x0, 0xff);
-                       DO_LINEAR( BC_RGBA_FLOAT, 4, float, float, 0x0, 1.0);
-                       DO_LINEAR( BC_RGBA8888, 4, unsigned char, int, 0x0, 0xff);
-                       DO_LINEAR( BC_YUV888, 3, unsigned char, int, 0x80, 0xff);
-                       DO_LINEAR( BC_YUVA8888, 4, unsigned char, int, 0x80, 0xff);
-                       DO_LINEAR( BC_RGB161616, 3, uint16_t, int, 0x0, 0xffff);
-                       DO_LINEAR( BC_RGBA16161616, 4, uint16_t, int, 0x0, 0xffff);
-                       DO_LINEAR( BC_YUV161616, 3, uint16_t, int, 0x8000, 0xffff);
-                       DO_LINEAR( BC_YUVA16161616, 4, uint16_t, int, 0x8000, 0xffff);
+                       DO_INTERP( BC_RGB_FLOAT, bi_linear, 3, float, float, 0x0, 1.0);
+                       DO_INTERP( BC_RGB888, bi_linear, 3, unsigned char, int, 0x0, 0xff);
+                       DO_INTERP( BC_RGBA_FLOAT, bi_linear, 4, float, float, 0x0, 1.0);
+                       DO_INTERP( BC_RGBA8888, bi_linear, 4, unsigned char, int, 0x0, 0xff);
+                       DO_INTERP( BC_YUV888, bi_linear, 3, unsigned char, int, 0x80, 0xff);
+                       DO_INTERP( BC_YUVA8888, bi_linear, 4, unsigned char, int, 0x80, 0xff);
+                       DO_INTERP( BC_RGB161616, bi_linear, 3, uint16_t, int, 0x0, 0xffff);
+                       DO_INTERP( BC_RGBA16161616, bi_linear, 4, uint16_t, int, 0x0, 0xffff);
+                       DO_INTERP( BC_YUV161616, bi_linear, 3, uint16_t, int, 0x8000, 0xffff);
+                       DO_INTERP( BC_YUVA16161616, bi_linear, 4, uint16_t, int, 0x8000, 0xffff);
                        }
                        break;
                default:
                case AffineEngine::AF_CUBIC:
                        switch( server->input->get_color_model() ) {
-                       DO_CUBIC( BC_RGB_FLOAT, 3, float, float, 0x0, 1.0);
-                       DO_CUBIC( BC_RGB888, 3, unsigned char, int, 0x0, 0xff);
-                       DO_CUBIC( BC_RGBA_FLOAT, 4, float, float, 0x0, 1.0);
-                       DO_CUBIC( BC_RGBA8888, 4, unsigned char, int, 0x0, 0xff);
-                       DO_CUBIC( BC_YUV888, 3, unsigned char, int, 0x80, 0xff);
-                       DO_CUBIC( BC_YUVA8888, 4, unsigned char, int, 0x80, 0xff);
-                       DO_CUBIC( BC_RGB161616, 3, uint16_t, int, 0x0, 0xffff);
-                       DO_CUBIC( BC_RGBA16161616, 4, uint16_t, int, 0x0, 0xffff);
-                       DO_CUBIC( BC_YUV161616, 3, uint16_t, int, 0x8000, 0xffff);
-                       DO_CUBIC( BC_YUVA16161616, 4, uint16_t, int, 0x8000, 0xffff);
+                       DO_INTERP( BC_RGB_FLOAT, bi_cubic, 3, float, float, 0x0, 1.0);
+                       DO_INTERP( BC_RGB888, bi_cubic, 3, unsigned char, int, 0x0, 0xff);
+                       DO_INTERP( BC_RGBA_FLOAT, bi_cubic, 4, float, float, 0x0, 1.0);
+                       DO_INTERP( BC_RGBA8888, bi_cubic, 4, unsigned char, int, 0x0, 0xff);
+                       DO_INTERP( BC_YUV888, bi_cubic, 3, unsigned char, int, 0x80, 0xff);
+                       DO_INTERP( BC_YUVA8888, bi_cubic, 4, unsigned char, int, 0x80, 0xff);
+                       DO_INTERP( BC_RGB161616, bi_cubic, 3, uint16_t, int, 0x0, 0xffff);
+                       DO_INTERP( BC_RGBA16161616, bi_cubic, 4, uint16_t, int, 0x0, 0xffff);
+                       DO_INTERP( BC_YUV161616, bi_cubic, 3, uint16_t, int, 0x8000, 0xffff);
+                       DO_INTERP( BC_YUVA16161616, bi_cubic, 4, uint16_t, int, 0x8000, 0xffff);
                        }
                        break;
                }
@@ -978,7 +761,14 @@ void AffineEngine::process(VFrame *output, VFrame *input, VFrame *temp, int mode
        }
 }
 
-
+void AffineEngine::set_matrix(
+       double in_x1, double in_y1, double in_x2, double in_y2,
+       double out_x1, double out_y1, double out_x2, double out_y2,
+       double out_x3, double out_y3, double out_x4, double out_y4)
+{
+       matrix.set_matrix(in_x1, in_y1, in_x2, in_y2,
+               out_x1, out_y1, out_x2, out_y2, out_x3, out_y3, out_x4, out_y4);
+}
 
 
 void AffineEngine::rotate(VFrame *output,
@@ -1066,15 +856,6 @@ void AffineEngine::rotate(VFrame *output,
        }
 }
 
-void AffineEngine::set_matrix(AffineMatrix *matrix)
-{
-       for( int i=0; i<3; ++i ) {
-               for( int j=0; j<3; ++j ) {
-                       this->matrix.values[i][j] = matrix->values[i][j];
-               }
-       }
-}
-
 void AffineEngine::set_in_viewport(int x, int y, int w, int h)
 {
        this->in_x = x;  this->in_y = y;