add option to store rendered image at a different prefix
[colorize.git] / src / colorize.c
index db604f7..fe50913 100644 (file)
@@ -7,16 +7,16 @@
 #include <time.h>
 #include "../lib/darray.h"
 #include "../lib/colorize.h"
-#include "ppm.h"
+#include "img.h"
 #include "yuv.h"
 #include "mark.h"
+#include "process.h"
+#include "settings.h"
 #include "dir_seperator.h"
 #ifdef WITH_OPENCV
 #include "opticalflow.h"
 #endif
 
-#define min(x,y) ((x < y) ? x : y)
-
 static void print_help(const char *app);
 static void print_test_help();
 
@@ -181,83 +181,14 @@ again:
 }
 
 /*
- * scaling
- */
-
-/* scale down image in img_buffer by calculating average */
-static void scale_img(unsigned short *img_buffer, int width, int height, int scale)
-{
-       int w, h, i, j, x, y;
-       int r, g, b;
-
-       if (scale == 1)
-               return;
-
-       w = width / scale;
-       h = height / scale;
-
-       for (i = 0; i < h; i++) {
-               for (j = 0; j < w; j++) {
-                       r = g = b = 0;
-                       for (y = 0; y < scale; y++) {
-                               for (x = 0; x < scale; x++) {
-                                       r += img_buffer[((i*scale+y) * width + j*scale+x) * 3 + 0];
-                                       g += img_buffer[((i*scale+y) * width + j*scale+x) * 3 + 1];
-                                       b += img_buffer[((i*scale+y) * width + j*scale+x) * 3 + 2];
-                               }
-                       }
-                       img_buffer[(i * w + j)*3 + 0] = r / scale / scale;
-                       img_buffer[(i * w + j)*3 + 1] = g / scale / scale;
-                       img_buffer[(i * w + j)*3 + 2] = b / scale / scale;
-               }
-       }
-}
-
-/* scale down mark map in mark_buffer */
-static void scale_mark(unsigned char *mark_buffer, int width, int height, int scale)
-{
-       int w, h, i, j, x, y;
-       unsigned char c, temp;
-
-       if (scale == 1)
-               return;
-
-       w = width / scale;
-       h = height / scale;
-
-       for (i = 0; i < h; i++) {
-               for (j = 0; j < w; j++) {
-                       c = 0;
-                       /* always use one index other than 0, if there is any in an areaa to be shrinked */
-                       for (y = 0; y < scale; y++) {
-                               for (x = 0; x < scale; x++) {
-                                       temp = mark_buffer[(i*scale+y) * width + j*scale+x];
-                                       if (temp)
-                                               c = temp;
-                               }
-                       }
-                       mark_buffer[i * w + j] = c;
-               }
-       }
-}
-
-/*
  * options
  */
 
-static int in_itr_num = 5, out_itr_num = 1, optical_flow = 1, bright_contrast = 1;
+static int in_itr_num = 5, out_itr_num = 1, quick = 0, optical_flow = 1, bright_contrast = 1, alpha_change = 1;
 int scale = 1, scalexyz = 999;
+static char output_prefix[256] = "";
 
-static enum test {
-       NO_TEST = 0,
-       FLOW_NEXT,
-       FLOW_PREV,
-       MARKED,
-       MASK,
-       MASK_COLOR,
-       BC_ONLY,
-       BC_IMAGE,
-} test = NO_TEST;
+static enum test test = NO_TEST;
 
 static int parse_test(const char *arg)
 {
@@ -281,6 +212,12 @@ static int parse_test(const char *arg)
                return BC_ONLY;
        if (!strcmp(arg, "bc-image"))
                return BC_IMAGE;
+       if (!strcmp(arg, "alpha"))
+               return ALPHA;
+       if (!strcmp(arg, "no-alpha"))
+               return NO_ALPHA;
+       if (!strcmp(arg, "removal-image"))
+               return REMOVAL_IMAGE;
 
        return NO_TEST;
 }
@@ -294,8 +231,10 @@ static int handle_options(int argc, char **argv)
                static struct option long_options[] = {
                        {"help", 0, 0, 'h'},
                        {"depth", 1, 0, 'd'},
+                       {"output-prefix", 1, 0, 'O'},
                        {"in-itr-num", 1, 0, 'i'},
                        {"out-itr-num", 1, 0, 'o'},
+                       {"quick", 0, 0, 'q'},
                        {"zscale", 1, 0, 'z'},
                        {"brightness-contrast", 1, 0, 'b'},
                        {"optical-flow", 1, 0, 'f'},
@@ -304,7 +243,7 @@ static int handle_options(int argc, char **argv)
                        {0, 0, 0, 0},
                };
 
-               c = getopt_long(argc, argv, "hd:i:o:z:b:f:s:t:", long_options, &option_index);
+               c = getopt_long(argc, argv, "hd:O:i:o:qz:b:f:s:t:", long_options, &option_index);
 
                if (c == -1)
                        break;
@@ -317,6 +256,10 @@ static int handle_options(int argc, char **argv)
                        save_depth = atoi(optarg);
                        skip_args += 2;
                        break;
+               case 'O':
+                       strcpy(output_prefix, optarg);
+                       skip_args += 2;
+                       break;
                case 'i':
                        in_itr_num = atoi(optarg);
                        skip_args += 2;
@@ -325,6 +268,10 @@ static int handle_options(int argc, char **argv)
                        out_itr_num = atoi(optarg);
                        skip_args += 2;
                        break;
+               case 'q':
+                       quick = 1;
+                       skip_args += 1;
+                       break;
                case 'z':
                        scalexyz = atoi(optarg);
                        skip_args += 2;
@@ -333,6 +280,10 @@ static int handle_options(int argc, char **argv)
                        bright_contrast = atoi(optarg);
                        skip_args += 2;
                        break;
+               case 'a':
+                       alpha_change = atoi(optarg);
+                       skip_args += 2;
+                       break;
                case 'f':
                        optical_flow = atoi(optarg);
                        skip_args += 2;
@@ -367,7 +318,7 @@ static void print_help(const char *app)
 #include "../version.h"
        );
        printf("Usage: %s [options] <grey ppm image> <marked ppm image> <result ppm image> [<frames> <start>]\n", app);
-       printf("       Colorize grey image using maked image and save to result image.\n");
+       printf("       Colorize grey image using marked image and save to result image.\n");
        printf("       If frames and start frame is given, image names must include printf integer formatting (e.g. %%04d).\n");
        printf("Usage: %s [options] <grey ppm image> marked <result ppm image>\n", app);
        printf("       Colorize grey image using marked mask + palette and save to result image.\n");
@@ -377,14 +328,17 @@ static void print_help(const char *app)
        printf("\nOptions:\n");
        printf(" -h --help                           This help\n");
        printf(" -d --depth <bits>                   Save images with given color bit depth (default=%d)\n", save_depth);
+       printf(" -O --output-prefix <path>/<prefix>  Store result image of a sequence using this prefix\n");
        printf(" -i --in-itr-num <num>               Alter inner iterations (weightening count) of colorization algorithm (default=%d)\n", in_itr_num);
        printf(" -o --out-itr-num <num>              Alter outer iterations (complete turns) of colorization algorithm (default=%d)\n", out_itr_num);
+       printf(" -q --quick                          Use quick render, but sufaces may be colorized incomplete\n");
        printf(" -z --zscale <levels>                How many grids (staring with the finest) should be scaled in z direction to generate the next coarse grid ");
        if (scalexyz < 999)
                printf("(default=%d)\n", scalexyz);
        else
                printf("(default=infinite)\n");
        printf(" -b --brightness-contrast [0 | 1]    Apply brightnes and contrast, if defined in palette by GUI (default=%d)\n", bright_contrast);
+       printf(" -a --alpha-change [0 | 1]           Apply alpha channel change, if defined in palette by GUI (default=%d)\n", alpha_change);
 #ifdef WITH_OPENCV
        printf(" -f --optical-flow [0 | 1]           Apply optical flow, if defined by GUI (default=%d)\n", optical_flow);
 #endif
@@ -399,11 +353,14 @@ static void print_test_help()
        printf("           flow-next     Optical flow plane to next image\n");
        printf("           flow-prev     Optical flow plane to previous image\n");
 #endif
-       printf("           marked        Only apply makred colors to grey image\n");
+       printf("           marked        Only apply marked colors to grey image\n");
        printf("           mask          Show mask of marked areas\n");
        printf("           mask+color    Show mask of marked areas + color\n");
        printf("           bc-only       Only apply brightness+contrast, leave colors of grey image as is\n");
        printf("           bc-image      Show brightness+contrast change on grey image as uv components\n");
+       printf("           alpha         Show the image with alpha channel only\n");
+       printf("           no-alpha      Show the image without alpha channel, to see pixles that are made transparent\n");
+       printf("           removal-image Show the image with \"transparency removal layer\" only, but keep u and v\n");
 }
 
 /*
@@ -412,20 +369,21 @@ static void print_test_help()
 
 int main(int argc, char *argv[])
 {
-       darray_t *gI = NULL, *cI = NULL, *markIm = NULL, *ntscIm = NULL;
+       darray_t *gI = NULL, *cI = NULL, *mI = NULL, *I = NULL;
        darray_t *flow = NULL, *flow_i = NULL;
-       double *ptr, *ptr2, *ptr3;
+       double *ptr_gI = NULL, *ptr_cI = NULL, *ptr_y = NULL, *ptr_u = NULL, *ptr_v = NULL, *ptr_a = NULL, *ptr_r = NULL, *ptr_b = NULL, *ptr_c = NULL, *ptr_m = NULL;
        double diff, sum;
        int dims[4];
        int w = 0, h = 0, load_w, load_h, k = 1, index = 0, z;
-       unsigned short *img_buffer, *img_buffer_all = NULL;
+       unsigned short *img = NULL;
        unsigned char *mark_buffer = NULL;
        int rc, x, y, i, ii;
        time_t start, end;
        const char* filename;
        char first_filename[256];
        int seq_offset = 0, seq_next = 0;
-       int features, change_bc;
+       int features, change_bc, change_alpha;
+       char *feat_names[20];
        int skip_args;
 
        skip_args = handle_options(argc, argv);
@@ -464,7 +422,7 @@ next_sequence:
 
        time(&start);
 
-       change_bc = 0;
+       change_bc = change_alpha = 0;
        for (z = 0; z < k; z++) {
                if (sequence) {
                        filename = sequence[z].filename;
@@ -475,10 +433,13 @@ next_sequence:
                }
 #ifdef WITH_OPENCV
                // load flow settings
-               if (sequence || !strcmp(argv[2], "marked")) {
+               if (sequence && optical_flow)
                        flow_default();
-                       if (optical_flow)
-                               load_flow(first_filename);
+#endif
+               load_settings(first_filename);
+#ifdef WITH_OPENCV
+               // load flow settings
+               if (sequence && optical_flow) {
                        if (flow_enable == 0 && (test == FLOW_NEXT || test == FLOW_PREV)) {
                                fprintf(stderr, "Cannot test optical flow, because it is not enabled by GUI.\n");
                                exit (0);
@@ -486,12 +447,12 @@ next_sequence:
                }
 #endif
                // load original image and convert their RGB components to double RGB array
-               rc = load_img(-1, &img_buffer, &load_w, &load_h, filename, index + z);
-               if (rc) {
+               img = load_img(&load_w, &load_h, filename, index + z);
+               if (!img) {
                        fprintf(stderr, "Failed to load grey image '%s'\n", filename);
                        return 0;
                }
-               scale_img(img_buffer, load_w, load_h, scale);
+               scale_img(img, load_w, load_h, scale);
                if (z == 0) {
                        w = load_w / scale;
                        h = load_h / scale;
@@ -517,20 +478,8 @@ next_sequence:
                        printf("failed to create marked image array\n");
                        exit (0);
                }
-               ptr = darrayGetPr(gI) + w*h*3*z;
-               img2array(img_buffer, w, h, ptr, w, h);
-#ifdef WITH_OPENCV
-               if (k > 1 && flow_enable) {
-                       if (!img_buffer_all)
-                               img_buffer_all = malloc(w*h*3*k*sizeof(unsigned short));
-                       if (!img_buffer_all) {
-                               printf("failed to create grey image array\n");
-                               exit (0);
-                       }
-                       memcpy(img_buffer_all + w*h*3*z, img_buffer, w*h*3*sizeof(unsigned short));
-               }
-#endif
-               free(img_buffer);
+               img2array_short(img, w, h, darrayGetPr(gI) + w*h*3*z, w, h);
+               free(img);
 
                if (sequence || !strcmp(argv[2], "marked")) {
                        char name[256];
@@ -552,7 +501,7 @@ next_sequence:
                        /* always load full unscaled image, then scale down */
                        if (load_marked(mark_buffer + w*h*z, load_w, load_h, name) == 0) {
                                scale_mark(mark_buffer + w*h*z, load_w, load_h, scale);
-                               ptr = darrayGetPr(cI) + w*h*3*z;
+                               ptr_cI = darrayGetPr(cI) + w*h*3*z;
                                for (y = 0; y < h; y++) {
                                        for (x = 0; x < w; x++) {
                                                /* do not apply mask on index 0 */
@@ -562,27 +511,30 @@ next_sequence:
                                                /* check for any brightness/contrast change */
                                                if (bright_contrast && (mark_palette[c-1].bright != 0 || mark_palette[c-1].contrast != 1))
                                                        change_bc = 1;
+                                               /* check for any alpha change */
+                                               if (alpha_change && mark_palette[c-1].alpha < 1)
+                                                       change_alpha = 1;
                                                /* do not apply white pixles, this meas: keep original color */
                                                if (mark_palette[c-1].r == 255 && mark_palette[c-1].g == 255 && mark_palette[c-1].b == 255)
                                                        continue;
-                                               ptr[y*w+x] = mark_palette[c-1].r / 255.0F;
-                                               ptr[y*w+x + w*h] = mark_palette[c-1].g / 255.0F;
-                                               ptr[y*w+x + w*h*2] = mark_palette[c-1].b / 255.0F;
+                                               ptr_cI[y*w+x] = mark_palette[c-1].r / 255.0F;
+                                               ptr_cI[y*w+x + w*h] = mark_palette[c-1].g / 255.0F;
+                                               ptr_cI[y*w+x + w*h*2] = mark_palette[c-1].b / 255.0F;
                                        }
                                }
                        } else
                                memset(mark_buffer + w*h*z, 0, w*h);
                } else {
                        // load marked image and convert their RGB components to double YUV array
-                       rc = load_img(-1, &img_buffer, &load_w, &load_h, argv[2], index + z);
-                       if (!rc) {
+                       img = load_img(&load_w, &load_h, argv[2], index + z);
+                       if (!img) {
+                               scale_img(img, load_w, load_h, scale);
                                if (load_w/scale != w || load_h/scale != h) {
                                        fprintf(stderr, "Error: All input images must have equal dimenstions.\n");
                                        return 0;
                                }
-                               ptr = darrayGetPr(cI) + w*h*3*z;
-                               img2array(img_buffer, w, h, ptr, w, h);
-                               free(img_buffer);
+                               img2array_short(img, w, h, darrayGetPr(cI) + w*h*3*z, w, h);
+                               free(img);
                        } else {
                                fprintf(stderr, "Failed to load marked image, omitting...\n");
                                memcpy(darrayGetPr(cI) + w*h*3*z, darrayGetPr(gI) + w*h*3*z, w*h*3 * sizeof(double));
@@ -590,37 +542,31 @@ next_sequence:
                }
        }
 
-       /* create color mask and ntsc arrays for the colorization process */
-       dims[0] = w; dims[1] = h; dims[2] = k;
-       markIm = darrayCreate(3, dims);
-       if (!markIm) {
-               printf("failed to create mark array\n");
-               exit (0);
-       }
-       features = (change_bc) ? 4 : 2;
-       dims[0] = w; dims[1] = h; dims[2] = features+1; dims[3] = k;
-       ntscIm = darrayCreate(4, dims);
-       if (!ntscIm) {
-               printf("failed to create ntsc array\n");
-               exit (0);
-       }
+       rc = alloc_I_arrays(&I, &mI, w, h, k, &features, feat_names, change_alpha, change_bc);
+       if (rc)
+               exit(0);
 
        for (z = 0; z < k; z++) {
+               set_I_ptr(I, mI, w, h, z, features, change_alpha, change_bc, &ptr_y, &ptr_u, &ptr_v, &ptr_a, &ptr_r, &ptr_b, &ptr_c, &ptr_m);
+               ptr_gI = darrayGetPr(gI) + w*h*3*z;
+               ptr_cI = darrayGetPr(cI) + w*h*3*z;
+
+               // convert original image into YUV
+               rgb2yuv(ptr_gI, ptr_gI, w, h);
+               // convert maked image into YUV
+               rgb2yuv(ptr_cI, ptr_cI, w, h);
+
                if (sequence || !strcmp(argv[2], "marked")) {
                        unsigned char c;
-                       ptr = darrayGetPr(markIm) + w*h*z;
                        // use marked mask to fill markIm
                        for (y = 0; y < h; y++) {
                                for (x = 0; x < w; x++) {
-                                       if (x < w && y < h) {
-                                               /* do not apply mask on index 0 */
-                                               c = mark_buffer[y*w+x + w*h*z];
-                                       } else
-                                               c = 0;
+                                       /* do not apply mask on index 0 */
+                                       c = mark_buffer[y*w+x + w*h*z];
                                        if (c)
-                                               ptr[y*w+x] = 1.0F;
+                                               ptr_m[y*w+x] = 1.0F;
                                        else
-                                               ptr[y*w+x] = 0.0F;
+                                               ptr_m[y*w+x] = 0.0F;
                                }
                        }
                } else {
@@ -629,100 +575,32 @@ next_sequence:
                        // - convert into absolute (positive values)
                        // - sum all components to get grey image
                        // - apply threshold (pixle is 1F, if the absolute difference is > 0.01F)
-                       // original code: markIm=(sum(abs(gI-cI),3)>0.01);
-                       ptr = darrayGetPr(gI) + w*h*3*z;
-                       ptr2 = darrayGetPr(cI) + w*h*3*z;
-                       ptr3 = darrayGetPr(markIm) + w*h*z;
+                       // original code: markIm=(sum(abs(gI-cI),3)>0.01); (according to developers of the algorithm)
                        for (i = 0, ii = w * h; i < ii; i++) {
                                diff = 0;
-                               sum = ptr[i] - ptr2[i];
+                               sum = ptr_gI[i] - ptr_cI[i];
                                if (sum < 0)
                                        diff -= sum;
                                else
                                        diff += sum;
-                               sum = ptr[i + ii] - ptr2[i + ii];
+                               sum = ptr_gI[i + ii] - ptr_cI[i + ii];
                                if (sum < 0)
                                        diff -= sum;
                                else
                                        diff += sum;
-                               sum = ptr[i + ii + ii] - ptr2[i + ii + ii];
+                               sum = ptr_gI[i + ii + ii] - ptr_cI[i + ii + ii];
                                if (sum < 0)
                                        diff -= sum;
                                else
                                        diff += sum;
                                if (diff > 0.01)
-                                       ptr3[i] = 1.0F;
+                                       ptr_m[i] = 1.0;
                                else
-                                       ptr3[i] = 0.0F;
+                                       ptr_m[i] = 0.0;
                        }
                }
 
-               // convert original image into YUV
-               ptr = darrayGetPr(gI) + w*h*3*z;
-               rgb2yuv(ptr, ptr, w, h);
-
-               // convert maked image into YUV
-               ptr = darrayGetPr(cI) + w*h*3*z;
-               rgb2yuv(ptr, ptr, w, h);
-
-               if (test != BC_ONLY) {
-                       if (sequence || !strcmp(argv[2], "marked")) {
-                               unsigned char c;
-                               // generate NTSC image: use luminance from original image and chrominance from original or marked image
-                               ptr = darrayGetPr(gI) + w*h*3*z;
-                               ptr2 = darrayGetPr(cI) + w*h*3*z;
-                               ptr3 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                               /* use original y component */
-                               memcpy(ptr3, ptr, w * h * sizeof(double));
-                               /* apply new uv components */
-                               for (y = 0; y < h; y++) {
-                                       for (x = 0; x < w; x++) {
-                                               c = mark_buffer[y*w+x + w*h*z];
-                                               if (c == 0) {
-                                                       ptr3[w * h + w * y + x] = ptr[w * h + w * y + x];
-                                                       ptr3[w * h * 2 + w * y + x] = ptr[w * h * 2 + w * y + x];
-                                               } else {
-                                                       ptr3[w * h + w * y + x] = ptr2[w * h + w * y + x];
-                                                       ptr3[w * h * 2 + w * y + x] = ptr2[w * h * 2 + w * y + x];
-                                               }
-                                       }
-                               }
-                       } else {
-                               // generate NTSC image: use luminance from original image and chrominance from maked image
-                               ptr = darrayGetPr(gI) + w*h*3*z;
-                               ptr2 = darrayGetPr(cI) + w*h*3*z;
-                               ptr3 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                               memcpy(ptr3, ptr, w * h * sizeof(double));
-                               memcpy(ptr3 + w * h, ptr2 + w * h, w * h * sizeof(double));
-                               memcpy(ptr3 + w * h * 2, ptr2 + w * h * 2, w * h * sizeof(double));
-                       }
-               } else {
-                       /* use grey image as result if BC_ONLY test is selected */
-                       ptr = darrayGetPr(gI) + w*h*3*z;
-                       ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       memcpy(ptr2, ptr, w * h * 3 * sizeof(double));
-               }
-
-               if (change_bc) {
-                       unsigned char c;
-                       ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       /* use original y component */
-                       memcpy(ptr2, ptr, w * h * sizeof(double));
-                       /* apply brightness and contrast from makred pixles to uv components of grey image */
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       /* use unchanged brightness and contrast on index 0 */
-                                       c = mark_buffer[y*w+x + w*h*z];
-                                       if (c == 0) {
-                                               ptr2[y*w+x + w*h*3] = 0;
-                                               ptr2[y*w+x + w*h*4] = 0.1;
-                                       } else {
-                                               ptr2[y*w+x + w*h*3] = mark_palette[c-1].bright / 10.0;
-                                               ptr2[y*w+x + w*h*4] = mark_palette[c-1].contrast / 10.0;
-                                       }
-                               }
-                       }
-               }
+               prepare_arrays(w, h, change_alpha, change_bc, mark_buffer+w*h*z, ptr_gI, ptr_cI, ptr_y, ptr_u, ptr_v, ptr_a, ptr_r, ptr_b, ptr_c, ptr_m, test);
        }
 
 #ifdef WITH_OPENCV
@@ -744,16 +622,14 @@ next_sequence:
                printf("Note: Optical flow is not activated!\n");
        for (z = 0; z < k-1; z++) {
                if (flow)
-                       create_flow_maps(NULL, img_buffer_all + w*h*3*(z+1), img_buffer_all + w*h*3*z, w, h, flow_window/scale, 0, NULL, NULL, darrayGetPr(flow) + w*h*z, darrayGetPr(flow) + w*h*z + w*h*(k-1), NULL);
+                       create_flow_maps(NULL, darrayGetPr(gI) + w*h*3*(z+1), darrayGetPr(gI) + w*h*3*z, w, h, flow_window/scale, 0, NULL, NULL, darrayGetPr(flow) + w*h*z, darrayGetPr(flow) + w*h*z + w*h*(k-1), NULL);
                if (flow_i)
-                       create_flow_maps(img_buffer_all + w*h*3*z, NULL, img_buffer_all + w*h*3*(z+1), w, h, flow_window/scale, 0, darrayGetPr(flow_i) + w*h*z, darrayGetPr(flow_i) + w*h*z + w*h*(k-1), NULL, NULL, NULL);
+                       create_flow_maps(darrayGetPr(gI) + w*h*3*z, NULL, darrayGetPr(gI) + w*h*3*(z+1), w, h, flow_window/scale, 0, darrayGetPr(flow_i) + w*h*z, darrayGetPr(flow_i) + w*h*z + w*h*(k-1), NULL, NULL, NULL);
        }
 #else
        if (k > 1)
                printf("Note: Optical flow is not compiled in!\n");
 #endif
-       free(img_buffer_all);
-       img_buffer_all = NULL;
 
        darrayDestroy(gI);
        gI = NULL;
@@ -762,7 +638,7 @@ next_sequence:
 
        if (test != FLOW_NEXT && test != FLOW_PREV && test != MARKED && test != MASK && test != MASK_COLOR && test != BC_ONLY && test != BC_IMAGE) {
                printf("Colorizing %d frames, please wait...\n", k);
-               rc = colorize(ntscIm, markIm, flow, flow_i, in_itr_num, out_itr_num, scalexyz);
+               rc = colorize(I, mI, flow, flow_i, in_itr_num, out_itr_num, quick, scalexyz, feat_names, NULL);
                if (rc < 0) {
                        if (k > 1)
                                printf("No memory! Use smaller frames or less frames between key frames or add more memory.");
@@ -772,152 +648,79 @@ next_sequence:
                }
        }
 
-       /* if we have a change, we apply brightness+contrast from ntscIm */
-       if (change_bc) {
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       /* apply contrast */
-                                       ptr2[w * y + x] = (ptr2[w * y + x] - 0.5) * ptr[w * h * 4 + w * y + x] * 10.0 + 0.5;
-                                       /* apply brightness */
-                                       ptr2[w * y + x] += ptr[w * h * 3 + w * y + x] * 10.0;
-                                       if (ptr2[w * y + x] < 0)
-                                               ptr2[w * y + x] = 0;
-                                       if (ptr2[w * y + x] > 1)
-                                               ptr2[w * y + x] = 1;
-#if 0
-#warning TEST: show brightness and contrast change as uv vectors on a grey array */
-ptr2[w * y + x] = 0.5;
-ptr2[w * h + w * y + x] = ptr[w * h + w * y + x] * 10;
-ptr2[w * h * 2 + w * y + x] = ptr[w * h * 2 + w * y + x] * 10 - 1;
-#endif
-                               }
-                       }
-               }
-       }
+       for (z = 0; z < k; z++) {
+               set_I_ptr(I, mI, w, h, z, features, change_alpha, change_bc, &ptr_y, &ptr_u, &ptr_v, &ptr_a, &ptr_r, &ptr_b, &ptr_c, &ptr_m);
+               postpare_arrays(w, h, change_alpha, change_bc, ptr_y, ptr_u, ptr_v, ptr_a, ptr_r, ptr_b, ptr_c, ptr_m, test);
 
 #ifdef WITH_OPENCV
-       if (test == FLOW_NEXT || test == FLOW_PREV) {
-               /* apply flow planes to result image as u and y vector */
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
+               if (test == FLOW_NEXT || test == FLOW_PREV) {
+                       double *ptr_f1 = NULL, *ptr_f2 = NULL;
+                       /* apply flow planes to result image as u and y vector */
                        if (test == FLOW_NEXT) {
-                               ptr2 = darrayGetPr(flow) + w*h*z;
-                               ptr3 = darrayGetPr(flow) + w*h*z*(k-1);
+                               if (flow) {
+                                       ptr_f1 = darrayGetPr(flow) + w*h*z;
+                                       ptr_f2 = darrayGetPr(flow) + w*h*z*(k-1);
+                               }
                        } else {
-                               ptr2 = darrayGetPr(flow_i) + w*h*z;
-                               ptr3 = darrayGetPr(flow_i) + w*h*z*(k-1);
+                               if (flow_i) {
+                                       ptr_f1 = darrayGetPr(flow_i) + w*h*z;
+                                       ptr_f2 = darrayGetPr(flow_i) + w*h*z*(k-1);
+                               }
                        }
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       ptr[w * y + x] = 0.5;
-                                       if (z < k-1) {
-                                               ptr[w * y + x + w*h] = ptr2[w * y + x] / 50;
-                                               ptr[w * y + x + w*h*2] = ptr3[w * y + x] / 50;
-                                       } else {
-                                               ptr[w * y + x + w*h] = 0;
-                                               ptr[w * y + x + w*h*2] = 0;
+                       if (ptr_f1 && ptr_f1) {
+                               for (y = 0; y < h; y++) {
+                                       for (x = 0; x < w; x++) {
+                                               ptr_y[w*y+x] = 0.5;
+                                               if (z < k-1) {
+                                                       ptr_u[w*y+x] = ptr_f1[w * y + x] / 50;
+                                                       ptr_v[w*y+x] = ptr_f2[w * y + x] / 50;
+                                               } else {
+                                                       ptr_u[w*y+x] = 0;
+                                                       ptr_v[w*y+x] = 0;
+                                               }
                                        }
                                }
                        }
                }
-       }
 #endif
 
-       if (test == MASK) {
-               /* apply maked mask as image */
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       ptr2 = darrayGetPr(markIm) + w*h*z;
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       ptr[w * y + x] = ptr2[w * y + x];
-                                       ptr[w * y + x + w*h] = ptr2[w * y + x];
-                                       ptr[w * y + x + w*h*2] = ptr2[w * y + x];
-                               }
-                       }
-               }
-       }
-
-       if (test == MASK_COLOR) {
-               /* apply maked mask on grey image */
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       ptr2 = darrayGetPr(markIm) + w*h*z;
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       /* darken unmarked areas, make maked areas with uniformed brightness */
-                                       if (ptr2[w * y + x] < 0.5F)
-                                               ptr[w * y + x] = ptr[w * y + x] / 4;
-                                       else
-                                               ptr[w * y + x] = 0.5F;
-                               }
-                       }
-               }
-       }
-
-       if (test == BC_IMAGE) {
-               /* apply bc image as result image */
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       /* use uniformed brightness as y component */
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       ptr[w * y + x] = 0.5F;
-                               }
-                       }
-                       if (change_bc) {
-                               ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                               memcpy(ptr+w*h, ptr2+w*h*3, w * h * sizeof(double));
-                               memcpy(ptr+w*h*2, ptr2+w*h*4, w * h * sizeof(double));
-                       } else {
-                               memset(ptr+w*h, 0, w * h * sizeof(double));
-                               memset(ptr+w*h*2, 0, w * h * sizeof(double));
-                       }
-               }
-       }
-
-       // save result YUV array to image with RGB components
-       img_buffer = (unsigned short *)malloc(w*h*3*sizeof(unsigned short));
-       if (!img_buffer) {
-               fprintf(stderr, "Failed to allocate image buffer\n");
-               return 0;
-       }
-       for (z = 0; z < k; z++) {
-               ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-               yuv2rgb(ptr, ptr, w, h);
-               array2img(ptr, w, h, img_buffer, w, h);
+               // save result YUV array to image with RGB components
+               yuv2rgb(ptr_y, ptr_y, w, h);
                if (sequence) {
                        static char name[256], *p, *q;
                        p = sequence[z].filename;
                        while((q = strchr(p, DIR_SEPERATOR)))
                                p = q + 1;
-                       strcpy(name, sequence[z].filename);
-                       name[p - sequence[z].filename] = '\0';
-                       strcat(name, "colorized_");
+                       if (output_prefix[0] == '\0') {
+                               strcpy(name, sequence[z].filename);
+                               name[p - sequence[z].filename] = '\0';
+                               strcat(name, "colorized_");
+                       } else {
+                               strcpy(name, output_prefix);
+                       }
                        strcat(name, p);
                        filename = name;
                } else
                        filename = argv[3];
-               save_img(img_buffer, w, h, filename, index + z);
+               /* don't save alpha on these tests */
+               if (test == ALPHA || test == REMOVAL_IMAGE || test == NO_ALPHA)
+                       save_img_array(ptr_y, w, h, 0, filename, index + z);
+               else
+                       save_img_array(ptr_y, w, h, change_alpha, filename, index + z);
        }
-       free(img_buffer);
 
        time(&end);
        printf("Elapsed time: %d minutes, %d seconds\n", (int)(end-start)/60, (int)(end-start)%60);
 
        // destroy
-       darrayDestroy(ntscIm);
-       ntscIm = NULL;
+       darrayDestroy(I);
+       I = NULL;
+       darrayDestroy(mI);
+       mI = NULL;
        darrayDestroy(flow);
        flow = NULL;
        darrayDestroy(flow_i);
        flow_i = NULL;
-       darrayDestroy(markIm);
-       markIm = NULL;
 
        free(mark_buffer);
        mark_buffer = NULL;