rerate can handle interlaced input frames as fields
authorAndreas Eversberg <jolly@eversberg.eu>
Sun, 27 Sep 2015 06:47:47 +0000 (08:47 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Sun, 27 Sep 2015 06:47:47 +0000 (08:47 +0200)
tools/rerate.c

index 6c7ea9f..f2d5cbf 100644 (file)
 
 int flow_window = 30, border = 0;
 double limit_frames = 0;
+int interlace = 0, swap = 0;
+
+static void field_img(int width, int height, unsigned short *img, int odd)
+{
+       int y, x;
+       signed int value;
+
+       /* use even lines: 0, 2, 4... */
+       /* use odd lines: 1, 3, 5... */
+       for (y = (!!odd); y < height-2; y += 2) {
+               for (x = 0; x < width*3; x++) {
+                       value = img[width * y * 3 + x];
+                       value += img[width * (y+2) * 3 + x];
+                       img[width * (y+1) * 3 + x] = (value >> 1);
+               }
+       }
+       /* duplicate border line that can't be interpolated */
+       if (!odd)
+               memcpy(img + width * (height-1) * 3, img + width * (height-2) * 3, width * 3 * sizeof(unsigned short));
+       else
+               memcpy(img, img + width * 3, width * 3 * sizeof(unsigned short));
+}
 
 static inline void smooth_pixle(double *array, int width, int height, int i, int j)
 {
@@ -298,10 +320,13 @@ static void print_help(const char *app)
        printf(" -b --border <pixles> Remove border pixles, if darker than image (try 1)\n");
        printf(" -w --window <size>   Change optical flow window size (default %d)\n", flow_window);
        printf(" -f --frames <number> Limit number of input frames (default infinite)\n");
+       printf(" -i --interlace       Handle input image as interlaced image\n");
+       printf("                      Note: oldfps refers to frames, not the individual fields\n");
+       printf(" -e --even            Use even lines for first field, instead of odd lines\n");
        printf(" input                Input image sequence (e.g. input_%%05d.ppm)\n");
        printf(" output               Output image sequence (e.g. output_%%05d.ppm)\n");
        printf(" first                Index of first input and output image\n");
-       printf(" oldfps               Old frame rate\n");
+       printf(" oldfps               Old frame rate (complete frames in case of interlace)\n");
        printf(" newfps               New frame rate\n");
 }
 
@@ -317,10 +342,12 @@ static int handle_options(int argc, char **argv)
                        {"border", 1, 0, 'b'},
                        {"window", 1, 0, 'w'},
                        {"frames", 1, 0, 'f'},
+                       {"interlace", 0, 0, 'i'},
+                       {"even", 0, 0, 'e'},
                        {0, 0, 0, 0},
                };
 
-               c = getopt_long(argc, argv, "hd:b:w:f:", long_options, &option_index);
+               c = getopt_long(argc, argv, "hd:b:w:f:ie", long_options, &option_index);
 
                if (c == -1)
                        break;
@@ -345,6 +372,14 @@ static int handle_options(int argc, char **argv)
                        limit_frames = atoi(optarg);
                        skip_args += 2;
                        break;
+               case 'i':
+                       interlace = 1;
+                       skip_args++;
+                       break;
+               case 'e':
+                       swap = 1;
+                       skip_args++;
+                       break;
                default:
                        break;
                }
@@ -391,15 +426,29 @@ next_frame:
        offset = inputframe - baseframe;
        if (offset < 0.001)
                offset = 0.0;
+       else if (interlace && offset < 0.501 && offset > 0.499)
+               offset = 0.5;
        else if (offset > 0.999) {
                offset = 0.0;
                baseframe++;
        }
-       if (offset == 0.0) {
-               printf("Copy input frame %d, output frame %d\n", (int)baseframe, outputframe);
+       if (offset == 0.0 || (interlace && offset == 0.5)) {
+               if (interlace) {
+                       if (offset < 0.5)
+                               printf("Copy input frame %d (first field), output frame %d\n", (int)baseframe, outputframe);
+                       else
+                               printf("Copy input frame %d (second field), output frame %d\n", (int)baseframe, outputframe);
+               } else
+                       printf("Copy input frame %d, output frame %d\n", (int)baseframe, outputframe);
                res = load_img(&width, &height, inputname, baseframe);
                if (!res)
                        goto end;
+               if (interlace) {
+                       if (offset < 0.5)
+                               field_img(width, height, res, (!swap)); // first field
+                       else
+                               field_img(width, height, res, swap); // second field
+               }
                rc = save_img(res, width, height, 0, outputname, outputframe);
                if (rc < 0)
                        goto out;
@@ -408,9 +457,21 @@ next_frame:
                img1 = load_img(&width, &height, inputname, baseframe);
                if (!img1)
                        goto end;
-               img2 = load_img(&width2, &height2, inputname, baseframe+1);
-               if (!img2)
-                       goto end;
+               if (interlace && offset < 0.5) {
+                       field_img(width, height, img1, (!swap)); // first field of baseframe
+                       img2 = load_img(&width2, &height2, inputname, baseframe);
+                       if (!img2)
+                               goto end;
+                       field_img(width2, height2, img2, swap); // second field of baseframe
+               } else {
+                       img2 = load_img(&width2, &height2, inputname, baseframe+1);
+                       if (!img2)
+                               goto end;
+                       if (interlace) {
+                               field_img(width, height, img1, swap); // second field of baseframe
+                               field_img(width2, height2, img2, (!swap)); // first field of baseframe+1
+                       }
+               }
                if (width != width2) {
                        printf("Frame %d and %d have different width (%d != %d)\n", (int)baseframe, (int)baseframe+1, width, width2);
                        goto out;
@@ -419,10 +480,20 @@ next_frame:
                        printf("Frame %d and %d have different height (%d != %d)\n", (int)baseframe, (int)baseframe+1, height, height2);
                        goto out;
                }
+               if (interlace && (height & 1)) {
+                       printf("Interlaced frame %d must have even number of lines (not %d)\n", (int)baseframe, height);
+                       goto out;
+               }
                res = malloc(width * height * 3 * sizeof(unsigned short));
                if (!res)
                        goto out;
-               rc = interpolate(img1, img2, res, width, height, offset, (int)baseframe);
+               if (interlace) {
+                       if (offset < 0.5)
+                               rc = interpolate(img1, img2, res, width, height, offset * 2.0, ((int)baseframe) * 2);
+                       else
+                               rc = interpolate(img1, img2, res, width, height, (offset * 2.0) - 1.0, ((int)baseframe) * 2 + 1);
+               } else
+                       rc = interpolate(img1, img2, res, width, height, offset, (int)baseframe);
                if (rc < 0)
                        goto out;
                rc = save_img(res, width, height, 0, outputname, outputframe);