Commits

Francesco Romani committed 08c41b0

[filter][vid.stab] bump vid.stab to 0.79

Apply missing changes from patchset 0.77.

Comments (0)

Files changed (4)

filter/stabilize/filter_stabilize.c

 */
 
 #define MOD_NAME    "filter_stabilize.so"
-#define MOD_VERSION "v0.79 (2011-10-12)"
+#define MOD_VERSION "v0.80 (2011-11-13)"
 #define MOD_CAP     "extracts relative transformations of \n\
     subsequent frames (used for stabilization together with the\n\
     transform filter in a second pass)"

filter/stabilize/filter_transform.c

 */
 
 #define MOD_NAME    "filter_transform.so"
-#define MOD_VERSION "v0.79 (2011-10-12)"
+#define MOD_VERSION "v0.80 (2011-11-13)"
 #define MOD_CAP     "transforms each frame according to transformations\n\
  given in an input file (e.g. translation, rotate) see also filter stabilize"
 #define MOD_AUTHOR  "Georg Martius"
 
 #define PIXEL(img, x, y, w, h, def) ((x) < 0 || (y) < 0) ? def       \
     : (((x) >=w || (y) >= h) ? def : img[(x) + (y) * w]) 
+#define PIX(img, x, y, w, h) (img[(x) + (y) * w]) 
 // gives Pixel in N-channel image. channel in {0..N-1}
 #define PIXELN(img, x, y, w, h, N,channel , def) ((x) < 0 || (y) < 0) ? def  \
     : (((x) >=w || (y) >= h) ? def : img[((x) + (y) * w)*N + channel]) 
     Transform* trans;    // array of transformations
     int current_trans;   // index to current transformation
     int trans_len;       // length of trans array
+    short warned_transform_end; // whether we warned that there is no transform left
  
     /* Options */
     int maxshift;        // maximum number of pixels we will shift
     char conf_str[TC_BUF_MIN];
 } TransformData;
 
-static const char* interpoltypes[4] = {"No", "Linear", "Bi-Linear", "Quadratic"};
+static const char* interpoltypes[5] = {"No (0)", "Linear (1)", "Bi-Linear (2)", 
+                                       "Quadratic (3)", "Bi-Cubic (4)"};
 
 static const char transform_help[] = ""
     "Overview\n"
     "                Note that the value given at 'zoom' is added to the \n"
     "                here calculated one\n"
     "    'interpol'  type of interpolation: 0: no interpolation, \n"
-    "                1: linear (horizontal) (def), 2: bi-linear 3: quadratic\n"
+    "                1: linear (horizontal), 2: bi-linear (def), \n"
+    "                3: quadratic 4: bi-cubic\n"
     "    'sharpen'   amount of sharpening: 0: no sharpening (def: 0.8)\n"
     "                uses filter unsharp with 5x5 matrix\n"
     "    'help'      print this help message\n";
 
 /* forward deklarations, please look below for documentation*/
+void interpolateBiLinBorder(unsigned char *rv, float x, float y, 
+                          unsigned char* img, int w, int h, unsigned char def);
+void interpolateBiCub(unsigned char *rv, float x, float y, 
+                      unsigned char* img, int width, int height, unsigned char def);
 void interpolateSqr(unsigned char *rv, float x, float y, 
                     unsigned char* img, int w, int h, unsigned char def);
 void interpolateBiLin(unsigned char *rv, float x, float y, 
                     unsigned char* img, int width, int height, 
                     unsigned char def) = 0;
 
+/** interpolateBiLinBorder: bi-linear interpolation function that also works at the border.
+    This is used by many other interpolation methods at and outsize the border, see interpolate */
+void interpolateBiLinBorder(unsigned char *rv, float x, float y, 
+                            unsigned char* img, int width, int height, 
+                            unsigned char def)
+{
+    int x_f = myfloor(x);
+    int x_c = x_f+1;
+    int y_f = myfloor(y);
+    int y_c = y_f+1;
+    short v1 = PIXEL(img, x_c, y_c, width, height, def);
+    short v2 = PIXEL(img, x_c, y_f, width, height, def);
+    short v3 = PIXEL(img, x_f, y_c, width, height, def);
+    short v4 = PIXEL(img, x_f, y_f, width, height, def);        
+    float s  = (v1*(x - x_f)+v3*(x_c - x))*(y - y_f) + 
+        (v2*(x - x_f) + v4*(x_c - x))*(y_c - y);
+    *rv = (unsigned char)s;
+}
+
+/* taken from http://en.wikipedia.org/wiki/Bicubic_interpolation for alpha=-0.5
+   in matrix notation: 
+   a0-a3 are the neigthboring points where the target point is between a1 and a2
+   t is the point of interpolation (position between a1 and a2) value between 0 and 1
+                 | 0, 2, 0, 0 |  |a0|
+                 |-1, 0, 1, 0 |  |a1|
+   (1,t,t^2,t^3) | 2,-5, 4,-1 |  |a2|
+                 |-1, 3,-3, 1 |  |a3|              
+*/
+static short bicub_kernel(float t, short a0, short a1, short a2, short a3){ 
+    return (2*a1 + t*((-a0+a2) + t*((2*a0-5*a1+4*a2-a3) + t*(-a0+3*a1-3*a2+a3) )) ) / 2;
+}
+
+/** interpolateBiCub: bi-cubic interpolation function using 4x4 pixel, see interpolate */
+void interpolateBiCub(unsigned char *rv, float x, float y, 
+                      unsigned char* img, int width, int height, unsigned char def)
+{
+    // do a simple linear interpolation at the border
+    if (x < 1 || x > width-2 || y < 1 || y > height - 2) { 
+        interpolateBiLinBorder(rv, x,y,img,width,height,def);    
+    } else {
+        int x_f = myfloor(x);
+        int y_f = myfloor(y);
+        float tx = x-x_f;
+        short v1 = bicub_kernel(tx,
+                                PIX(img, x_f-1, y_f-1, width, height),
+                                PIX(img, x_f,   y_f-1, width, height),
+                                PIX(img, x_f+1, y_f-1, width, height),
+                                PIX(img, x_f+2, y_f-1, width, height));
+        short v2 = bicub_kernel(tx,
+                                PIX(img, x_f-1, y_f, width, height),
+                                PIX(img, x_f,   y_f, width, height),
+                                PIX(img, x_f+1, y_f, width, height),
+                                PIX(img, x_f+2, y_f, width, height));
+        short v3 = bicub_kernel(tx,
+                                PIX(img, x_f-1, y_f+1, width, height),
+                                PIX(img, x_f,   y_f+1, width, height),
+                                PIX(img, x_f+1, y_f+1, width, height),
+                                PIX(img, x_f+2, y_f+1, width, height));
+        short v4 = bicub_kernel(tx,
+                                PIX(img, x_f-1, y_f+2, width, height),
+                                PIX(img, x_f,   y_f+2, width, height),
+                                PIX(img, x_f+1, y_f+2, width, height),
+                                PIX(img, x_f+2, y_f+2, width, height));
+        *rv = (unsigned char)bicub_kernel(y-y_f, v1, v2, v3, v4);
+    }
+}
+
 /** interpolateSqr: bi-quatratic interpolation function, see interpolate */
 void interpolateSqr(unsigned char *rv, float x, float y, 
                     unsigned char* img, int width, int height, unsigned char def)
 {
-    if (x < - 1 || x > width || y < -1 || y > height) {
-        *rv = def;    
+    if (x < 0 || x > width-1 || y < 0 || y > height - 1) { 
+        interpolateBiLinBorder(rv, x, y, img, width, height, def);    
     } else {
-        int x_c = (int)ceilf(x);
-        int x_f = (int)floorf(x);
-        int y_c = (int)ceilf(y);
-        int y_f = (int)floorf(y);
-        short v1 = PIXEL(img, x_c, y_c, width, height, def);
-        short v2 = PIXEL(img, x_c, y_f, width, height, def);
-        short v3 = PIXEL(img, x_f, y_c, width, height, def);
-        short v4 = PIXEL(img, x_f, y_f, width, height, def);
-        float f1 = 1 - sqrt(fabs(x_c - x) * fabs(y_c - y));
-        float f2 = 1 - sqrt(fabs(x_c - x) * fabs(y_f - y));
-        float f3 = 1 - sqrt(fabs(x_f - x) * fabs(y_c - y));
-        float f4 = 1 - sqrt(fabs(x_f - x) * fabs(y_f - y));
+        int x_f = myfloor(x);
+        int x_c = x_f+1;
+        int y_f = myfloor(y);
+        int y_c = y_f+1;
+        short v1 = PIX(img, x_c, y_c, width, height);
+        short v2 = PIX(img, x_c, y_f, width, height);
+        short v3 = PIX(img, x_f, y_c, width, height);
+        short v4 = PIX(img, x_f, y_f, width, height);
+        float f1 = 1 - sqrt((x_c - x) * (y_c - y));
+        float f2 = 1 - sqrt((x_c - x) * (y - y_f));
+        float f3 = 1 - sqrt((x - x_f) * (y_c - y));
+        float f4 = 1 - sqrt((x - x_f) * (y - y_f));
         float s  = (v1*f1 + v2*f2 + v3*f3+ v4*f4)/(f1 + f2 + f3 + f4);
-        *rv = (unsigned char)s;
+        *rv = (unsigned char)s;   
     }
 }
 
                       unsigned char* img, int width, int height, 
                       unsigned char def)
 {
-    if (x < - 1 || x > width || y < -1 || y > height) {
-        *rv = def;    
+    if (x < 0 || x > width-1 || y < 0 || y > height - 1) { 
+        interpolateBiLinBorder(rv, x, y, img, width, height, def);    
     } else {
-        int x_c = (int)ceilf(x);
-        int x_f = (int)floorf(x);
-        if(x_f==x_c) x_c++;
-        int y_c = (int)ceilf(y);
-        int y_f = (int)floorf(y);
-        if(y_f==y_c) y_c++;
-        short v1 = PIXEL(img, x_c, y_c, width, height, def);
-        short v2 = PIXEL(img, x_c, y_f, width, height, def);
-        short v3 = PIXEL(img, x_f, y_c, width, height, def);
-        short v4 = PIXEL(img, x_f, y_f, width, height, def);        
-        float s  = (v1*(x - x_f)*(y - y_f) + v2*((x - x_f)*(y_c - y)) + 
-                    v3*(x_c - x)*(y - y_f) + v4*((x_c - x)*(y_c - y)));
+        int x_f = myfloor(x);
+        int x_c = x_f+1;
+        int y_f = myfloor(y);
+        int y_c = y_f+1;
+        short v1 = PIX(img, x_c, y_c, width, height);
+        short v2 = PIX(img, x_c, y_f, width, height);
+        short v3 = PIX(img, x_f, y_c, width, height);
+        short v4 = PIX(img, x_f, y_f, width, height);        
+        float s  = (v1*(x - x_f)+v3*(x_c - x))*(y - y_f) +  
+            (v2*(x - x_f) + v4*(x_c - x))*(y_c - y);
         *rv = (unsigned char)s;
     }
 }
 
+
 /** interpolateLin: linear (only x) interpolation function, see interpolate */
 void interpolateLin(unsigned char *rv, float x, float y, 
                     unsigned char* img, int width, int height, 
                     unsigned char def)
 {
-    if (x < - 1 || x > width || y < -1 || y > height) {
-        *rv = def;    
-    } else {
-        int x_c = (int)ceilf(x);
-        int x_f = (int)floorf(x);
-        if(x_f==x_c) x_c++;
-        int y_n = myround(y);
-        float v1 = PIXEL(img, x_c, y_n, width, height, def);
-        float v2 = PIXEL(img, x_f, y_n, width, height, def);
-        float s  = v1*(x - x_f) + v2*(x_c - x);
-        *rv = (unsigned char)s;
-    }
+    int x_f = myfloor(x);
+    int x_c = x_f+1;
+    int y_n = myround(y);
+    float v1 = PIXEL(img, x_c, y_n, width, height, def);
+    float v2 = PIXEL(img, x_f, y_n, width, height, def);
+    float s  = v1*(x - x_f) + v2*(x_c - x);
+    *rv = (unsigned char)s;
 }
 
 /** interpolateZero: nearest neighbor interpolation function, see interpolate */
 void interpolateZero(unsigned char *rv, float x, float y, 
                    unsigned char* img, int width, int height, unsigned char def)
 {
-    if (x < - 1 || x > width || y < -1 || y > height) {
-        *rv = def;    
-    } else {
-        int x_n = myround(x);
-        int y_n = myround(y);
-        *rv = (unsigned char) PIXEL(img, x_n, y_n, width, height, def);
-    }
+    int x_n = myround(x);
+    int y_n = myround(y);
+    *rv = (unsigned char) PIXEL(img, x_n, y_n, width, height, def);
 }
 
 
 /** 
- * interpolateN: quatratic interpolation function for N channel image. 
+ * interpolateN: Bi-linear interpolation function for N channel image. 
  *
  * Parameters:
  *             rv: destination pixel (call by reference)
     if (x < - 1 || x > width || y < -1 || y > height) {
         *rv = def;    
     } else {
-        int x_c = (int)ceilf(x);
-        int x_f = (int)floorf(x);
-        int y_c = (int)ceilf(y);
-        int y_f = (int)floorf(y);
+        int x_f = myfloor(x);
+        int x_c = x_f+1;
+        int y_f = myfloor(y);
+        int y_c = y_f+1;
         short v1 = PIXELN(img, x_c, y_c, width, height, N, channel, def);
         short v2 = PIXELN(img, x_c, y_f, width, height, N, channel, def);
         short v3 = PIXELN(img, x_f, y_c, width, height, N, channel, def);
-        short v4 = PIXELN(img, x_f, y_f, width, height, N, channel, def);
-        float f1 = 1 - sqrt(fabs(x_c - x) * fabs(y_c - y));
-        float f2 = 1 - sqrt(fabs(x_c - x) * fabs(y_f - y));
-        float f3 = 1 - sqrt(fabs(x_f - x) * fabs(y_c - y));
-        float f4 = 1 - sqrt(fabs(x_f - x) * fabs(y_f - y));
-        float s  = (v1*f1 + v2*f2 + v3*f3+ v4*f4)/(f1 + f2 + f3 + f4);
-        *rv = (unsigned char)s;
+        short v4 = PIXELN(img, x_f, y_f, width, height, N, channel, def);        
+        float s  = (v1*(x - x_f)+v3*(x_c - x))*(y - y_f) + 
+            (v2*(x - x_f) + v4*(x_c - x))*(y_c - y);
+        *rv = (unsigned char)s;        
     }
 }
 
     td = self->userdata;
 
     td->vob = vob;
-    if (!td->vob) {
+    if (!td->vob)
         return TC_ERROR; /* cannot happen */
-    }
+
     /**** Initialise private data structure */
 
     /* td->framesize = td->vob->im_v_width *
     td->trans = 0;
     td->trans_len = 0;
     td->current_trans = 0;
-  
+    td->warned_transform_end = 0;  
+
     /* Options */
     td->maxshift = -1;
     td->maxangle = -1;
 
     td->zoom    = 0;
     td->optzoom = 1;
-    td->interpoltype = 1;
+    td->interpoltype = 2; // bi-linear
     td->sharpen = 0.8;
   
     if (options != NULL) {
         optstr_get(options, "interpol" , "%d", &td->interpoltype);
         optstr_get(options, "sharpen"  , "%lf",&td->sharpen);
     }
-    td->interpoltype = TC_MIN(td->interpoltype,3);
+    td->interpoltype = TC_MIN(td->interpoltype,4);
     if (verbose) {
         tc_log_info(MOD_NAME, "Image Transformation/Stabilization Settings:");
         tc_log_info(MOD_NAME, "    input     = %s", td->input);
         return TC_ERROR;            
     }  
 
-    /* if we keep the borders, we need a second buffer to store
-       the previous stabilized frame. */
-    if (td->crop == 0) {
+    // if we keep the borders, we need a second buffer so store 
+    //  the previous stabilized frame
+    if(td->crop == 0){ 
         td->dest = tc_malloc(td->framesize_dest);
         if (td->dest == NULL) {
+            tc_log_error(MOD_NAME, "tc_malloc failed\n");
             return TC_ERROR;
         }
     }
       case 1:  interpolate = &interpolateLin; break;
       case 2:  interpolate = &interpolateBiLin; break;
       case 3:  interpolate = &interpolateSqr; break;
-      default: interpolate = &interpolateZero;
+      case 4:  interpolate = &interpolateBiCub; break;
+      default: interpolate = &interpolateBiLin;
     }
 
     /* Is this the right point to add the filter? Seems to be the case.*/
-    if (td->sharpen > 0) {
+    if(td->sharpen>0){
         /* load unsharp filter */
         char unsharp_param[256];
         sprintf(unsharp_param,"luma=%f:%s:chroma=%f:%s", 
             tc_log_warn(MOD_NAME, "cannot load unsharp filter!");
         }
     }
-
+    
     return TC_OK;
 }
 
     TC_MODULE_SELF_CHECK(frame, "filter_video");
   
     td = self->userdata;
-
+            
     memcpy(td->src, frame->video_buf, td->framesize_src);
-    if (td->crop == 0) {
-        if (frame->id == 0) {
-            /* if we keep borders, then save the first frame into the
-               background buffer (dest) */
+    if (td->crop == 0) { 
+        if(frame->id == 0) {
+            // if we keep borders, save first frame into the background buffer (dest)
             memcpy(td->dest, frame->video_buf, td->framesize_src);
         }
-    } else { /* otherwise we directly operate on the framebuffer */
+    }else{ // otherwise we directly operate on the framebuffer
         td->dest = frame->video_buf;
     }
-    if (td->current_trans >= td->trans_len) {
-        tc_log_error(MOD_NAME, "not enough transforms found!\n");
-        return TC_ERROR;
+    if (td->current_trans >= td->trans_len) {        
+        td->current_trans = td->trans_len-1;
+        if(!td->warned_transform_end)
+            tc_log_warn(MOD_NAME, "not enough transforms found, use last transformation!\n");
+        td->warned_transform_end = 1;        
     }
   
     if (td->vob->im_v_codec == CODEC_RGB) {
         tc_log_error(MOD_NAME, "unsupported Codec: %i\n", td->vob->im_v_codec);
         return TC_ERROR;
     }
-    if (td->crop == 0) {
-        /* note: dest stores the stabilized frame to be the default
-           for the next frame */
+    if(td->crop == 0){ 
+        // note: dest stores stabilized frame to be the default for next frame
         memcpy(frame->video_buf, td->dest, td->framesize_src);
     }
+
     td->current_trans++;
     return TC_OK;
 }
         tc_free(td->src);
         td->src = NULL;
     }
-    if (td->crop == 0) {
-        /* if we keep the borders, we need a second buffer to store
-           the previous stabilized frame. */
-        tc_free(td->dest);
-        td->dest = NULL;
-    }
     if (td->trans) {
         tc_free(td->trans);
         td->trans = NULL;
 }
 
 /* checks for parameter in function _inspect */
-#define CHECKPARAM(paramname, formatstring, variable) do { \
-    if (optstr_lookup(param, paramname)) {                 \
-        tc_snprintf(td->conf_str, sizeof(td->conf_str),    \
-                    formatstring, variable);               \
-        *value = td->conf_str;                             \
-    }                                                      \
-} while (0)
+#define CHECKPARAM(paramname, formatstring, variable)       \
+    if (optstr_lookup(param, paramname)) {                \
+        tc_snprintf(td->conf_str, sizeof(td->conf_str),   \
+                    formatstring, variable);              \
+        *value = td->conf_str;                            \
+    }
 
 /**
  * stabilize_inspect:  Return the value of an option in this instance of

filter/stabilize/transform.c

 #include <math.h>
 #include "transform.h"
 
-/* normal round function */
-int myround(double x)
-{
-    double x_;
-    x_ = floor(x);
-    if (x - x_ >= 0.5)
-        return ((int)x_) + 1;
-    else
-        return (int)x_;
-}
-
-
 /***********************************************************************
  * helper functions to create and operate with transforms.
  * all functions are non-destructive

filter/stabilize/transform.h

                               int percentil, 
                               Transform* min, Transform* max);
 
-/* helper functions that should be in math.h! */
+/* helper functions */
 
-/* normal round function */
-int myround(double x);
+/* optimized round function */
+inline static int myround(float x) {
+    if(x>0)
+        return x + 0.5;
+    else
+        return x - 0.5;
+}
+
+
+/* optimized floor function 
+   This does not give the correct value for negative integer values like -1.0. In this case
+   it will produce -2.0.
+*/
+inline static int myfloor(float x) {
+    if(x<0)
+        return x - 1;
+    else
+        return x;
+}
+
 
 #endif
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.